diff options
77 files changed, 1497 insertions, 1234 deletions
diff --git a/build.sh b/build.sh index 139c28359..139c28359 100755..100644 --- a/build.sh +++ b/build.sh diff --git a/compiler/ast.nim b/compiler/ast.nim index ab315877a..660f3e45e 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -257,7 +257,7 @@ type sfThread, # proc will run as a thread # variable is a thread variable sfCompileTime, # proc can be evaluated at compile time - sfMerge, # proc can be merged with itself + sfConstructor, # proc is a C++ constructor sfDeadCodeElim, # dead code elimination for the module is turned on sfBorrow, # proc is borrowed sfInfixCall, # symbol needs infix call syntax in target language; @@ -663,7 +663,9 @@ type locOther # location is something other TLocFlag* = enum lfIndirect, # backend introduced a pointer - lfParamCopy, # backend introduced a parameter copy (LLVM) + lfFullExternalName, # only used when 'gCmd == cmdPretty': Indicates + # that the symbol has been imported via 'importc: "fullname"' and + # no format string. lfNoDeepCopy, # no need for a deep copy lfNoDecl, # do not declare it in C lfDynamicLib, # link symbol to dynamic library @@ -915,9 +917,7 @@ const skIterators* = {skIterator, skClosureIterator} - lfFullExternalName* = lfParamCopy # \ - # only used when 'gCmd == cmdPretty': Indicates that the symbol has been - # imported via 'importc: "fullname"' and no format string. +var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things proc isCallExpr*(n: PNode): bool = result = n.kind in nkCallKinds @@ -1333,8 +1333,12 @@ proc propagateToOwner*(owner, elem: PType) = if elem.isMetaType: owner.flags.incl tfHasMeta - if owner.kind != tyProc: - if elem.isGCedMem or tfHasGCedMem in elem.flags: + if owner.kind notin {tyProc, tyGenericInst, tyGenericBody, + tyGenericInvocation}: + let elemB = elem.skipTypes({tyGenericInst}) + if elemB.isGCedMem or tfHasGCedMem in elemB.flags: + # for simplicity, we propagate this flag even to generics. We then + # ensure this doesn't bite us in sempass2. owner.flags.incl tfHasGCedMem proc rawAddSon*(father, son: PType) = diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 86f300aa0..91dcaef42 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -412,7 +412,8 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) = else: var pl: PRope = nil #var param = typ.n.sons[1].sym - app(pl, genThisArg(p, ri, 1, typ)) + if 1 < ri.len: + app(pl, genThisArg(p, ri, 1, typ)) app(pl, op.r) var params: PRope for i in countup(2, length - 1): diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index a4938c9ac..441ceb22a 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -33,7 +33,7 @@ proc isAssignedImmediately(n: PNode): bool {.inline.} = return false result = true -proc genVarTuple(p: BProc, n: PNode) = +proc genVarTuple(p: BProc, n: PNode) = var tup, field: TLoc if n.kind != nkVarTuple: internalError(n.info, "genVarTuple") var L = sonsLen(n) @@ -49,7 +49,7 @@ proc genVarTuple(p: BProc, n: PNode) = genLineDir(p, n) initLocExpr(p, n.sons[L-1], tup) var t = tup.t.getUniqueType - for i in countup(0, L-3): + for i in countup(0, L-3): var v = n.sons[i].sym if sfCompileTime in v.flags: continue if sfGlobal in v.flags: @@ -60,11 +60,11 @@ proc genVarTuple(p: BProc, n: PNode) = assignLocalVar(p, v) initLocalVar(p, v, immediateAsgn=isAssignedImmediately(n[L-1])) initLoc(field, locExpr, t.sons[i], tup.s) - if t.kind == tyTuple: + if t.kind == tyTuple: field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)]) - else: + else: if t.n.sons[i].kind != nkSym: internalError(n.info, "genVarTuple") - field.r = ropef("$1.$2", + field.r = ropef("$1.$2", [rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)]) putLocIntoDest(p, v.loc, field) @@ -117,7 +117,7 @@ proc endBlock(p: BProc, blockEnd: PRope) = line(p, cpsStmts, blockEnd) proc endBlock(p: BProc) = - let topBlock = p.blocks.len - 1 + let topBlock = p.blocks.len - 1 var blockEnd = if p.blocks[topBlock].label != nil: rfmt(nil, "} $1: ;$n", p.blocks[topBlock].label) else: @@ -190,10 +190,10 @@ proc genSingleVar(p: BProc, a: PNode) = targetProc = p.module.preInitProc assignGlobalVar(targetProc, v) # XXX: be careful here. - # Global variables should not be zeromem-ed within loops + # Global variables should not be zeromem-ed within loops # (see bug #20). # That's why we are doing the construction inside the preInitProc. - # genObjectInit relies on the C runtime's guarantees that + # genObjectInit relies on the C runtime's guarantees that # global variables will be initialized to zero. genObjectInit(p.module.preInitProc, cpsInit, v.typ, v.loc, true) # Alternative construction using default constructor (which may zeromem): @@ -202,7 +202,8 @@ proc genSingleVar(p: BProc, a: PNode) = genVarPrototypeAux(generatedHeader, v) registerGcRoot(p, v) else: - let imm = isAssignedImmediately(a.sons[2]) + let value = a.sons[2] + let imm = isAssignedImmediately(value) if imm and p.module.compileToCpp and p.splitDecls == 0 and not containsHiddenPointer(v.typ): # C++ really doesn't like things like 'Foo f; f = x' as that invokes a @@ -211,8 +212,19 @@ proc genSingleVar(p: BProc, a: PNode) = genLineDir(p, a) let decl = localVarDecl(p, v) var tmp: TLoc - initLocExprSingleUse(p, a.sons[2], tmp) - lineF(p, cpsStmts, "$# = $#;$n", decl, tmp.rdLoc) + if value.kind in nkCallKinds and value[0].kind == nkSym and + sfConstructor in value[0].sym.flags: + var params: PRope + let typ = skipTypes(value.sons[0].typ, abstractInst) + assert(typ.kind == tyProc) + for i in 1.. <value.len: + if params != nil: params.app(~", ") + assert(sonsLen(typ) == sonsLen(typ.n)) + app(params, genOtherArg(p, value, i, typ)) + lineF(p, cpsStmts, "$#($#);$n", decl, params) + else: + initLocExprSingleUse(p, value, tmp) + lineF(p, cpsStmts, "$# = $#;$n", decl, tmp.rdLoc) return assignLocalVar(p, v) initLocalVar(p, v, imm) @@ -229,10 +241,10 @@ proc genClosureVar(p: BProc, a: PNode) = genLineDir(p, a) loadInto(p, a.sons[0], a.sons[2], v) -proc genVarStmt(p: BProc, n: PNode) = - for i in countup(0, sonsLen(n) - 1): +proc genVarStmt(p: BProc, n: PNode) = + for i in countup(0, sonsLen(n) - 1): var a = n.sons[i] - if a.kind == nkCommentStmt: continue + if a.kind == nkCommentStmt: continue if a.kind == nkIdentDefs: # can be a lifted var nowadays ... if a.sons[0].kind == nkSym: @@ -242,12 +254,12 @@ proc genVarStmt(p: BProc, n: PNode) = else: genVarTuple(p, a) -proc genConstStmt(p: BProc, t: PNode) = - for i in countup(0, sonsLen(t) - 1): +proc genConstStmt(p: BProc, t: PNode) = + for i in countup(0, sonsLen(t) - 1): var it = t.sons[i] - if it.kind == nkCommentStmt: continue + if it.kind == nkCommentStmt: continue if it.kind != nkConstDef: internalError(t.info, "genConstStmt") - var c = it.sons[0].sym + var c = it.sons[0].sym if c.typ.containsCompileTimeOnly: continue if sfFakeConst in c.flags: genSingleVar(p, it) @@ -274,9 +286,9 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) = getTemp(p, n.typ, d) genLineDir(p, n) let lend = getLabel(p) - for i in countup(0, sonsLen(n) - 1): + for i in countup(0, sonsLen(n) - 1): let it = n.sons[i] - if it.len == 2: + if it.len == 2: when newScopeForIf: startBlock(p) initLocExprSingleUse(p, it.sons[0], a) lelse = getLabel(p) @@ -303,13 +315,13 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) = if sonsLen(n) > 1: fixLabel(p, lend) -proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = +proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = # Called by return and break stmts. # Deals with issues faced when jumping out of try/except/finally stmts, var stack: seq[PNode] newSeq(stack, 0) - + var alreadyPoppedCnt = p.inExceptBlock for i in countup(1, howManyTrys): if not p.module.compileToCpp: @@ -327,11 +339,11 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = # Find finally-stmt for this try-stmt # and generate a copy of its sons var finallyStmt = lastSon(tryStmt) - if finallyStmt.kind == nkFinally: + if finallyStmt.kind == nkFinally: genStmts(p, finallyStmt.sons[0]) # push old elements again: - for i in countdown(howManyTrys-1, 0): + for i in countdown(howManyTrys-1, 0): p.nestedTryStmts.add(stack[i]) if not p.module.compileToCpp: @@ -344,14 +356,14 @@ proc genReturnStmt(p: BProc, t: PNode) = p.beforeRetNeeded = true genLineDir(p, t) if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0]) - blockLeaveActions(p, + blockLeaveActions(p, howManyTrys = p.nestedTryStmts.len, howManyExcepts = p.inExceptBlock) if (p.finallySafePoints.len > 0): # If we're in a finally block, and we came here by exception # consume it before we return. var safePoint = p.finallySafePoints[p.finallySafePoints.len-1] - linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint) + linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint) lineF(p, cpsStmts, "goto BeforeRet;$n", []) proc genComputedGoto(p: BProc; n: PNode) = @@ -387,7 +399,7 @@ proc genComputedGoto(p: BProc; n: PNode) = let topBlock = p.blocks.len-1 let oldBody = p.blocks[topBlock].sections[cpsStmts] p.blocks[topBlock].sections[cpsStmts] = nil - + for j in casePos+1 .. <n.len: genStmts(p, n.sons[j]) let tailB = p.blocks[topBlock].sections[cpsStmts] @@ -402,7 +414,7 @@ proc genComputedGoto(p: BProc; n: PNode) = initLocExpr(p, caseStmt.sons[0], a) # first goto: lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc) - + for i in 1 .. <caseStmt.len: startBlock(p) let it = caseStmt.sons[i] @@ -426,7 +438,7 @@ proc genComputedGoto(p: BProc; n: PNode) = proc genWhileStmt(p: BProc, t: PNode) = # we don't generate labels here as for example GCC would produce # significantly worse code - var + var a: TLoc labl: TLabel assert(sonsLen(t) == 2) @@ -437,7 +449,7 @@ proc genWhileStmt(p: BProc, t: PNode) = p.breakIdx = startBlock(p, "while (1) {$n") p.blocks[p.breakIdx].isLoop = true initLocExpr(p, t.sons[0], a) - if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0): + if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0): let label = assignLabel(p.blocks[p.breakIdx]) lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label]) var loopBody = t.sons[1] @@ -483,23 +495,23 @@ proc genParForStmt(p: BProc, t: PNode) = let call = t.sons[1] initLocExpr(p, call.sons[1], rangeA) initLocExpr(p, call.sons[2], rangeB) - + lineF(p, cpsStmts, "#pragma omp parallel for $4$n" & - "for ($1 = $2; $1 <= $3; ++$1)", + "for ($1 = $2; $1 <= $3; ++$1)", forLoopVar.loc.rdLoc, rangeA.rdLoc, rangeB.rdLoc, call.sons[3].getStr.toRope) - + p.breakIdx = startBlock(p) p.blocks[p.breakIdx].isLoop = true genStmts(p, t.sons[2]) endBlock(p) dec(p.withinLoop) - -proc genBreakStmt(p: BProc, t: PNode) = + +proc genBreakStmt(p: BProc, t: PNode) = var idx = p.breakIdx - if t.sons[0].kind != nkEmpty: + if t.sons[0].kind != nkEmpty: # named break? assert(t.sons[0].kind == nkSym) var sym = t.sons[0].sym @@ -511,13 +523,13 @@ proc genBreakStmt(p: BProc, t: PNode) = if idx < 0 or not p.blocks[idx].isLoop: internalError(t.info, "no loop to break") let label = assignLabel(p.blocks[idx]) - blockLeaveActions(p, + blockLeaveActions(p, p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts, p.inExceptBlock - p.blocks[idx].nestedExceptStmts) genLineDir(p, t) lineF(p, cpsStmts, "goto $1;$n", [label]) -proc getRaiseFrmt(p: BProc): string = +proc getRaiseFrmt(p: BProc): string = if p.module.compileToCpp: result = "throw NimException($1, $2);$n" elif getCompilerProc("Exception") != nil: @@ -532,7 +544,7 @@ proc genRaiseStmt(p: BProc, t: PNode) = var finallyBlock = p.nestedTryStmts[p.nestedTryStmts.len - 1].lastSon if finallyBlock.kind == nkFinally: genSimpleBlock(p, finallyBlock.sons[0]) - if t.sons[0].kind != nkEmpty: + if t.sons[0].kind != nkEmpty: var a: TLoc initLocExpr(p, t.sons[0], a) var e = rdLoc(a) @@ -547,23 +559,23 @@ proc genRaiseStmt(p: BProc, t: PNode) = else: linefmt(p, cpsStmts, "#reraiseException();$n") -proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc, - rangeFormat, eqFormat: TFormatStr, labl: TLabel) = - var +proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc, + rangeFormat, eqFormat: TFormatStr, labl: TLabel) = + var x, y: TLoc var length = sonsLen(b) - for i in countup(0, length - 2): - if b.sons[i].kind == nkRange: + for i in countup(0, length - 2): + if b.sons[i].kind == nkRange: initLocExpr(p, b.sons[i].sons[0], x) initLocExpr(p, b.sons[i].sons[1], y) - lineCg(p, cpsStmts, rangeFormat, + lineCg(p, cpsStmts, rangeFormat, [rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl]) - else: + else: initLocExpr(p, b.sons[i], x) lineCg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl]) -proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc, - labId, until: int): TLabel = +proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc, + labId, until: int): TLabel = var lend = getLabel(p) for i in 1..until: lineF(p, cpsStmts, "LA$1: ;$n", [toRope(labId + i)]) @@ -596,23 +608,23 @@ proc genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc, else: result = genCaseSecondPass(p, t, d, labId, until) -proc genCaseGeneric(p: BProc, t: PNode, d: var TLoc, - rangeFormat, eqFormat: TFormatStr) = +proc genCaseGeneric(p: BProc, t: PNode, d: var TLoc, + rangeFormat, eqFormat: TFormatStr) = var a: TLoc initLocExpr(p, t.sons[0], a) var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, sonsLen(t)-1, a) fixLabel(p, lend) -proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel, - branches: var openArray[PRope]) = +proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel, + branches: var openArray[PRope]) = var x: TLoc var length = sonsLen(b) - for i in countup(0, length - 2): + 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}) var j = int(hashString(b.sons[i].strVal) and high(branches)) - appcg(p.module, branches[j], "if (#eqStrings($1, $2)) goto $3;$n", + appcg(p.module, branches[j], "if (#eqStrings($1, $2)) goto $3;$n", [rdLoc(e), rdLoc(x), labl]) proc genStringCase(p: BProc, t: PNode, d: var TLoc) = @@ -627,35 +639,35 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) = var a: TLoc initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto: var labId = p.labels - for i in countup(1, sonsLen(t) - 1): + for i in countup(1, sonsLen(t) - 1): inc(p.labels) - if t.sons[i].kind == nkOfBranch: - genCaseStringBranch(p, t.sons[i], a, con("LA", toRope(p.labels)), + if t.sons[i].kind == nkOfBranch: + genCaseStringBranch(p, t.sons[i], a, con("LA", toRope(p.labels)), branches) - else: + else: # else statement: nothing to do yet # but we reserved a label, which we use later discard - linefmt(p, cpsStmts, "switch (#hashString($1) & $2) {$n", + linefmt(p, cpsStmts, "switch (#hashString($1) & $2) {$n", rdLoc(a), toRope(bitMask)) for j in countup(0, high(branches)): if branches[j] != nil: - lineF(p, cpsStmts, "case $1: $n$2break;$n", + lineF(p, cpsStmts, "case $1: $n$2break;$n", [intLiteral(j), branches[j]]) lineF(p, cpsStmts, "}$n") # else statement: - if t.sons[sonsLen(t)-1].kind != nkOfBranch: - lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)]) + if t.sons[sonsLen(t)-1].kind != nkOfBranch: + lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)]) # third pass: generate statements var lend = genCaseSecondPass(p, t, d, labId, sonsLen(t)-1) fixLabel(p, lend) else: genCaseGeneric(p, t, d, "", "if (#eqStrings($1, $2)) goto $3;$n") - -proc branchHasTooBigRange(b: PNode): bool = - for i in countup(0, sonsLen(b)-2): + +proc branchHasTooBigRange(b: PNode): bool = + 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: + b.sons[i].sons[1].intVal - b.sons[i].sons[0].intVal > RangeExpandLimit: return true proc ifSwitchSplitPoint(p: BProc, n: PNode): int = @@ -664,21 +676,21 @@ proc ifSwitchSplitPoint(p: BProc, n: PNode): int = var stmtBlock = lastSon(branch) if stmtBlock.stmtsContainPragma(wLinearScanEnd): result = i - elif hasSwitchRange notin CC[cCompiler].props: - if branch.kind == nkOfBranch and branchHasTooBigRange(branch): + elif hasSwitchRange notin CC[cCompiler].props: + if branch.kind == nkOfBranch and branchHasTooBigRange(branch): result = i proc genCaseRange(p: BProc, branch: PNode) = var length = branch.len - for j in 0 .. length-2: - if branch[j].kind == nkRange: - if hasSwitchRange in CC[cCompiler].props: + for j in 0 .. length-2: + if branch[j].kind == nkRange: + if hasSwitchRange in CC[cCompiler].props: lineF(p, cpsStmts, "case $1 ... $2:$n", [ - genLiteral(p, branch[j][0]), + genLiteral(p, branch[j][0]), genLiteral(p, branch[j][1])]) - else: + else: var v = copyNode(branch[j][0]) - while v.intVal <= branch[j][1].intVal: + while v.intVal <= branch[j][1].intVal: lineF(p, cpsStmts, "case $1:$n", [genLiteral(p, v)]) inc(v.intVal) else: @@ -687,53 +699,53 @@ proc genCaseRange(p: BProc, branch: PNode) = proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) = # 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, d, rangeFormat = "if ($1 >= $2 && $1 <= $3) goto $4;$n", - eqFormat = "if ($1 == $2) goto $3;$n", + eqFormat = "if ($1 == $2) goto $3;$n", splitPoint, a) else: nil - + # generate switch part (might be empty): if splitPoint+1 < n.len: lineF(p, cpsStmts, "switch ($1) {$n", [rdCharLoc(a)]) var hasDefault = false - for i in splitPoint+1 .. < n.len: + for i in splitPoint+1 .. < n.len: var branch = n[i] - if branch.kind == nkOfBranch: + if branch.kind == nkOfBranch: genCaseRange(p, branch) - else: + else: # else part of case statement: lineF(p, cpsStmts, "default:$n") hasDefault = true exprBlock(p, branch.lastSon, d) lineF(p, cpsStmts, "break;$n") - if (hasAssume in CC[cCompiler].props) and not hasDefault: + if (hasAssume in CC[cCompiler].props) and not hasDefault: lineF(p, cpsStmts, "default: __assume(0);$n") lineF(p, cpsStmts, "}$n") if lend != nil: fixLabel(p, lend) - -proc genCase(p: BProc, t: PNode, d: var TLoc) = + +proc genCase(p: BProc, t: PNode, d: var TLoc) = genLineDir(p, t) if not isEmptyType(t.typ) and d.k == locNone: getTemp(p, t.typ, d) case skipTypes(t.sons[0].typ, abstractVarRange).kind of tyString: genStringCase(p, t, d) - of tyFloat..tyFloat128: - genCaseGeneric(p, t, d, "if ($1 >= $2 && $1 <= $3) goto $4;$n", + of tyFloat..tyFloat128: + genCaseGeneric(p, t, d, "if ($1 >= $2 && $1 <= $3) goto $4;$n", "if ($1 == $2) goto $3;$n") else: genOrdinalCase(p, t, d) - -proc hasGeneralExceptSection(t: PNode): bool = + +proc hasGeneralExceptSection(t: PNode): bool = var length = sonsLen(t) var i = 1 - while (i < length) and (t.sons[i].kind == nkExceptBranch): + while (i < length) and (t.sons[i].kind == nkExceptBranch): var blen = sonsLen(t.sons[i]) - if blen == 1: + if blen == 1: return true inc(i) result = false @@ -798,7 +810,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = lineF(p, cpsStmts, "if ($1) ", [orExpr]) exprBlock(p, t.sons[i].sons[blen-1], d) inc(i) - + # reraise the exception if there was no catch all # and none of the handlers matched if not catchAllPresent: @@ -811,15 +823,15 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = line(p, cpsStmts, ~"throw;$n") endBlock(p) - + lineF(p, cpsStmts, "}$n") # end of catch block dec p.inExceptBlock - + discard pop(p.nestedTryStmts) if (i < length) and (t.sons[i].kind == nkFinally): genSimpleBlock(p, t.sons[i].sons[0]) - -proc genTry(p: BProc, t: PNode, d: var TLoc) = + +proc genTry(p: BProc, t: PNode, d: var TLoc) = # code to generate: # # XXX: There should be a standard dispatch algorithm @@ -841,7 +853,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) = # clearException(); # } # } - # { + # { # /* finally: */ # printf('fin!\n'); # } @@ -927,14 +939,14 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): PRope = res.add(rdLoc(a).ropeToStr) else: var r = sym.loc.r - if r == nil: + if r == nil: # if no name has already been given, # it doesn't matter much: r = mangleName(sym) sym.loc.r = r # but be consequent! res.add(r.ropeToStr) else: internalError(t.sons[i].info, "genAsmOrEmitStmt()") - + if isAsmStmt and hasGnuAsm in CC[cCompiler].props: for x in splitLines(res): var j = 0 @@ -952,40 +964,43 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): PRope = res.add(tnl) result = res.toRope -proc genAsmStmt(p: BProc, t: PNode) = +proc genAsmStmt(p: BProc, t: PNode) = assert(t.kind == nkAsmStmt) genLineDir(p, t) var s = genAsmOrEmitStmt(p, t, isAsmStmt=true) + # see bug #2362, "top level asm statements" seem to be a mis-feature + # but even if we don't do this, the example in #2362 cannot possibly + # work: if p.prc == nil: # top level asm statement? appf(p.module.s[cfsProcHeaders], CC[cCompiler].asmStmtFrmt, [s]) else: lineF(p, cpsStmts, CC[cCompiler].asmStmtFrmt, [s]) -proc genEmit(p: BProc, t: PNode) = +proc genEmit(p: BProc, t: PNode) = genLineDir(p, t) var s = genAsmOrEmitStmt(p, t.sons[1]) - if p.prc == nil: + if p.prc == nil: # top level emit pragma? app(p.module.s[cfsProcHeaders], s) else: line(p, cpsStmts, s) -var +var breakPointId: int = 0 gBreakpoints: PRope # later the breakpoints are inserted into the main proc -proc genBreakPoint(p: BProc, t: PNode) = +proc genBreakPoint(p: BProc, t: PNode) = var name: string if optEndb in p.options: - if t.kind == nkExprColonExpr: + if t.kind == nkExprColonExpr: assert(t.sons[1].kind in {nkStrLit..nkTripleStrLit}) name = normalize(t.sons[1].strVal) - else: + else: inc(breakPointId) name = "bp" & $breakPointId genLineDir(p, t) # BUGFIX - appcg(p.module, gBreakpoints, + appcg(p.module, gBreakpoints, "#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [ toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)), makeCString(name)]) @@ -1006,14 +1021,14 @@ proc genPragma(p: BProc, n: PNode) = of wEmit: genEmit(p, it) of wBreakpoint: genBreakPoint(p, it) of wWatchPoint: genWatchpoint(p, it) - of wInjectStmt: + of wInjectStmt: var p = newProc(nil, p.module) p.options = p.options - {optLineTrace, optStackTrace} genStmts(p, it.sons[1]) p.module.injectStmt = p.s(cpsStmts) else: discard -proc fieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool = +proc fieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool = if optFieldCheck in p.options: var le = asgn.sons[0] if le.kind == nkCheckedFieldExpr: @@ -1021,23 +1036,23 @@ proc fieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool = result = sfDiscriminant in field.flags elif le.kind == nkDotExpr: var field = le.sons[1].sym - result = sfDiscriminant in field.flags + result = sfDiscriminant in field.flags -proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType, - field: PSym) = +proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType, + field: PSym) = var t = skipTypes(objtype, abstractVar) assert t.kind == tyObject discard genTypeInfo(p.module, t) var L = lengthOrd(field.typ) if not containsOrIncl(p.module.declaredThings, field.id): - appcg(p.module, cfsVars, "extern $1", + appcg(p.module, cfsVars, "extern $1", discriminatorTableDecl(p.module, t, field)) lineCg(p, cpsStmts, "#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n", [rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field), intLiteral(L+1)]) -proc asgnFieldDiscriminant(p: BProc, e: PNode) = +proc asgnFieldDiscriminant(p: BProc, e: PNode) = var a, tmp: TLoc var dotExpr = e.sons[0] var d: PSym @@ -1047,8 +1062,8 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) = expr(p, e.sons[1], tmp) genDiscriminantCheck(p, a, tmp, dotExpr.sons[0].typ, dotExpr.sons[1].sym) genAssignment(p, a, tmp, {}) - -proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) = + +proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) = genLineDir(p, e) if not fieldDiscriminantCheckNeeded(p, e): var a: TLoc @@ -1059,7 +1074,7 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) = else: asgnFieldDiscriminant(p, e) -proc genStmts(p: BProc, t: PNode) = +proc genStmts(p: BProc, t: PNode) = var a: TLoc expr(p, t, a) internalAssert a.k in {locNone, locTemp, locLocalVar} diff --git a/compiler/cgen.nim b/compiler/cgen.nim index cc376d87a..0b0526b65 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -9,7 +9,7 @@ ## This module implements the C code generator. -import +import ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options, intsets, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, @@ -25,7 +25,7 @@ when options.hasTinyCBackend: var generatedHeader: BModule -proc addForwardedProc(m: BModule, prc: PSym) = +proc addForwardedProc(m: BModule, prc: PSym) = m.forwardedProcs.add(prc) inc(gForwardedProcsCounter) @@ -33,7 +33,7 @@ proc getCgenModule(s: PSym): BModule = result = if s.position >= 0 and s.position < gModules.len: gModules[s.position] else: nil -proc findPendingModule(m: BModule, s: PSym): BModule = +proc findPendingModule(m: BModule, s: PSym): BModule = var ms = getModule(s) result = gModules[ms.position] @@ -41,21 +41,21 @@ proc emitLazily(s: PSym): bool {.inline.} = result = optDeadCodeElim in gGlobalOptions or sfDeadCodeElim in getModule(s).flags -proc initLoc(result: var TLoc, k: TLocKind, typ: PType, s: TStorageLoc) = +proc initLoc(result: var TLoc, k: TLocKind, typ: PType, s: TStorageLoc) = result.k = k result.s = s result.t = typ result.r = nil result.flags = {} -proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: PRope, s: TStorageLoc) = +proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: PRope, s: TStorageLoc) = # fills the loc if it is not already initialized - if a.k == locNone: + if a.k == locNone: a.k = k a.t = typ a.s = s if a.r == nil: a.r = r - + proc isSimpleConst(typ: PType): bool = let t = skipTypes(typ, abstractVar) result = t.kind notin @@ -67,43 +67,43 @@ proc useStringh(m: BModule) = m.includesStringh = true discard lists.includeStr(m.headerFiles, "<string.h>") -proc useHeader(m: BModule, sym: PSym) = - if lfHeader in sym.loc.flags: +proc useHeader(m: BModule, sym: PSym) = + if lfHeader in sym.loc.flags: assert(sym.annex != nil) discard lists.includeStr(m.headerFiles, getStr(sym.annex.path)) proc cgsym(m: BModule, name: string): PRope -proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope = +proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope = var i = 0 var length = len(frmt) result = nil var num = 0 - while i < length: - if frmt[i] == '$': + while i < length: + if frmt[i] == '$': inc(i) # skip '$' case frmt[i] - of '$': + of '$': app(result, "$") inc(i) - of '#': + of '#': inc(i) app(result, args[num]) inc(num) - of '0'..'9': + of '0'..'9': var j = 0 - while true: + while true: j = (j * 10) + ord(frmt[i]) - ord('0') inc(i) - if i >= length or not (frmt[i] in {'0'..'9'}): break + if i >= length or not (frmt[i] in {'0'..'9'}): break num = j - if j > high(args) + 1: + if j > high(args) + 1: internalError("ropes: invalid format string $" & $j) app(result, args[j-1]) of 'n': if optLineDir notin gOptions: app(result, rnl) inc(i) - of 'N': + of 'N': app(result, rnl) inc(i) else: internalError("ropes: invalid format string $" & frmt[i]) @@ -117,37 +117,37 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope = elif frmt[i] == '#' and frmt[i+1] == '$': inc(i, 2) var j = 0 - while frmt[i] in Digits: + while frmt[i] in Digits: j = (j * 10) + ord(frmt[i]) - ord('0') inc(i) app(result, cgsym(m, args[j-1].ropeToStr)) var start = i - while i < length: + while i < length: if frmt[i] != '$' and frmt[i] != '#': inc(i) - else: break - if i - 1 >= start: + else: break + if i - 1 >= start: app(result, substr(frmt, start, i - 1)) template rfmt(m: BModule, fmt: string, args: varargs[PRope]): expr = ropecg(m, fmt, args) -proc appcg(m: BModule, c: var PRope, frmt: TFormatStr, - args: varargs[PRope]) = +proc appcg(m: BModule, c: var PRope, frmt: TFormatStr, + args: varargs[PRope]) = app(c, ropecg(m, frmt, args)) -proc appcg(m: BModule, s: TCFileSection, frmt: TFormatStr, - args: varargs[PRope]) = +proc appcg(m: BModule, s: TCFileSection, frmt: TFormatStr, + args: varargs[PRope]) = app(m.s[s], ropecg(m, frmt, args)) -proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr, - args: varargs[PRope]) = +proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr, + args: varargs[PRope]) = app(p.s(s), ropecg(p.module, frmt, args)) var indent = "\t".toRope proc indentLine(p: BProc, r: PRope): PRope = result = r for i in countup(0, p.blocks.len-1): prepend(result, indent) - + proc line(p: BProc, s: TCProcSection, r: PRope) = app(p.s(s), indentLine(p, r)) @@ -180,7 +180,7 @@ proc genCLineDir(r: var PRope, filename: string, line: int) = appf(r, "$N#line $2 $1$N", [toRope(makeSingleLineCString(filename)), toRope(line)]) -proc genCLineDir(r: var PRope, info: TLineInfo) = +proc genCLineDir(r: var PRope, info: TLineInfo) = genCLineDir(r, info.toFullPath, info.safeLineNm) proc genLineDir(p: BProc, t: PNode) = @@ -261,7 +261,9 @@ proc isComplexValueType(t: PType): bool {.inline.} = proc resetLoc(p: BProc, loc: var TLoc) = let containsGcRef = containsGarbageCollectedRef(loc.t) - if not isComplexValueType(skipTypes(loc.t, abstractVarRange)): + let typ = skipTypes(loc.t, abstractVarRange) + if isImportedCppType(typ): return + if not isComplexValueType(typ): if containsGcRef: var nilLoc: TLoc initLoc(nilLoc, locTemp, loc.t, OnStack) @@ -282,35 +284,37 @@ proc resetLoc(p: BProc, loc: var TLoc) = useStringh(p.module) linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n", addrLoc(loc), rdLoc(loc)) - # XXX: We can be extra clever here and call memset only + # XXX: We can be extra clever here and call memset only # on the bytes following the m_type field? genObjectInit(p, cpsStmts, loc.t, loc, true) proc constructLoc(p: BProc, loc: TLoc, isTemp = false) = - if not isComplexValueType(skipTypes(loc.t, abstractRange)): + let typ = skipTypes(loc.t, abstractRange) + if not isComplexValueType(typ): linefmt(p, cpsStmts, "$1 = 0;$n", rdLoc(loc)) else: if not isTemp or containsGarbageCollectedRef(loc.t): # don't use memset for temporary values for performance if we can # avoid it: - useStringh(p.module) - linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n", - addrLoc(loc), rdLoc(loc)) + if not isImportedCppType(typ): + useStringh(p.module) + linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n", + addrLoc(loc), rdLoc(loc)) genObjectInit(p, cpsStmts, loc.t, loc, true) proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) = if sfNoInit notin v.flags: # we know it is a local variable and thus on the stack! # If ``not immediateAsgn`` it is not initialized in a binding like - # ``var v = X`` and thus we need to init it. + # ``var v = X`` and thus we need to init it. # If ``v`` contains a GC-ref we may pass it to ``unsureAsgnRef`` somehow # which requires initialization. However this can really only happen if - # ``var v = X()`` gets transformed into ``X(&v)``. + # ``var v = X()`` gets transformed into ``X(&v)``. # Nowadays the logic in ccgcalls deals with this case however. if not immediateAsgn: constructLoc(p, v.loc) -proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = +proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = inc(p.labels) result.r = con("LOC", toRope(p.labels)) linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r) @@ -353,20 +357,9 @@ proc deinitGCFrame(p: BProc): PRope = if p.gcFrameId > 0: result = ropecg(p.module, "if (((NU)&GCFRAME) < 4096) #nimGCFrame(&GCFRAME);$n") - -proc allocParam(p: BProc, s: PSym) = - assert(s.kind == skParam) - if lfParamCopy notin s.loc.flags: - inc(p.labels) - var tmp = con("%LOC", toRope(p.labels)) - incl(s.loc.flags, lfParamCopy) - incl(s.loc.flags, lfIndirect) - lineF(p, cpsInit, "$1 = alloca $3$n" & "store $3 $2, $3* $1$n", - [tmp, s.loc.r, getTypeDesc(p.module, s.loc.t)]) - s.loc.r = tmp - -proc localDebugInfo(p: BProc, s: PSym) = - if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return + +proc localDebugInfo(p: BProc, s: PSym) = + if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return # XXX work around a bug: No type information for open arrays possible: if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return var a = con("&", s.loc.r) @@ -379,7 +372,7 @@ proc localDebugInfo(p: BProc, s: PSym) = inc p.blocks[p.blocks.len-1].frameLen proc localVarDecl(p: BProc; s: PSym): PRope = - if s.loc.k == locNone: + if s.loc.k == locNone: fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack) if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy) result = getTypeDesc(p.module, s.loc.t) @@ -406,22 +399,22 @@ include ccgthreadvars proc varInDynamicLib(m: BModule, sym: PSym) proc mangleDynLibProc(sym: PSym): PRope -proc assignGlobalVar(p: BProc, s: PSym) = - if s.loc.k == locNone: +proc assignGlobalVar(p: BProc, s: PSym) = + if s.loc.k == locNone: fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), OnHeap) - + if lfDynamicLib in s.loc.flags: var q = findPendingModule(p.module, s) - if q != nil and not containsOrIncl(q.declaredThings, s.id): + if q != nil and not containsOrIncl(q.declaredThings, s.id): varInDynamicLib(q, s) else: s.loc.r = mangleDynLibProc(s) return useHeader(p.module, s) if lfNoDecl in s.loc.flags: return - if sfThread in s.flags: + if sfThread in s.flags: declareThreadVar(p.module, s, sfImportc in s.flags) - else: + else: var decl: PRope = nil var td = getTypeDesc(p.module, s.loc.t) if s.constraint.isNil: @@ -437,25 +430,25 @@ proc assignGlobalVar(p: BProc, s: PSym) = # fixes tests/run/tzeroarray: resetLoc(p, s.loc) if p.module.module.options * {optStackTrace, optEndb} == - {optStackTrace, optEndb}: - appcg(p.module, p.module.s[cfsDebugInit], - "#dbgRegisterGlobal($1, &$2, $3);$n", - [makeCString(normalize(s.owner.name.s & '.' & s.name.s)), + {optStackTrace, optEndb}: + appcg(p.module, p.module.s[cfsDebugInit], + "#dbgRegisterGlobal($1, &$2, $3);$n", + [makeCString(normalize(s.owner.name.s & '.' & s.name.s)), s.loc.r, genTypeInfo(p.module, s.typ)]) - -proc assignParam(p: BProc, s: PSym) = + +proc assignParam(p: BProc, s: PSym) = assert(s.loc.r != nil) localDebugInfo(p, s) -proc fillProcLoc(sym: PSym) = - if sym.loc.k == locNone: +proc fillProcLoc(sym: PSym) = + if sym.loc.k == locNone: fillLoc(sym.loc, locProc, sym.typ, mangleName(sym), OnStack) - -proc getLabel(p: BProc): TLabel = + +proc getLabel(p: BProc): TLabel = inc(p.labels) result = con("LA", toRope(p.labels)) -proc fixLabel(p: BProc, labl: TLabel) = +proc fixLabel(p: BProc, labl: TLabel) = lineF(p, cpsStmts, "$1: ;$n", [labl]) proc genVarPrototype(m: BModule, sym: PSym) @@ -467,6 +460,7 @@ proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc) proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) proc intLiteral(i: BiggestInt): PRope proc genLiteral(p: BProc, n: PNode): PRope +proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): PRope proc initLocExpr(p: BProc, e: PNode, result: var TLoc) = initLoc(result, locNone, e.typ, OnUnknown) @@ -487,12 +481,12 @@ include ccgcalls, "ccgstmts.nim", "ccgexprs.nim" proc isGetProcAddr(lib: PLib): bool = let n = lib.path - result = n.kind in nkCallKinds and n.typ != nil and + result = n.kind in nkCallKinds and n.typ != nil and n.typ.kind in {tyPointer, tyProc} -proc loadDynamicLib(m: BModule, lib: PLib) = +proc loadDynamicLib(m: BModule, lib: PLib) = assert(lib != nil) - if not lib.generated: + if not lib.generated: lib.generated = true var tmp = getGlobalTempName() assert(lib.name == nil) @@ -504,14 +498,14 @@ proc loadDynamicLib(m: BModule, lib: PLib) = if gVerbosity >= 2: msgWriteln("Dependency: " & lib.path.strVal) var loadlib: PRope = nil - for i in countup(0, high(s)): + for i in countup(0, high(s)): inc(m.labels) if i > 0: app(loadlib, "||") - appcg(m, loadlib, "($1 = #nimLoadLibrary((#NimStringDesc*) &$2))$n", + appcg(m, loadlib, "($1 = #nimLoadLibrary((#NimStringDesc*) &$2))$n", [tmp, getStrLit(m, s[i])]) - appcg(m, m.s[cfsDynLibInit], - "if (!($1)) #nimLoadLibraryError((#NimStringDesc*) &$2);$n", - [loadlib, getStrLit(m, lib.path.strVal)]) + appcg(m, m.s[cfsDynLibInit], + "if (!($1)) #nimLoadLibraryError((#NimStringDesc*) &$2);$n", + [loadlib, getStrLit(m, lib.path.strVal)]) else: var p = newProc(nil, m) p.options = p.options - {optStackTrace, optEndb} @@ -520,20 +514,20 @@ proc loadDynamicLib(m: BModule, lib: PLib) = app(m.s[cfsVars], p.s(cpsLocals)) app(m.s[cfsDynLibInit], p.s(cpsInit)) app(m.s[cfsDynLibInit], p.s(cpsStmts)) - appcg(m, m.s[cfsDynLibInit], - "if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n", + appcg(m, m.s[cfsDynLibInit], + "if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n", [tmp, rdLoc(dest)]) - + if lib.name == nil: internalError("loadDynamicLib") - + proc mangleDynLibProc(sym: PSym): PRope = - if sfCompilerProc in sym.flags: + if sfCompilerProc in sym.flags: # NOTE: sym.loc.r is the external name! result = toRope(sym.name.s) else: result = ropef("Dl_$1", [toRope(sym.id)]) - -proc symInDynamicLib(m: BModule, sym: PSym) = + +proc symInDynamicLib(m: BModule, sym: PSym) = var lib = sym.annex let isCall = isGetProcAddr(lib) var extname = sym.loc.r @@ -565,13 +559,13 @@ proc symInDynamicLib(m: BModule, sym: PSym) = else: internalError(sym.info, "wrong index: " & idx) else: - appcg(m, m.s[cfsDynLibInit], - "\t$1 = ($2) #nimGetProcAddr($3, $4);$n", - [tmp, getTypeDesc(m, sym.typ), + appcg(m, m.s[cfsDynLibInit], + "\t$1 = ($2) #nimGetProcAddr($3, $4);$n", + [tmp, getTypeDesc(m, sym.typ), lib.name, makeCString(ropeToStr(extname))]) appf(m.s[cfsVars], "$2 $1;$n", [sym.loc.r, getTypeDesc(m, sym.loc.t)]) -proc varInDynamicLib(m: BModule, sym: PSym) = +proc varInDynamicLib(m: BModule, sym: PSym) = var lib = sym.annex var extname = sym.loc.r loadDynamicLib(m, lib) @@ -579,9 +573,9 @@ proc varInDynamicLib(m: BModule, sym: PSym) = var tmp = mangleDynLibProc(sym) sym.loc.r = tmp # from now on we only need the internal name inc(m.labels, 2) - appcg(m, m.s[cfsDynLibInit], - "$1 = ($2*) #nimGetProcAddr($3, $4);$n", - [tmp, getTypeDesc(m, sym.typ), + appcg(m, m.s[cfsDynLibInit], + "$1 = ($2*) #nimGetProcAddr($3, $4);$n", + [tmp, getTypeDesc(m, sym.typ), lib.name, makeCString(ropeToStr(extname))]) appf(m.s[cfsVars], "$2* $1;$n", [sym.loc.r, getTypeDesc(m, sym.loc.t)]) @@ -590,9 +584,9 @@ proc symInDynamicLibPartial(m: BModule, sym: PSym) = sym.loc.r = mangleDynLibProc(sym) sym.typ.sym = nil # generate a new name -proc cgsym(m: BModule, name: string): PRope = +proc cgsym(m: BModule, name: string): PRope = var sym = magicsys.getCompilerProc(name) - if sym != nil: + if sym != nil: case sym.kind of skProc, skMethod, skConverter, skIterators: genProc(m, sym) of skVar, skResult, skLet: genVarPrototype(m, sym) @@ -604,18 +598,18 @@ proc cgsym(m: BModule, name: string): PRope = # we're picky here for the system module too: rawMessage(errSystemNeeds, name) result = sym.loc.r - + proc generateHeaders(m: BModule) = app(m.s[cfsHeaders], tnl & "#include \"nimbase.h\"" & tnl) var it = PStrEntry(m.headerFiles.head) while it != nil: - if it.data[0] notin {'\"', '<'}: + if it.data[0] notin {'\"', '<'}: appf(m.s[cfsHeaders], "$N#include \"$1\"$N", [toRope(it.data)]) else: appf(m.s[cfsHeaders], "$N#include $1$N", [toRope(it.data)]) it = PStrEntry(it.next) -proc retIsNotVoid(s: PSym): bool = +proc retIsNotVoid(s: PSym): bool = result = (s.typ.sons[0] != nil) and not isInvalidReturnType(s.typ.sons[0]) proc initFrame(p: BProc, procname, filename: PRope): PRope = @@ -663,11 +657,11 @@ proc genProcAux(m: BModule, prc: PSym) = else: fillResult(res) assignParam(p, res) - if skipTypes(res.typ, abstractInst).kind == tyArray: + if skipTypes(res.typ, abstractInst).kind == tyArray: incl(res.loc.flags, lfIndirect) res.loc.s = OnUnknown - - for i in countup(1, sonsLen(prc.typ.n) - 1): + + for i in countup(1, sonsLen(prc.typ.n) - 1): var param = prc.typ.n.sons[i].sym if param.typ.isCompileTimeOnly: continue assignParam(p, param) @@ -682,11 +676,11 @@ proc genProcAux(m: BModule, prc: PSym) = else: generatedProc = rfmt(nil, "$N$1 {$N", header) app(generatedProc, initGCFrame(p)) - if optStackTrace in prc.options: + if optStackTrace in prc.options: app(generatedProc, p.s(cpsLocals)) var procname = makeCString(prc.name.s) app(generatedProc, initFrame(p, procname, prc.info.quotedFilename)) - else: + else: app(generatedProc, p.s(cpsLocals)) if optProfiler in prc.options: # invoke at proc entry for recursion: @@ -706,12 +700,12 @@ proc crossesCppBoundary(m: BModule; sym: PSym): bool {.inline.} = sfCompileToCpp notin sym.getModule().flags and gCmd != cmdCompileToCpp -proc genProcPrototype(m: BModule, sym: PSym) = +proc genProcPrototype(m: BModule, sym: PSym) = useHeader(m, sym) - if lfNoDecl in sym.loc.flags: return + if lfNoDecl in sym.loc.flags: return if lfDynamicLib in sym.loc.flags: if getModule(sym).id != m.module.id and - not containsOrIncl(m.declaredThings, sym.id): + not containsOrIncl(m.declaredThings, sym.id): app(m.s[cfsVars], rfmt(nil, "extern $1 $2;$n", getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym))) elif not containsOrIncl(m.declaredProtos, sym.id): @@ -722,13 +716,13 @@ proc genProcPrototype(m: BModule, sym: PSym) = header.app(" __attribute__((naked))") app(m.s[cfsProcHeaders], rfmt(nil, "$1;$n", header)) -proc genProcNoForward(m: BModule, prc: PSym) = +proc genProcNoForward(m: BModule, prc: PSym) = fillProcLoc(prc) useHeader(m, prc) if lfImportCompilerProc in prc.loc.flags: # dependency to a compilerproc: discard cgsym(m, prc.name.s) - return + return genProcPrototype(m, prc) if lfNoDecl in prc.loc.flags: discard elif prc.typ.callConv == ccInline: @@ -738,13 +732,13 @@ proc genProcNoForward(m: BModule, prc: PSym) = if not containsOrIncl(m.declaredThings, prc.id): genProcAux(m, prc) elif lfDynamicLib in prc.loc.flags: var q = findPendingModule(m, prc) - if q != nil and not containsOrIncl(q.declaredThings, prc.id): + if q != nil and not containsOrIncl(q.declaredThings, prc.id): symInDynamicLib(q, prc) else: symInDynamicLibPartial(m, prc) elif sfImportc notin prc.flags: var q = findPendingModule(m, prc) - if q != nil and not containsOrIncl(q.declaredThings, prc.id): + if q != nil and not containsOrIncl(q.declaredThings, prc.id): genProcAux(q, prc) proc requestConstImpl(p: BProc, sym: PSym) = @@ -770,7 +764,7 @@ proc requestConstImpl(p: BProc, sym: PSym) = proc isActivated(prc: PSym): bool = prc.typ != nil -proc genProc(m: BModule, prc: PSym) = +proc genProc(m: BModule, prc: PSym) = if sfBorrow in prc.flags or not isActivated(prc): return fillProcLoc(prc) if sfForward in prc.flags: addForwardedProc(m, prc) @@ -780,19 +774,19 @@ proc genProc(m: BModule, prc: PSym) = generatedHeader != nil and lfNoDecl notin prc.loc.flags: genProcPrototype(generatedHeader, prc) if prc.typ.callConv == ccInline: - if not containsOrIncl(generatedHeader.declaredThings, prc.id): + if not containsOrIncl(generatedHeader.declaredThings, prc.id): genProcAux(generatedHeader, prc) -proc genVarPrototypeAux(m: BModule, sym: PSym) = +proc genVarPrototypeAux(m: BModule, sym: PSym) = assert(sfGlobal in sym.flags) useHeader(m, sym) fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap) - if (lfNoDecl in sym.loc.flags) or containsOrIncl(m.declaredThings, sym.id): - return - if sym.owner.id != m.module.id: + if (lfNoDecl in sym.loc.flags) or containsOrIncl(m.declaredThings, sym.id): + return + if sym.owner.id != m.module.id: # else we already have the symbol generated! assert(sym.loc.r != nil) - if sfThread in sym.flags: + if sfThread in sym.flags: declareThreadVar(m, sym, true) else: app(m.s[cfsVars], "extern ") @@ -838,7 +832,7 @@ proc genFilenames(m: BModule): PRope = result.appf("dbgRegisterFilename($1);$N", fileInfos[i].projPath.makeCString) proc genMainProc(m: BModule) = - const + const # The use of a volatile function pointer to call Pre/NimMainInner # prevents inlining of the NimMainInner function and dependent # functions, which might otherwise merge their stack frames. @@ -859,7 +853,7 @@ proc genMainProc(m: BModule) = MainProcs = "\tNimMain();$N" - + MainProcsWithResult = MainProcs & "\treturn nim_program_result;$N" @@ -880,7 +874,7 @@ proc genMainProc(m: BModule) = "char** cmdLine;$N" & "char** gEnv;$N" & NimMainBody - + PosixCMain = "int main(int argc, char** args, char** env) {$N" & "\tcmdLine = args;$N" & @@ -888,20 +882,20 @@ proc genMainProc(m: BModule) = "\tgEnv = env;$N" & MainProcsWithResult & "}$N$N" - + StandaloneCMain = "int main(void) {$N" & MainProcs & "\treturn 0;$N" & "}$N$N" - + WinNimMain = NimMainBody - + WinCMain = "N_STDCALL(int, WinMain)(HINSTANCE hCurInstance, $N" & " HINSTANCE hPrevInstance, $N" & " LPSTR lpCmdLine, int nCmdShow) {$N" & MainProcsWithResult & "}$N$N" - + WinNimDllMain = "N_LIB_EXPORT " & NimMainBody WinCDllMain = @@ -911,7 +905,7 @@ proc genMainProc(m: BModule) = "\treturn 1;$N}$N$N" PosixNimDllMain = WinNimDllMain - + PosixCDllMain = "void NIM_POSIX_INIT NimMainInit(void) {$N" & MainProcs & @@ -919,11 +913,11 @@ proc genMainProc(m: BModule) = var nimMain, otherMain: TFormatStr if platform.targetOS == osWindows and - gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}: - if optGenGuiApp in gGlobalOptions: + gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}: + if optGenGuiApp in gGlobalOptions: nimMain = WinNimMain otherMain = WinCMain - else: + else: nimMain = WinNimDllMain otherMain = WinCDllMain discard lists.includeStr(m.headerFiles, "<windows.h>") @@ -939,7 +933,7 @@ proc genMainProc(m: BModule) = if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint") if optEndb in gOptions: gBreakpoints.app(m.genFilenames) - + let initStackBottomCall = if platform.targetOS == osStandalone: "".toRope else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N") @@ -964,11 +958,11 @@ proc getSomeInitName(m: PSym, suffix: string): PRope = result.app "_" result.app m.name.s result.app suffix - + proc getInitName(m: PSym): PRope = getSomeInitName(m, "Init") proc getDatInitName(m: PSym): PRope = getSomeInitName(m, "DatInit") -proc registerModuleToMain(m: PSym) = +proc registerModuleToMain(m: PSym) = var init = m.getInitName datInit = m.getDatInitName @@ -981,19 +975,19 @@ proc registerModuleToMain(m: PSym) = app(mainModInit, initCall) else: app(otherModsInit, initCall) - -proc genInitCode(m: BModule) = + +proc genInitCode(m: BModule) = var initname = getInitName(m.module) var prc = ropef("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", [initname]) - if m.typeNodes > 0: - appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n", + if m.typeNodes > 0: + appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n", [m.typeNodesName, toRope(m.typeNodes)]) - if m.nimTypes > 0: - appcg(m, m.s[cfsTypeInit1], "static #TNimType $1[$2];$n", + if m.nimTypes > 0: + appcg(m, m.s[cfsTypeInit1], "static #TNimType $1[$2];$n", [m.nimTypesName, toRope(m.nimTypes)]) - + app(prc, initGCFrame(m.initProc)) - + app(prc, genSectionStart(cpsLocals)) app(prc, m.preInitProc.s(cpsLocals)) app(prc, m.initProc.s(cpsLocals)) @@ -1009,7 +1003,7 @@ proc genInitCode(m: BModule) = app(prc, initFrame(m.initProc, procname, m.module.info.quotedFilename)) else: app(prc, ~"\tTFrame F; F.len = 0;$N") - + app(prc, genSectionStart(cpsInit)) app(prc, m.preInitProc.s(cpsInit)) app(prc, m.initProc.s(cpsInit)) @@ -1033,27 +1027,27 @@ proc genInitCode(m: BModule) = app(prc, genSectionStart(i)) app(prc, m.s[i]) app(prc, genSectionEnd(i)) - + appf(prc, "}$N$N") # we cannot simply add the init proc to ``m.s[cfsProcs]`` anymore because # that would lead to a *nesting* of merge sections which the merger does # not support. So we add it to another special section: ``cfsInitProc`` app(m.s[cfsInitProc], prc) - + for i, el in pairs(m.extensionLoaders): if el != nil: let ex = ropef("N_NIMCALL(void, nimLoadProcs$1)(void) {$2}$N$N", (i.ord - '0'.ord).toRope, el) app(m.s[cfsInitProc], ex) -proc genModule(m: BModule, cfile: string): PRope = +proc genModule(m: BModule, cfile: string): PRope = result = getFileHeader(cfile) result.app(genMergeInfo(m)) - + generateHeaders(m) generateThreadLocalStorage(m) - for i in countup(cfsHeaders, cfsProcs): + for i in countup(cfsHeaders, cfsProcs): app(result, genSectionStart(i)) app(result, m.s[i]) app(result, genSectionEnd(i)) @@ -1069,7 +1063,7 @@ proc newPostInitProc(m: BModule): BProc = # little hack so that unique temporaries are generated: result.labels = 200_000 -proc initProcOptions(m: BModule): TOptions = +proc initProcOptions(m: BModule): TOptions = if sfSystemModule in m.module.flags: gOptions-{optStackTrace} else: gOptions proc rawNewModule(module: PSym, filename: string): BModule = @@ -1124,11 +1118,11 @@ proc resetModule*(m: BModule) = m.typeNodes = 0 m.nimTypes = 0 nullify m.extensionLoaders - + # indicate that this is now cached module # the cache will be invalidated by nullifying gModules m.fromCache = true - + # we keep only the "merge info" information for the module # and the properties that can't change: # m.filename @@ -1155,11 +1149,11 @@ proc newModule(module: PSym): BModule = growCache gModules, module.position gModules[module.position] = result - if (optDeadCodeElim in gGlobalOptions): - if (sfDeadCodeElim in module.flags): + if (optDeadCodeElim in gGlobalOptions): + if (sfDeadCodeElim in module.flags): internalError("added pending module twice: " & module.filename) -proc myOpen(module: PSym): PPassContext = +proc myOpen(module: PSym): PPassContext = result = newModule(module) if optGenIndex in gGlobalOptions and generatedHeader == nil: let f = if headerFile.len > 0: headerFile else: gProjectFull @@ -1175,12 +1169,12 @@ proc writeHeader(m: BModule) = generateHeaders(m) generateThreadLocalStorage(m) - for i in countup(cfsHeaders, cfsProcs): + for i in countup(cfsHeaders, cfsProcs): app(result, genSectionStart(i)) app(result, m.s[i]) app(result, genSectionEnd(i)) app(result, m.s[cfsInitProc]) - + if optGenDynLib in gGlobalOptions: result.app("N_LIB_IMPORT ") result.appf("N_CDECL(void, NimMain)(void);$n") @@ -1200,20 +1194,20 @@ proc myOpenCached(module: PSym, rd: PRodReader): PPassContext = readMergeInfo(getCFile(m), m) result = m -proc myProcess(b: PPassContext, n: PNode): PNode = +proc myProcess(b: PPassContext, n: PNode): PNode = result = n if b == nil or passes.skipCodegen(n): return var m = BModule(b) m.initProc.options = initProcOptions(m) genStmts(m.initProc, n) -proc finishModule(m: BModule) = +proc finishModule(m: BModule) = var i = 0 - while i <= high(m.forwardedProcs): + while i <= high(m.forwardedProcs): # Note: ``genProc`` may add to ``m.forwardedProcs``, so we cannot use # a ``for`` loop here var prc = m.forwardedProcs[i] - if sfForward in prc.flags: + if sfForward in prc.flags: internalError(prc.info, "still forwarded: " & prc.name.s) genProcNoForward(m, prc) inc(i) @@ -1221,13 +1215,13 @@ proc finishModule(m: BModule) = dec(gForwardedProcsCounter, i) setLen(m.forwardedProcs, 0) -proc shouldRecompile(code: PRope, cfile: string): bool = +proc shouldRecompile(code: PRope, cfile: string): bool = result = true if optForceFullMake notin gGlobalOptions: var objFile = toObjFile(cfile) - if writeRopeIfNotEqual(code, cfile): return + if writeRopeIfNotEqual(code, cfile): return if existsFile(objFile) and os.fileNewer(objFile, cfile): result = false - else: + else: writeRope(code, cfile) # We need 2 different logics here: pending modules (including @@ -1240,15 +1234,15 @@ proc writeModule(m: BModule, pending: bool) = # generate code for the init statements of the module: var cfile = getCFile(m) var cfilenoext = changeFileExt(cfile, "") - + if not m.fromCache or optForceFullMake in gGlobalOptions: genInitCode(m) finishTypeDescriptions(m) - if sfMainModule in m.module.flags: + if sfMainModule in m.module.flags: # generate main file: app(m.s[cfsProcHeaders], mainModProcs) generateThreadVarsSize(m) - + var code = genModule(m, cfile) when hasTinyCBackend: if gCmd == cmdRun: @@ -1269,13 +1263,13 @@ proc writeModule(m: BModule, pending: bool) = # ``system.c`` but then compilation fails due to an error. This means # that ``system.o`` is missing, so we need to call the C compiler for it: addFileToCompile(cfile) - + addFileToLink(cfilenoext) proc updateCachedModule(m: BModule) = let cfile = getCFile(m) let cfilenoext = changeFileExt(cfile, "") - + if mergeRequired(m) and sfMainModule notin m.module.flags: mergeFiles(cfile, m) genInitCode(m) @@ -1286,17 +1280,17 @@ proc updateCachedModule(m: BModule) = addFileToLink(cfilenoext) -proc myClose(b: PPassContext, n: PNode): PNode = +proc myClose(b: PPassContext, n: PNode): PNode = result = n - if b == nil or passes.skipCodegen(n): return + if b == nil or passes.skipCodegen(n): return var m = BModule(b) - if n != nil: + if n != nil: m.initProc.options = initProcOptions(m) genStmts(m.initProc, n) - # cached modules need to registered too: + # cached modules need to registered too: registerModuleToMain(m.module) - if sfMainModule in m.module.flags: + if sfMainModule in m.module.flags: m.objHasKidsValid = true var disp = generateMethodDispatchers() for i in 0..sonsLen(disp)-1: genProcAux(m, disp.sons[i].sym) diff --git a/compiler/guards.nim b/compiler/guards.nim index b0420cb75..cedd2be2b 100644 --- a/compiler/guards.nim +++ b/compiler/guards.nim @@ -373,13 +373,28 @@ proc addFactNeg*(m: var TModel, n: PNode) = let n = n.neg if n != nil: addFact(m, n) +proc canonOpr(opr: PSym): PSym = + case opr.magic + of someEq: result = opEq + of someLe: result = opLe + of someLt: result = opLt + of someLen: result = opLen + of someAdd: result = opAdd + of someSub: result = opSub + of someMul: result = opMul + of someDiv: result = opDiv + else: result = opr + proc sameTree*(a, b: PNode): bool = result = false if a == b: result = true - elif (a != nil) and (b != nil) and (a.kind == b.kind): + elif a != nil and b != nil and a.kind == b.kind: case a.kind - of nkSym: result = a.sym == b.sym + of nkSym: + result = a.sym == b.sym + if not result and a.sym.magic != mNone: + result = a.sym.magic == b.sym.magic or canonOpr(a.sym) == canonOpr(b.sym) of nkIdent: result = a.ident.id == b.ident.id of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal @@ -643,7 +658,7 @@ proc factImplies(fact, prop: PNode): TImplication = if a == b: return ~a return impUnknown else: - internalError(fact.info, "invalid fact") + return impUnknown of mAnd: result = factImplies(fact.sons[1], prop) if result != impUnknown: return result @@ -657,7 +672,7 @@ proc factImplies(fact, prop: PNode): TImplication = of someLe: result = impliesLe(fact, prop.sons[1], prop.sons[2]) of someLt: result = impliesLt(fact, prop.sons[1], prop.sons[2]) of mInSet: result = impliesIn(fact, prop.sons[2], prop.sons[1]) - else: internalError(prop.info, "invalid proposition") + else: result = impUnknown proc doesImply*(facts: TModel, prop: PNode): TImplication = assert prop.kind in nkCallKinds diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 6d3379bb9..88e32404a 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -9,8 +9,8 @@ # This module implements lookup helpers. -import - intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread, +import + intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread, renderer, wordrecg, idgen, nimfix.prettybase proc ensureNoMissingOrUnusedSymbols(scope: PScope) @@ -87,14 +87,14 @@ proc searchInScopes*(c: PContext, s: PIdent): PSym = if result != nil: return result = nil -proc debugScopes*(c: PContext) {.deprecated.} = +proc debugScopes*(c: PContext; limit=0) {.deprecated.} = var i = 0 for scope in walkScopes(c.currentScope): echo "scope ", i for h in 0 .. high(scope.symbols.data): if scope.symbols.data[h] != nil: echo scope.symbols.data[h].name.s - if i == 2: break + if i == limit: break inc i proc searchInScopes*(c: PContext, s: PIdent, filter: TSymKinds): PSym = @@ -108,7 +108,7 @@ proc errorSym*(c: PContext, n: PNode): PSym = var m = n # ensure that 'considerQuotedIdent' can't fail: if m.kind == nkDotExpr: m = m.sons[1] - let ident = if m.kind in {nkIdent, nkSym, nkAccQuoted}: + let ident = if m.kind in {nkIdent, nkSym, nkAccQuoted}: considerQuotedIdent(m) else: getIdent("err:" & renderTree(m)) @@ -119,11 +119,11 @@ proc errorSym*(c: PContext, n: PNode): PSym = if gCmd != cmdInteractive and c.inCompilesContext == 0: c.importTable.addSym(result) -type - TOverloadIterMode* = enum +type + TOverloadIterMode* = enum oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, oimSymChoice, oimSymChoiceLocalLookup - TOverloadIter*{.final.} = object + TOverloadIter*{.final.} = object it*: TIdentIter m*: PSym mode*: TOverloadIterMode @@ -131,7 +131,7 @@ type scope*: PScope inSymChoice: IntSet -proc getSymRepr*(s: PSym): string = +proc getSymRepr*(s: PSym): string = case s.kind of skProc, skMethod, skConverter, skIterators: result = getProcHeader(s) else: result = s.name.s @@ -148,7 +148,7 @@ proc ensureNoMissingOrUnusedSymbols(scope: PScope) = if missingImpls == 0: localError(s.info, errImplOfXexpected, getSymRepr(s)) inc missingImpls - elif {sfUsed, sfExported} * s.flags == {} and optHints in s.options: + elif {sfUsed, sfExported} * s.flags == {} and optHints in s.options: # BUGFIX: check options in s! if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}: # XXX: implicit type params are currently skTypes @@ -156,11 +156,11 @@ proc ensureNoMissingOrUnusedSymbols(scope: PScope) = if s.typ != nil and tfImplicitTypeParam notin s.typ.flags: message(s.info, hintXDeclaredButNotUsed, getSymRepr(s)) s = nextIter(it, scope.symbols) - + proc wrongRedefinition*(info: TLineInfo, s: string) = if gCmd != cmdInteractive: localError(info, errAttemptToRedefine, s) - + proc addDecl*(c: PContext, sym: PSym) = if not c.currentScope.addUniqueSym(sym): wrongRedefinition(sym.info, sym.name.s) @@ -172,7 +172,7 @@ proc addDeclAt*(scope: PScope, sym: PSym) = if not scope.addUniqueSym(sym): wrongRedefinition(sym.info, sym.name.s) -proc addInterfaceDeclAux(c: PContext, sym: PSym) = +proc addInterfaceDeclAux(c: PContext, sym: PSym) = if sfExported in sym.flags: # add to interface: if c.module != nil: strTableAdd(c.module.tab, sym) @@ -183,16 +183,16 @@ proc addInterfaceDeclAt*(c: PContext, scope: PScope, sym: PSym) = addInterfaceDeclAux(c, sym) proc addOverloadableSymAt*(scope: PScope, fn: PSym) = - if fn.kind notin OverloadableSyms: + if fn.kind notin OverloadableSyms: internalError(fn.info, "addOverloadableSymAt") return let check = strTableGet(scope.symbols, fn.name) - if check != nil and check.kind notin OverloadableSyms: + if check != nil and check.kind notin OverloadableSyms: wrongRedefinition(fn.info, fn.name.s) else: scope.addSym(fn) - -proc addInterfaceDecl*(c: PContext, sym: PSym) = + +proc addInterfaceDecl*(c: PContext, sym: PSym) = # it adds the symbol to the interface if appropriate addDecl(c, sym) addInterfaceDeclAux(c, sym) @@ -221,7 +221,7 @@ when defined(nimfix): else: template fixSpelling(n: PNode; ident: PIdent; op: expr) = discard -proc lookUp*(c: PContext, n: PNode): PSym = +proc lookUp*(c: PContext, n: PNode): PSym = # Looks up a symbol. Generates an error in case of nil. case n.kind of nkIdent: @@ -242,12 +242,12 @@ proc lookUp*(c: PContext, n: PNode): PSym = else: internalError(n.info, "lookUp") return - if contains(c.ambiguousSymbols, result.id): + if contains(c.ambiguousSymbols, result.id): localError(n.info, errUseQualifier, result.name.s) if result.kind == skStub: loadStub(result) - -type - TLookupFlag* = enum + +type + TLookupFlag* = enum checkAmbiguity, checkUndeclared proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = @@ -294,7 +294,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = else: result = nil if result != nil and result.kind == skStub: loadStub(result) - + proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = case n.kind of nkIdent, nkAccQuoted: @@ -311,17 +311,17 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = of nkSym: result = n.sym o.mode = oimDone - of nkDotExpr: + of nkDotExpr: o.mode = oimOtherModule o.m = qualifiedLookUp(c, n.sons[0]) if o.m != nil and o.m.kind == skModule: var ident: PIdent = nil - if n.sons[1].kind == nkIdent: + if n.sons[1].kind == nkIdent: ident = n.sons[1].ident elif n.sons[1].kind == nkAccQuoted: ident = considerQuotedIdent(n.sons[1]) - if ident != nil: - if o.m == c.module: + if ident != nil: + if o.m == c.module: # a module may access its private members: result = initIdentIter(o.it, c.topLevelScope.symbols, ident).skipAlias(n) @@ -329,7 +329,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = else: result = initIdentIter(o.it, o.m.tab, ident).skipAlias(n) else: - localError(n.sons[1].info, errIdentifierExpected, + localError(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1])) result = errorSym(c, n.sons[1]) of nkClosedSymChoice, nkOpenSymChoice: @@ -347,12 +347,12 @@ proc lastOverloadScope*(o: TOverloadIter): int = of oimSelfModule: result = 1 of oimOtherModule: result = 0 else: result = -1 - -proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = + +proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = case o.mode - of oimDone: + of oimDone: result = nil - of oimNoQualifier: + of oimNoQualifier: if o.scope != nil: result = nextIdentIter(o.it, o.scope.symbols).skipAlias(n) while result == nil: @@ -360,13 +360,13 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = if o.scope == nil: break result = initIdentIter(o.it, o.scope.symbols, o.it.name).skipAlias(n) # BUGFIX: o.it.name <-> n.ident - else: + else: result = nil - of oimSelfModule: + of oimSelfModule: result = nextIdentIter(o.it, c.topLevelScope.symbols).skipAlias(n) - of oimOtherModule: + of oimOtherModule: result = nextIdentIter(o.it, o.m.tab).skipAlias(n) - of oimSymChoice: + of oimSymChoice: if o.symChoiceIndex < sonsLen(n): result = n.sons[o.symChoiceIndex].sym incl(o.inSymChoice, result.id) @@ -389,7 +389,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = if o.scope == nil: break result = firstIdentExcluding(o.it, o.scope.symbols, n.sons[0].sym.name, o.inSymChoice).skipAlias(n) - + if result != nil and result.kind == skStub: loadStub(result) proc pickSym*(c: PContext, n: PNode; kind: TSymKind; diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim index 58b5c5681..8c0875ab1 100644 --- a/compiler/parampatterns.nim +++ b/compiler/parampatterns.nim @@ -174,7 +174,8 @@ type arLValue, # is an l-value arLocalLValue, # is an l-value, but local var; must not escape # its stack frame! - arDiscriminant # is a discriminant + arDiscriminant, # is a discriminant + arStrange # it is a strange beast like 'typedesc[var T]' proc isAssignable*(owner: PSym, n: PNode): TAssignableResult = ## 'owner' can be nil! @@ -188,6 +189,9 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult = result = arLocalLValue else: result = arLValue + elif n.sym.kind == skType: + let t = n.sym.typ.skipTypes({tyTypeDesc}) + if t.kind == tyVar: result = arStrange of nkDotExpr: if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in {tyVar, tyPtr, tyRef}: @@ -222,7 +226,7 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult = discard proc isLValue*(n: PNode): bool = - isAssignable(nil, n) in {arLValue, arLocalLValue} + isAssignable(nil, n) in {arLValue, arLocalLValue, arStrange} proc matchNodeKinds*(p, n: PNode): bool = # matches the parameter constraint 'p' against the concrete AST 'n'. diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 78ee490e2..056e4f4c0 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -9,23 +9,23 @@ # This module implements semantic checking for pragmas -import - os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer, +import + os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer, wordrecg, ropes, options, strutils, lists, extccomp, math, magicsys, trees, rodread, types, lookups -const +const FirstCallConv* = wNimcall LastCallConv* = wNoconv const - procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, - wMagic, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, - wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, + procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, + wMagic, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, + wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl, wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe, - wOverride} + wOverride, wConstructor} converterPragmas* = procPragmas methodPragmas* = procPragmas templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty, @@ -33,7 +33,7 @@ const macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc, wNodecl, wMagic, wNosideeffect, wCompilerproc, wDeprecated, wExtern, wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator} - iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect, + iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect, wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern, wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises, wTags, wLocks, wGcSafe} @@ -46,18 +46,18 @@ const wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto, wInjectStmt, wDeprecated, wExperimental} - lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, - wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, + lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, + wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, wRaises, wLocks, wTags, wGcSafe} - typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, + typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow, wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef, wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked, wBorrow, wGcSafe} - fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, + fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, wImportCpp, wImportObjC, wError, wGuard} - varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, + varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern, wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal, wGensym, wInject, wCodegenDecl, wGuard} @@ -74,18 +74,18 @@ proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) proc invalidPragma(n: PNode) = localError(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments})) -proc pragmaAsm*(c: PContext, n: PNode): char = +proc pragmaAsm*(c: PContext, n: PNode): char = result = '\0' - if n != nil: - for i in countup(0, sonsLen(n) - 1): + if n != nil: + for i in countup(0, sonsLen(n) - 1): let it = n.sons[i] if it.kind == nkExprColonExpr and it.sons[0].kind == nkIdent: case whichKeyword(it.sons[0].ident) - of wSubsChar: + of wSubsChar: if it.sons[1].kind == nkCharLit: result = chr(int(it.sons[1].intVal)) else: invalidPragma(it) else: invalidPragma(it) - else: + else: invalidPragma(it) proc setExternName(s: PSym, extname: string) = @@ -94,7 +94,7 @@ proc setExternName(s: PSym, extname: string) = # note that '{.importc.}' is transformed into '{.importc: "$1".}' s.loc.flags.incl(lfFullExternalName) -proc makeExternImport(s: PSym, extname: string) = +proc makeExternImport(s: PSym, extname: string) = setExternName(s, extname) incl(s.flags, sfImportc) excl(s.flags, sfForward) @@ -145,7 +145,7 @@ proc newEmptyStrNode(n: PNode): PNode {.noinline.} = result.strVal = "" proc getStrLitNode(c: PContext, n: PNode): PNode = - if n.kind != nkExprColonExpr: + if n.kind != nkExprColonExpr: localError(n.info, errStringLiteralExpected) # error correction: result = newEmptyStrNode(n) @@ -153,62 +153,62 @@ proc getStrLitNode(c: PContext, n: PNode): PNode = n.sons[1] = c.semConstExpr(c, n.sons[1]) case n.sons[1].kind of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1] - else: + else: localError(n.info, errStringLiteralExpected) # error correction: result = newEmptyStrNode(n) -proc expectStrLit(c: PContext, n: PNode): string = +proc expectStrLit(c: PContext, n: PNode): string = result = getStrLitNode(c, n).strVal -proc expectIntLit(c: PContext, n: PNode): int = - if n.kind != nkExprColonExpr: +proc expectIntLit(c: PContext, n: PNode): int = + if n.kind != nkExprColonExpr: localError(n.info, errIntLiteralExpected) - else: + else: n.sons[1] = c.semConstExpr(c, n.sons[1]) case n.sons[1].kind of nkIntLit..nkInt64Lit: result = int(n.sons[1].intVal) else: localError(n.info, errIntLiteralExpected) -proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string = +proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string = if n.kind == nkExprColonExpr: result = expectStrLit(c, n) else: result = defaultStr proc processCodegenDecl(c: PContext, n: PNode, sym: PSym) = sym.constraint = getStrLitNode(c, n) -proc processMagic(c: PContext, n: PNode, s: PSym) = +proc processMagic(c: PContext, n: PNode, s: PSym) = #if sfSystemModule notin c.module.flags: # liMessage(n.info, errMagicOnlyInSystem) - if n.kind != nkExprColonExpr: + if n.kind != nkExprColonExpr: localError(n.info, errStringLiteralExpected) return var v: string if n.sons[1].kind == nkIdent: v = n.sons[1].ident.s else: v = expectStrLit(c, n) - for m in countup(low(TMagic), high(TMagic)): - if substr($m, 1) == v: + for m in countup(low(TMagic), high(TMagic)): + if substr($m, 1) == v: s.magic = m break if s.magic == mNone: message(n.info, warnUnknownMagic, v) -proc wordToCallConv(sw: TSpecialWord): TCallingConvention = +proc wordToCallConv(sw: TSpecialWord): TCallingConvention = # this assumes that the order of special words and calling conventions is # the same result = TCallingConvention(ord(ccDefault) + ord(sw) - ord(wNimcall)) -proc isTurnedOn(c: PContext, n: PNode): bool = +proc isTurnedOn(c: PContext, n: PNode): bool = if n.kind == nkExprColonExpr: let x = c.semConstBoolExpr(c, n.sons[1]) n.sons[1] = x if x.kind == nkIntLit: return x.intVal != 0 localError(n.info, errOnOrOffExpected) -proc onOff(c: PContext, n: PNode, op: TOptions) = +proc onOff(c: PContext, n: PNode, op: TOptions) = if isTurnedOn(c, n): gOptions = gOptions + op else: gOptions = gOptions - op - -proc pragmaDeadCodeElim(c: PContext, n: PNode) = + +proc pragmaDeadCodeElim(c: PContext, n: PNode) = if isTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim) else: excl(c.module.flags, sfDeadCodeElim) @@ -216,20 +216,20 @@ proc pragmaNoForward(c: PContext, n: PNode) = if isTurnedOn(c, n): incl(c.module.flags, sfNoForward) else: excl(c.module.flags, sfNoForward) -proc processCallConv(c: PContext, n: PNode) = - if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): +proc processCallConv(c: PContext, n: PNode) = + if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): var sw = whichKeyword(n.sons[1].ident) case sw - of FirstCallConv..LastCallConv: + of FirstCallConv..LastCallConv: POptionEntry(c.optionStack.tail).defaultCC = wordToCallConv(sw) else: localError(n.info, errCallConvExpected) - else: + else: localError(n.info, errCallConvExpected) - -proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib = + +proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib = var it = PLib(c.libs.head) - while it != nil: - if it.kind == kind: + while it != nil: + if it.kind == kind: if trees.exprStructuralEquivalent(it.path, path): return it it = PLib(it.next) result = newLib(kind) @@ -252,10 +252,10 @@ proc expectDynlibNode(c: PContext, n: PNode): PNode = if result.typ == nil or result.typ.kind notin {tyPointer, tyString, tyProc}: localError(n.info, errStringLiteralExpected) result = newEmptyStrNode(n) - -proc processDynLib(c: PContext, n: PNode, sym: PSym) = + +proc processDynLib(c: PContext, n: PNode, sym: PSym) = if (sym == nil) or (sym.kind == skModule): - POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic, + POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic, expectDynlibNode(c, n)) else: if n.kind == nkExprColonExpr: @@ -268,7 +268,7 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) = # since we'll be loading the dynlib symbols dynamically, we must use # a calling convention that doesn't introduce custom name mangling # cdecl is the default - the user can override this explicitly - if sym.kind in routineKinds and sym.typ != nil and + if sym.kind in routineKinds and sym.typ != nil and sym.typ.callConv == ccDefault: sym.typ.callConv = ccCDecl @@ -295,10 +295,10 @@ proc processNote(c: PContext, n: PNode) = n.sons[1] = x if x.kind == nkIntLit and x.intVal != 0: incl(gNotes, nk) else: excl(gNotes, nk) - else: + else: invalidPragma(n) - -proc processOption(c: PContext, n: PNode): bool = + +proc processOption(c: PContext, n: PNode): bool = if n.kind != nkExprColonExpr: result = true elif n.sons[0].kind == nkBracketExpr: processNote(c, n) elif n.sons[0].kind != nkIdent: result = true @@ -318,34 +318,34 @@ proc processOption(c: PContext, n: PNode): bool = of wAssertions: onOff(c, n, {optAssert}) of wWarnings: onOff(c, n, {optWarns}) of wHints: onOff(c, n, {optHints}) - of wCallconv: processCallConv(c, n) + of wCallconv: processCallConv(c, n) of wLinedir: onOff(c, n, {optLineDir}) of wStacktrace: onOff(c, n, {optStackTrace}) of wLinetrace: onOff(c, n, {optLineTrace}) of wDebugger: onOff(c, n, {optEndb}) of wProfiler: onOff(c, n, {optProfiler}) of wByRef: onOff(c, n, {optByRef}) - of wDynlib: processDynLib(c, n, nil) - of wOptimization: - if n.sons[1].kind != nkIdent: + of wDynlib: processDynLib(c, n, nil) + of wOptimization: + if n.sons[1].kind != nkIdent: invalidPragma(n) - else: + else: case n.sons[1].ident.s.normalize - of "speed": + of "speed": incl(gOptions, optOptimizeSpeed) excl(gOptions, optOptimizeSize) of "size": excl(gOptions, optOptimizeSpeed) incl(gOptions, optOptimizeSize) - of "none": + of "none": excl(gOptions, optOptimizeSpeed) excl(gOptions, optOptimizeSize) else: localError(n.info, errNoneSpeedOrSizeExpected) of wImplicitStatic: onOff(c, n, {optImplicitStatic}) of wPatterns: onOff(c, n, {optPatterns}) else: result = true - -proc processPush(c: PContext, n: PNode, start: int) = + +proc processPush(c: PContext, n: PNode, start: int) = if n.sons[start-1].kind == nkExprColonExpr: localError(n.info, errGenerated, "':' after 'push' not supported") var x = newOptionEntry() @@ -355,41 +355,41 @@ proc processPush(c: PContext, n: PNode, start: int) = x.dynlib = y.dynlib x.notes = gNotes append(c.optionStack, x) - for i in countup(start, sonsLen(n) - 1): + for i in countup(start, sonsLen(n) - 1): if processOption(c, n.sons[i]): # simply store it somewhere: if x.otherPragmas.isNil: x.otherPragmas = newNodeI(nkPragma, n.info) x.otherPragmas.add n.sons[i] #localError(n.info, errOptionExpected) - -proc processPop(c: PContext, n: PNode) = - if c.optionStack.counter <= 1: + +proc processPop(c: PContext, n: PNode) = + if c.optionStack.counter <= 1: localError(n.info, errAtPopWithoutPush) - else: - gOptions = POptionEntry(c.optionStack.tail).options + else: + gOptions = POptionEntry(c.optionStack.tail).options gNotes = POptionEntry(c.optionStack.tail).notes remove(c.optionStack, c.optionStack.tail) -proc processDefine(c: PContext, n: PNode) = - if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): +proc processDefine(c: PContext, n: PNode) = + if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): defineSymbol(n.sons[1].ident.s) message(n.info, warnDeprecated, "define") - else: + else: invalidPragma(n) - -proc processUndef(c: PContext, n: PNode) = - if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): + +proc processUndef(c: PContext, n: PNode) = + if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): undefSymbol(n.sons[1].ident.s) message(n.info, warnDeprecated, "undef") - else: + else: invalidPragma(n) - -type - TLinkFeature = enum + +type + TLinkFeature = enum linkNormal, linkSys -proc processCompile(c: PContext, n: PNode) = +proc processCompile(c: PContext, n: PNode) = var s = expectStrLit(c, n) var found = findFile(s) if found == "": found = s @@ -397,7 +397,7 @@ proc processCompile(c: PContext, n: PNode) = extccomp.addExternalFileToCompile(found) extccomp.addFileToLink(completeCFilePath(trunc, false)) -proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) = +proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) = var f = expectStrLit(c, n) if splitFile(f).ext == "": f = addFileExt(f, CC[cCompiler].objExt) var found = findFile(f) @@ -407,8 +407,8 @@ proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) = of linkSys: extccomp.addFileToLink(libpath / completeCFilePath(found, false)) else: internalError(n.info, "processCommonLink") - -proc pragmaBreakpoint(c: PContext, n: PNode) = + +proc pragmaBreakpoint(c: PContext, n: PNode) = discard getOptionalStr(c, n, "") proc pragmaWatchpoint(c: PContext, n: PNode) = @@ -427,59 +427,59 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode = return # now parse the string literal and substitute symbols: var a = 0 - while true: + while true: var b = strutils.find(str, marker, a) var sub = if b < 0: substr(str, a) else: substr(str, a, b - 1) if sub != "": addSon(result, newStrNode(nkStrLit, sub)) - if b < 0: break + if b < 0: break var c = strutils.find(str, marker, b + 1) if c < 0: sub = substr(str, b + 1) else: sub = substr(str, b + 1, c - 1) - if sub != "": + if sub != "": var e = searchInScopes(con, getIdent(sub)) - if e != nil: + if e != nil: if e.kind == skStub: loadStub(e) addSon(result, newSymNode(e)) - else: + else: addSon(result, newStrNode(nkStrLit, sub)) else: # an empty '``' produces a single '`' addSon(result, newStrNode(nkStrLit, $marker)) - if c < 0: break + if c < 0: break a = c + 1 else: illFormedAstLocal(n) result = newNode(nkAsmStmt, n.info) - -proc pragmaEmit(c: PContext, n: PNode) = + +proc pragmaEmit(c: PContext, n: PNode) = discard getStrLitNode(c, n) n.sons[1] = semAsmOrEmit(c, n, '`') -proc noVal(n: PNode) = +proc noVal(n: PNode) = if n.kind == nkExprColonExpr: invalidPragma(n) -proc pragmaUnroll(c: PContext, n: PNode) = - if c.p.nestedLoopCounter <= 0: +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: + if unrollFactor <% 32: n.sons[1] = newIntNode(nkIntLit, unrollFactor) - else: + else: invalidPragma(n) proc pragmaLine(c: PContext, n: PNode) = if n.kind == nkExprColonExpr: n.sons[1] = c.semConstExpr(c, n.sons[1]) let a = n.sons[1] - if a.kind == nkPar: + if a.kind == nkPar: var x = a.sons[0] var y = a.sons[1] if x.kind == nkExprColonExpr: x = x.sons[1] if y.kind == nkExprColonExpr: y = y.sons[1] - if x.kind != nkStrLit: + if x.kind != nkStrLit: localError(n.info, errStringLiteralExpected) - elif y.kind != nkIntLit: + elif y.kind != nkIntLit: localError(n.info, errIntLiteralExpected) else: n.info.fileIndex = msgs.fileInfoIdx(x.strVal) @@ -490,12 +490,12 @@ proc pragmaLine(c: PContext, n: PNode) = # sensible default: n.info = getInfoContext(-1) -proc processPragma(c: PContext, n: PNode, i: int) = +proc processPragma(c: PContext, n: PNode, i: int) = var it = n.sons[i] if it.kind != nkExprColonExpr: invalidPragma(n) elif it.sons[0].kind != nkIdent: invalidPragma(n) elif it.sons[1].kind != nkIdent: invalidPragma(n) - + var userPragma = newSym(skTemplate, it.sons[1].ident, nil, it.info) var body = newNodeI(nkPragma, n.info) for j in i+1 .. sonsLen(n)-1: addSon(body, n.sons[j]) @@ -508,7 +508,7 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) = if t.kind != tyObject: localError(x.info, errGenerated, "invalid type for raises/tags list") x.typ = t - + if n.kind == nkExprColonExpr: let it = n.sons[1] if it.kind notin {nkCurly, nkBracket}: @@ -569,7 +569,7 @@ proc deprecatedStmt(c: PContext; pragma: PNode) = localError(n.info, "key:value pair expected") proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym = - if it.kind != nkExprColonExpr: + if it.kind != nkExprColonExpr: invalidPragma(it); return let n = it[1] if n.kind == nkSym: @@ -592,9 +592,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, var key = if it.kind == nkExprColonExpr: it.sons[0] else: it if key.kind == nkIdent: var userPragma = strTableGet(c.userPragmas, key.ident) - if userPragma != nil: + if userPragma != nil: inc c.instCounter - if c.instCounter > 100: + if c.instCounter > 100: globalError(it.info, errRecursiveDependencyX, userPragma.name.s) pragma(c, sym, userPragma.ast, validPragmas) # ensure the pragma is also remember for generic instantiations in other @@ -603,9 +603,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, dec c.instCounter else: var k = whichKeyword(key.ident) - if k in validPragmas: + if k in validPragmas: case k - of wExportc: + of wExportc: makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info) incl(sym.flags, sfUsed) # avoid wrong hints of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1")) @@ -627,16 +627,16 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, var align = expectIntLit(c, it) if (not isPowerOfTwo(align) and align != 0) or align >% high(int16): localError(it.info, errPowerOfTwoExpected) - else: + else: sym.typ.align = align.int16 of wSize: if sym.typ == nil: invalidPragma(it) var size = expectIntLit(c, it) - if not isPowerOfTwo(size) or size <= 0 or size > 8: + if not isPowerOfTwo(size) or size <= 0 or size > 8: localError(it.info, errPowerOfTwoExpected) else: sym.typ.size = size - of wNodecl: + of wNodecl: noVal(it) incl(sym.loc.flags, lfNoDecl) of wPure, wAsmNoStackFrame: @@ -644,19 +644,19 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, if sym != nil: if k == wPure and sym.kind in routineKinds: invalidPragma(it) else: incl(sym.flags, sfPure) - of wVolatile: + of wVolatile: noVal(it) incl(sym.flags, sfVolatile) - of wRegister: + of wRegister: noVal(it) incl(sym.flags, sfRegister) - of wThreadVar: + of wThreadVar: noVal(it) incl(sym.flags, sfThread) of wDeadCodeElim: pragmaDeadCodeElim(c, it) of wNoForward: pragmaNoForward(c, it) of wMagic: processMagic(c, it, sym) - of wCompileTime: + of wCompileTime: noVal(it) incl(sym.flags, sfCompileTime) incl(sym.loc.flags, lfNoDecl) @@ -664,15 +664,18 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, noVal(it) incl(sym.flags, sfGlobal) incl(sym.flags, sfPure) - of wMerge: + of wMerge: + # only supported for backwards compat, doesn't do anything anymore + noVal(it) + of wConstructor: noVal(it) - incl(sym.flags, sfMerge) - of wHeader: + incl(sym.flags, sfConstructor) + of wHeader: var lib = getLib(c, libHeader, getStrLitNode(c, it)) addToLib(lib, sym) incl(sym.flags, sfImportc) incl(sym.loc.flags, lfHeader) - incl(sym.loc.flags, lfNoDecl) + incl(sym.loc.flags, lfNoDecl) # implies nodecl, because otherwise header would not make sense if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s) of wDestructor: @@ -685,13 +688,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, noVal(it) incl(sym.flags, sfNoSideEffect) if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect) - of wSideeffect: + of wSideeffect: noVal(it) incl(sym.flags, sfSideEffect) - of wNoreturn: + of wNoreturn: noVal(it) incl(sym.flags, sfNoReturn) - of wDynlib: + of wDynlib: processDynLib(c, it, sym) of wCompilerproc: noVal(it) # compilerproc may not get a string! @@ -703,7 +706,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, if it.kind == nkExprColonExpr: deprecatedStmt(c, it) elif sym != nil: incl(sym.flags, sfDeprecated) else: incl(c.module.flags, sfDeprecated) - of wVarargs: + of wVarargs: noVal(it) if sym.typ == nil: invalidPragma(it) else: incl(sym.typ.flags, tfVarargs) @@ -713,7 +716,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, else: noVal(it) incl(sym.flags, sfBorrow) - of wFinal: + of wFinal: noVal(it) if sym.typ == nil: invalidPragma(it) else: incl(sym.typ.flags, tfFinal) @@ -745,10 +748,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, else: incl(sym.typ.flags, tfPacked) of wHint: message(it.info, hintUser, expectStrLit(c, it)) of wWarning: message(it.info, warnUser, expectStrLit(c, it)) - of wError: + of wError: if sym != nil and sym.isRoutine: # This is subtle but correct: the error *statement* is only - # allowed for top level statements. Seems to be easier than + # allowed for top level statements. Seems to be easier than # distinguishing properly between # ``proc p() {.error}`` and ``proc p() = {.error: "msg".}`` noVal(it) @@ -765,11 +768,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, of wPassc: extccomp.addCompileOption(expectStrLit(c, it)) of wBreakpoint: pragmaBreakpoint(c, it) of wWatchPoint: pragmaWatchpoint(c, it) - of wPush: + of wPush: processPush(c, n, i + 1) - result = true + result = true of wPop: processPop(c, it) - of wPragma: + of wPragma: processPragma(c, n, i) result = true of wDiscardable: @@ -779,16 +782,16 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, noVal(it) if sym != nil: incl(sym.flags, sfNoInit) of wCodegenDecl: processCodegenDecl(c, it, sym) - of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, - wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, + of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, + wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wLinedir, wStacktrace, wLinetrace, wOptimization, - wCallconv, + wCallconv, wDebugger, wProfiler, wFloatchecks, wNanChecks, wInfChecks, wPatterns: if processOption(c, it): # calling conventions (boring...): localError(it.info, errOptionExpected) - of FirstCallConv..LastCallConv: + of FirstCallConv..LastCallConv: assert(sym != nil) if sym.typ == nil: invalidPragma(it) else: sym.typ.callConv = wordToCallConv(k) @@ -843,14 +846,14 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, of wInjectStmt: if it.kind != nkExprColonExpr: localError(it.info, errExprExpected) - else: + else: it.sons[1] = c.semExpr(c, it.sons[1]) of wExperimental: noVal(it) if isTopLevel(c): c.module.flags.incl sfExperimental else: - localError(it.info, "'experimental' pragma only valid as toplevel statement") + localError(it.info, "'experimental' pragma only valid as toplevel statement") else: invalidPragma(it) else: invalidPragma(it) else: processNote(c, it) @@ -884,7 +887,7 @@ proc hasPragma*(n: PNode, pragma: TSpecialWord): bool = var key = if p.kind == nkExprColonExpr: p[0] else: p if key.kind == nkIdent and whichKeyword(key.ident) == pragma: return true - + return false proc pragmaRec(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = diff --git a/compiler/sem.nim b/compiler/sem.nim index 36c0342cd..2d2f15fab 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -287,6 +287,7 @@ proc semConstExpr(c: PContext, n: PNode): PNode = return n result = getConstExpr(c.module, e) if result == nil: + #if e.kind == nkEmpty: globalError(n.info, errConstExprExpected) result = evalConstExpr(c.module, e) if result == nil or result.kind == nkEmpty: if e.info != n.info: diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 14644a8d6..48f54fa6c 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -8,12 +8,12 @@ # import - intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, + intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, wordrecg, strutils, options, guards # Second semantic checking pass over the AST. Necessary because the old # way had some inherent problems. Performs: -# +# # * effect+exception tracking # * "usage before definition" checking # * checks for invalid usages of compiletime magics (not implemented) @@ -23,7 +23,7 @@ import # Predefined effects: # io, time (time dependent), gc (performs GC'ed allocation), exceptions, # side effect (accesses global), store (stores into *type*), -# store_unknown (performs some store) --> store(any)|store(x) +# store_unknown (performs some store) --> store(any)|store(x) # load (loads from *type*), recursive (recursive call), unsafe, # endless (has endless loops), --> user effects are defined over *patterns* # --> a TR macro can annotate the proc with user defined annotations @@ -31,31 +31,31 @@ import # Load&Store analysis is performed on *paths*. A path is an access like # obj.x.y[i].z; splitting paths up causes some problems: -# +# # var x = obj.x # var z = x.y[i].z # # Alias analysis is affected by this too! A good solution is *type splitting*: -# T becomes T1 and T2 if it's known that T1 and T2 can't alias. -# +# T becomes T1 and T2 if it's known that T1 and T2 can't alias. +# # An aliasing problem and a race condition are effectively the same problem. # Type based alias analysis is nice but not sufficient; especially splitting # an array and filling it in parallel should be supported but is not easily # done: It essentially requires a built-in 'indexSplit' operation and dependent # typing. - + # ------------------------ exception and tag tracking ------------------------- discard """ exception tracking: - + a() # raises 'x', 'e' try: b() # raises 'e' except e: # must not undo 'e' here; hrm c() - + --> we need a stack of scopes for this analysis # XXX enhance the algorithm to care about 'dirty' expressions: @@ -209,8 +209,7 @@ proc useVar(a: PEffects, n: PNode) = a.init.add s.id if {sfGlobal, sfThread} * s.flags == {sfGlobal} and s.kind in {skVar, skLet}: if s.guard != nil: guardGlobal(a, n, s.guard) - if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem) and - tfGcSafe notin s.typ.flags: + if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem): if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n) markGcUnsafe(a) @@ -321,7 +320,7 @@ proc trackTryStmt(tracked: PEffects, n: PNode) = dec tracked.inTryStmt for i in oldState.. <tracked.init.len: addToIntersection(inter, tracked.init[i]) - + var branches = 1 var hasFinally = false for i in 1 .. < n.len: @@ -345,7 +344,7 @@ proc trackTryStmt(tracked: PEffects, n: PNode) = setLen(tracked.init, oldState) track(tracked, b.sons[blen-1]) hasFinally = true - + tracked.bottom = oldBottom if not hasFinally: setLen(tracked.init, oldState) @@ -356,7 +355,7 @@ proc isIndirectCall(n: PNode, owner: PSym): bool = # we don't count f(...) as an indirect call if 'f' is an parameter. # Instead we track expressions of type tyProc too. See the manual for # details: - if n.kind != nkSym: + if n.kind != nkSym: result = true elif n.sym.kind == skParam: result = owner != n.sym.owner or owner == nil @@ -366,13 +365,13 @@ proc isIndirectCall(n: PNode, owner: PSym): bool = proc isForwardedProc(n: PNode): bool = result = n.kind == nkSym and sfForward in n.sym.flags -proc trackPragmaStmt(tracked: PEffects, n: PNode) = - for i in countup(0, sonsLen(n) - 1): +proc trackPragmaStmt(tracked: PEffects, n: PNode) = + for i in countup(0, sonsLen(n) - 1): var it = n.sons[i] if whichPragma(it) == wEffects: # list the computed effects up to here: listEffects(tracked) - + proc effectSpec(n: PNode, effectType: TSpecialWord): PNode = for i in countup(0, sonsLen(n) - 1): var it = n.sons[i] @@ -387,12 +386,12 @@ proc documentEffect(n, x: PNode, effectType: TSpecialWord, idx: int): PNode = let spec = effectSpec(x, effectType) if isNil(spec): let s = n.sons[namePos].sym - + let actual = s.typ.n.sons[0] if actual.len != effectListLen: return let real = actual.sons[idx] - - # warning: hack ahead: + + # warning: hack ahead: var effects = newNodeI(nkBracket, n.info, real.len) for i in 0 .. <real.len: var t = typeToString(real[i].typ) @@ -409,7 +408,7 @@ proc documentRaises*(n: PNode) = let pragmas = n.sons[pragmasPos] let p1 = documentEffect(n, pragmas, wRaises, exceptionEffects) let p2 = documentEffect(n, pragmas, wTags, tagEffects) - + if p1 != nil or p2 != nil: if pragmas.kind == nkEmpty: n.sons[pragmasPos] = newNodeI(nkPragma, n.info) @@ -445,7 +444,7 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) = let pragma = s.ast.sons[pragmasPos] let spec = effectSpec(pragma, wRaises) mergeEffects(tracked, spec, n) - + let tagSpec = effectSpec(pragma, wTags) mergeTags(tracked, tagSpec, n) @@ -456,17 +455,17 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) = proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) = let n = n.skipConv - if paramType != nil and tfNotNil in paramType.flags and + if paramType != nil and tfNotNil in paramType.flags and n.typ != nil and tfNotNil notin n.typ.flags: if n.kind == nkAddr: # addr(x[]) can't be proven, but addr(x) can: if not containsNode(n, {nkDerefExpr, nkHiddenDeref}): return - elif n.kind == nkSym and n.sym.kind in routineKinds: + elif (n.kind == nkSym and n.sym.kind in routineKinds) or n.kind in procDefs: # 'p' is not nil obviously: return case impliesNotNil(tracked.guards, n) of impUnknown: - message(n.info, errGenerated, + message(n.info, errGenerated, "cannot prove '$1' is not nil" % n.renderTree) of impNo: message(n.info, errGenerated, "'$1' is provably nil" % n.renderTree) @@ -517,7 +516,7 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) = proc breaksBlock(n: PNode): bool = case n.kind of nkStmtList, nkStmtListExpr: - for c in n: + for c in n: if breaksBlock(c): return true of nkBreakStmt, nkReturnStmt, nkRaiseStmt: return true @@ -545,7 +544,7 @@ proc trackCase(tracked: PEffects, n: PNode) = if not breaksBlock(branch.lastSon): inc toCover for i in oldState.. <tracked.init.len: addToIntersection(inter, tracked.init[i]) - + let exh = case skipTypes(n.sons[0].typ, abstractVarRange-{tyTypeDesc}).kind of tyFloat..tyFloat128, tyString: lastSon(n).kind == nkElse @@ -590,7 +589,7 @@ proc trackIf(tracked: PEffects, n: PNode) = if count >= toCover: tracked.init.add id # else we can't merge as it is not exhaustive setLen(tracked.guards, oldFacts) - + proc trackBlock(tracked: PEffects, n: PNode) = if n.kind in {nkStmtList, nkStmtListExpr}: var oldState = -1 @@ -782,7 +781,7 @@ proc checkMethodEffects*(disp, branch: PSym) = checkRaisesSpec(tagsSpec, actual.sons[tagEffects], "can have an unlisted effect: ", hints=off, subtypeRelation) if sfThread in disp.flags and notGcSafe(branch.typ): - localError(branch.info, "base method is GC-safe, but '$1' is not" % + localError(branch.info, "base method is GC-safe, but '$1' is not" % branch.name.s) if branch.typ.lockLevel > disp.typ.lockLevel: when true: @@ -814,14 +813,14 @@ proc initEffects(effects: PNode; s: PSym; t: var TEffects) = newSeq(effects.sons, effectListLen) effects.sons[exceptionEffects] = newNodeI(nkArgList, s.info) effects.sons[tagEffects] = newNodeI(nkArgList, s.info) - + t.exc = effects.sons[exceptionEffects] t.tags = effects.sons[tagEffects] t.owner = s t.init = @[] t.guards = @[] t.locked = @[] - + proc trackProc*(s: PSym, body: PNode) = var effects = s.typ.n.sons[0] internalAssert effects.kind == nkEffectList diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 8a9f4a988..245f86427 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -352,7 +352,7 @@ proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType = for i in countup(0, sonsLen(n) - 1): addSonSkipIntLit(result, semTypeNode(c, n.sons[i], nil)) -proc semTuple(c: PContext, n: PNode, prev: PType): PType = +proc semTuple(c: PContext, n: PNode, prev: PType): PType = var typ: PType result = newOrPrevType(tyTuple, prev, c) result.n = newNodeI(nkRecList, n.info) @@ -800,7 +800,9 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, for i in 0 .. paramType.sonsLen - 2: if paramType.sons[i].kind == tyStatic: - result.rawAddSon makeTypeFromExpr(c, ast.emptyNode) # aka 'tyUnknown' + var x = copyNode(ast.emptyNode) + x.typ = paramType.sons[i] + result.rawAddSon makeTypeFromExpr(c, x) # aka 'tyUnknown' else: result.rawAddSon newTypeS(tyAnything, c) @@ -1045,8 +1047,8 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = var m = newCandidate(c, t) matches(c, n, copyTree(n), m) - if m.state != csMatch: - var err = "cannot instantiate " & typeToString(t) & "\n" & + if m.state != csMatch and not m.typedescMatched: + let err = "cannot instantiate " & typeToString(t) & "\n" & "got: (" & describeArgs(c, n) & ")\n" & "but expected: (" & describeArgs(c, t.n, 0) & ")" localError(n.info, errGenerated, err) diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 012782730..9e0716114 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -34,9 +34,9 @@ proc checkPartialConstructedType(info: TLineInfo, t: PType) = proc checkConstructedType*(info: TLineInfo, typ: PType) = var t = typ.skipTypes({tyDistinct}) if t.kind in tyTypeClasses: discard - elif tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject: + elif tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject: localError(info, errInvalidPragmaX, "acyclic") - elif t.kind == tyVar and t.sons[0].kind == tyVar: + elif t.kind == tyVar and t.sons[0].kind == tyVar: localError(info, errVarVarTypeNotAllowed) elif computeSize(t) == szIllegalRecursion: localError(info, errIllegalRecursionInTypeX, typeToString(t)) @@ -44,7 +44,7 @@ proc checkConstructedType*(info: TLineInfo, typ: PType) = sharedPtrCheck(info, t) when false: if t.kind == tyObject and t.sons[0] != nil: - if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags: + if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags: localError(info, errInheritanceOnlyWithNonFinalObjects) proc searchInstTypes*(key: PType): PType = @@ -69,7 +69,7 @@ proc searchInstTypes*(key: PType): PType = if not compareTypes(inst.sons[j], key.sons[j], flags = {ExactGenericParams}): break matchType - + return inst proc cacheTypeInst*(inst: PType) = @@ -79,7 +79,7 @@ proc cacheTypeInst*(inst: PType) = genericTyp.sym.typeInstCache.safeAdd(inst) type - TReplTypeVars* {.final.} = object + TReplTypeVars* {.final.} = object c*: PContext typeMap*: TIdTable # map PType to PType symMap*: TIdTable # map PSym to PSym @@ -151,7 +151,7 @@ proc reResolveCallsWithTypedescParams(cl: var TReplTypeVars, n: PNode): PNode = if needsFixing: n.sons[0] = newSymNode(n.sons[0].sym.owner) return cl.c.semOverloadedCall(cl.c, n, n, {skProc}) - + for i in 0 .. <n.safeLen: n.sons[i] = reResolveCallsWithTypedescParams(cl, n[i]) @@ -203,18 +203,18 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode = newSons(result, length) for i in countup(0, length - 1): result.sons[i] = replaceTypeVarsN(cl, n.sons[i]) - -proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym = + +proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym = if s == nil: return nil result = PSym(idTableGet(cl.symMap, s)) - if result == nil: + if result == nil: result = copySym(s, false) incl(result.flags, sfFromGeneric) idTablePut(cl.symMap, s, result) result.owner = s.owner result.typ = replaceTypeVarsT(cl, s.typ) result.ast = replaceTypeVarsN(cl, s.ast) - + proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType = result = PType(idTableGet(cl.typeMap, t)) if result == nil: @@ -234,7 +234,7 @@ proc instCopyType*(cl: var TReplTypeVars, t: PType): PType = result.flags.incl tfFromGeneric result.flags.excl tfInstClearedFlags -proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = +proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = # tyGenericInvocation[A, tyGenericInvocation[A, B]] # is difficult to handle: var body = t.sons[0] @@ -256,7 +256,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = propagateToOwner(header, x) else: propagateToOwner(header, x) - + if header != t: # search again after first pass: result = searchInstTypes(header) @@ -282,7 +282,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = header.sons[i] = x propagateToOwner(header, x) idTablePut(cl.typeMap, body.sons[i-1], x) - + for i in countup(1, sonsLen(t) - 1): # if one of the params is not concrete, we cannot do anything # but we already raised an error! @@ -310,7 +310,7 @@ proc eraseVoidParams*(t: PType) = # don't deal with '(): void': if t.sons[0] != nil and t.sons[0].kind == tyEmpty: t.sons[0] = nil - + for i in 1 .. <t.sonsLen: # don't touch any memory unless necessary if t.sons[i].kind == tyEmpty: @@ -332,7 +332,7 @@ proc skipIntLiteralParams*(t: PType) = if skipped != p: t.sons[i] = skipped if i > 0: t.n.sons[i].sym.typ = skipped - + # when the typeof operator is used on a static input # param, the results gets infected with static as well: if t.sons[0] != nil and t.sons[0].kind == tyStatic: @@ -359,7 +359,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = if t.kind in {tyStatic, tyGenericParam, tyIter} + tyTypeClasses: let lookup = PType(idTableGet(cl.typeMap, t)) if lookup != nil: return lookup - + case t.kind of tyGenericInvocation: result = handleGenericInvocation(cl, t) @@ -373,7 +373,8 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = if cl.allowMetaTypes: return assert t.n.typ != t var n = prepareNode(cl, t.n) - n = cl.c.semConstExpr(cl.c, n) + if n.kind != nkEmpty: + n = cl.c.semConstExpr(cl.c, n) if n.typ.kind == tyTypeDesc: # XXX: sometimes, chained typedescs enter here. # It may be worth investigating why this is happening, @@ -394,7 +395,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = of tyInt, tyFloat: result = skipIntLit(t) - + of tyTypeDesc: let lookup = PType(idTableGet(cl.typeMap, t)) # lookupTypeVar(cl, t) if lookup != nil: @@ -402,7 +403,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = if tfUnresolved in t.flags: result = result.base elif t.sons[0].kind != tyNone: result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t.sons[0])) - + of tyUserTypeClass: result = t @@ -411,31 +412,31 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = for i in 1 .. <result.sonsLen: result.sons[i] = replaceTypeVarsT(cl, result.sons[i]) propagateToOwner(result, result.lastSon) - + else: if containsGenericType(t): result = instCopyType(cl, t) result.size = -1 # needs to be recomputed - + for i in countup(0, sonsLen(result) - 1): if result.sons[i] != nil: result.sons[i] = replaceTypeVarsT(cl, result.sons[i]) propagateToOwner(result, result.sons[i]) result.n = replaceTypeVarsN(cl, result.n) - + case result.kind of tyArray: let idx = result.sons[0] internalAssert idx.kind != tyStatic - + of tyObject, tyTuple: propagateFieldFlags(result, result.n) - + of tyProc: eraseVoidParams(result) skipIntLiteralParams(result) - + else: discard proc initTypeVars*(p: PContext, pt: TIdTable, info: TLineInfo): TReplTypeVars = @@ -450,7 +451,7 @@ proc replaceTypesInBody*(p: PContext, pt: TIdTable, n: PNode): PNode = pushInfoContext(n.info) result = replaceTypeVarsN(cl, n) popInfoContext() - + proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo, t: PType): PType = var cl = initTypeVars(p, pt, info) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index e56d82a5b..38340ffb7 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -46,7 +46,7 @@ type # be instantiated coerceDistincts*: bool # this is an explicit coercion that can strip away # a distrinct type - typedescMatched: bool + typedescMatched*: bool inheritancePenalty: int # to prefer closest father object type errors*: CandidateErrors # additional clarifications to be displayed to the # user if overload resolution fails @@ -989,7 +989,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = else: internalAssert a.sons != nil and a.sons.len > 0 c.typedescMatched = true - result = typeRel(c, f.base, a.skipTypes({tyGenericParam, tyTypeDesc})) + var aa = a + while aa.kind in {tyTypeDesc, tyGenericParam} and + aa.len > 0: + aa = lastSon(aa) + result = typeRel(c, f.base, aa) if result > isGeneric: result = isGeneric else: result = isNone diff --git a/compiler/transf.nim b/compiler/transf.nim index 325ce9d5e..2143b6bec 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -579,8 +579,7 @@ proc getMergeOp(n: PNode): PSym = case n.kind of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix, nkCallStrLit: - if (n.sons[0].kind == nkSym) and (n.sons[0].sym.kind == skProc) and - (sfMerge in n.sons[0].sym.flags): + if n.sons[0].kind == nkSym and n.sons[0].sym.magic == mConStrStr: result = n.sons[0].sym else: discard diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 11d839c41..2b80f6aed 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -28,7 +28,7 @@ proc opGorge*(cmd, input: string): string = except IOError, OSError: result = "" -proc opSlurp*(file: string, info: TLineInfo, module: PSym): string = +proc opSlurp*(file: string, info: TLineInfo, module: PSym): string = try: let filename = file.findFile result = readFile(filename) @@ -87,7 +87,12 @@ proc mapTypeToAst(t: PType, info: TLineInfo; allowRecursion=false): PNode = result.add mapTypeToAst(t.sons[i], info) of tyGenericInst, tyGenericBody, tyOrdinal, tyUserTypeClassInst: result = mapTypeToAst(t.lastSon, info) - of tyGenericParam, tyDistinct, tyForward: result = atomicType(t.sym.name.s) + of tyDistinct: + if allowRecursion: + result = mapTypeToBracket("distinct", t, info) + else: + result = atomicType(t.sym.name.s) + of tyGenericParam, tyForward: result = atomicType(t.sym.name.s) of tyObject: if allowRecursion: result = newNodeIT(nkObjectTy, info, t) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 5b7b0b0fd..2383e2542 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -15,7 +15,7 @@ # this doesn't matter. However it matters for strings and other complex # types that use the 'node' field; the reason is that slots are # re-used in a register based VM. Example: -# +# # .. code-block:: nim # let s = a & b # no matter what, create fresh node # s = a & b # no matter what, keep the node @@ -64,17 +64,17 @@ proc codeListing(c: PCtx, result: var string, start=0; last = -1) = let y = c.code[i+1] let z = c.code[i+2] result.addf("\t$#\tr$#, r$#, $#, $#", ($opc).substr(3), x.regA, x.regB, - c.types[y.regBx-wordExcess].typeToString, + c.types[y.regBx-wordExcess].typeToString, c.types[z.regBx-wordExcess].typeToString) inc i, 2 elif opc < firstABxInstr: - result.addf("\t$#\tr$#, r$#, r$#", ($opc).substr(3), x.regA, + result.addf("\t$#\tr$#, r$#, r$#", ($opc).substr(3), x.regA, x.regB, x.regC) elif opc in relativeJumps: result.addf("\t$#\tr$#, L$#", ($opc).substr(3), x.regA, i+x.regBx-wordExcess) elif opc in {opcLdConst, opcAsgnConst}: - result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA, + result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA, c.constants[x.regBx-wordExcess].renderTree) else: result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA, x.regBx-wordExcess) @@ -117,7 +117,7 @@ proc gABx(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0; bx: int) = # Applies `opc` to `bx` and stores it into register `a` # `bx` must be signed and in the range [-32767, 32768] if bx >= -32767 and bx <= 32768: - let ins = (opc.uint32 or a.uint32 shl 8'u32 or + let ins = (opc.uint32 or a.uint32 shl 8'u32 or (bx+wordExcess).uint32 shl 16'u32).TInstr c.code.add(ins) c.debug.add(n.info) @@ -174,7 +174,7 @@ proc getTemp(c: PCtx; typ: PType): TRegister = if c.slots[i].kind == k and not c.slots[i].inUse: c.slots[i].inUse = true return TRegister(i) - + # if register pressure is high, we re-use more aggressively: if c.maxSlots >= HighRegisterPressure: for i in 0 .. c.maxSlots-1: @@ -208,7 +208,7 @@ proc getTempRange(c: PCtx; n: int; kind: TSlotKind): TRegister = result = TRegister(c.maxSlots) inc c.maxSlots, n for k in result .. result+n-1: c.slots[k] = (inUse: true, kind: kind) - + proc freeTempRange(c: PCtx; start: TRegister, n: int) = for i in start .. start+n-1: c.freeTemp(TRegister(i)) @@ -217,7 +217,7 @@ template withTemp(tmp, typ: expr, body: stmt) {.immediate, dirty.} = body c.freeTemp(tmp) -proc popBlock(c: PCtx; oldLen: int) = +proc popBlock(c: PCtx; oldLen: int) = for f in c.prc.blocks[oldLen].fixups: c.patch(f) c.prc.blocks.setLen(oldLen) @@ -386,7 +386,7 @@ proc genLiteral(c: PCtx; n: PNode): int = result = rawGenLiteral(c, n) proc unused(n: PNode; x: TDest) {.inline.} = - if x >= 0: + if x >= 0: #debug(n) internalError(n.info, "not unused") @@ -446,11 +446,11 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) = var blen = len(it) # first opcExcept contains the end label of the 'except' block: let endExcept = c.xjmp(it, opcExcept, 0) - for j in countup(0, blen - 2): + for j in countup(0, blen - 2): assert(it.sons[j].kind == nkType) let typ = it.sons[j].typ.skipTypes(abstractPtrs-{tyTypeDesc}) c.gABx(it, opcExcept, 0, c.genType(typ)) - if blen == 1: + if blen == 1: # general except section: c.gABx(it, opcExcept, 0, 0) c.gen(it.lastSon, dest) @@ -498,7 +498,7 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) = template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar proc isGlobal(n: PNode): bool = n.kind == nkSym and isGlobal(n.sym) -proc needsAsgnPatch(n: PNode): bool = +proc needsAsgnPatch(n: PNode): bool = n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr, nkDerefExpr, nkHiddenDeref} or (n.kind == nkSym and n.sym.isGlobal) @@ -552,9 +552,9 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) = proc genNew(c: PCtx; n: PNode) = let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ) else: c.genx(n.sons[1]) - # we use the ref's base type here as the VM conflates 'ref object' + # we use the ref's base type here as the VM conflates 'ref object' # and 'object' since internally we already have a pointer. - c.gABx(n, opcNew, dest, + c.gABx(n, opcNew, dest, c.genType(n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).sons[0])) c.genAsgnPatch(n.sons[1], dest) c.freeTemp(dest) @@ -657,7 +657,7 @@ proc genUnaryStmt(c: PCtx; n: PNode; opc: TOpcode) = proc genVarargsABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) = if dest < 0: dest = getTemp(c, n.typ) var x = c.getTempRange(n.len-1, slotTempStr) - for i in 1..n.len-1: + for i in 1..n.len-1: var r: TRegister = x+i-1 c.gen(n.sons[i], r) c.gABC(n, opc, dest, x, n.len-1) @@ -681,7 +681,7 @@ proc genAddSubInt(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) = genBinaryABC(c, n, dest, opc) c.genNarrow(n, dest) -proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) = +proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) = let tmp = c.genx(arg) if dest < 0: dest = c.getTemp(n.typ) c.gABC(n, opc, dest, tmp) @@ -792,12 +792,12 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = genNarrow(c, n, dest) of mUnaryMinusF64: genUnaryABC(c, n, dest, opcUnaryMinusFloat) of mUnaryPlusI, mUnaryPlusI64, mUnaryPlusF64: gen(c, n.sons[1], dest) - of mBitnotI, mBitnotI64: + of mBitnotI, mBitnotI64: genUnaryABC(c, n, dest, opcBitnotInt) genNarrowU(c, n, dest) of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, - mToU8, mToU16, mToU32, mToFloat, mToBiggestFloat, mToInt, - mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, + mToU8, mToU16, mToU32, mToFloat, mToBiggestFloat, mToInt, + mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr: genConv(c, n, n.sons[1], dest) of mEqStr: genBinaryABC(c, n, dest, opcEqStr) @@ -825,7 +825,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = c.gABC(n, if m == mSetLengthStr: opcSetLenStr else: opcSetLenSeq, d, tmp) c.genAsgnPatch(n.sons[1], d) c.freeTemp(tmp) - of mSwap: + of mSwap: unused(n, dest) var d1 = c.genx(n.sons[1]) @@ -874,7 +874,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = c.freeTemp(tmp1) c.freeTemp(tmp3) c.genAsgnPatch(d2AsNode, d2) - c.freeTemp(d2) + c.freeTemp(d2) of mReset: unused(n, dest) var d = c.genx(n.sons[1]) @@ -913,7 +913,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = of mAppendStrCh: unused(n, dest) genBinaryStmtVar(c, n, opcAddStrCh) - of mAppendStrStr: + of mAppendStrStr: unused(n, dest) genBinaryStmtVar(c, n, opcAddStrStr) of mAppendSeqElem: @@ -923,7 +923,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = genUnaryABC(c, n, dest, opcParseExprToAst) of mParseStmtToAst: genUnaryABC(c, n, dest, opcParseStmtToAst) - of mTypeTrait: + of mTypeTrait: let tmp = c.genx(n.sons[1]) if dest < 0: dest = c.getTemp(n.typ) c.gABx(n, opcSetType, tmp, c.genType(n.sons[1].typ)) @@ -960,19 +960,19 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = of mNSetIntVal: unused(n, dest) genBinaryStmt(c, n, opcNSetIntVal) - of mNSetFloatVal: + of mNSetFloatVal: unused(n, dest) genBinaryStmt(c, n, opcNSetFloatVal) of mNSetSymbol: unused(n, dest) genBinaryStmt(c, n, opcNSetSymbol) - of mNSetIdent: + of mNSetIdent: unused(n, dest) genBinaryStmt(c, n, opcNSetIdent) of mNSetType: unused(n, dest) genBinaryStmt(c, n, opcNSetType) - of mNSetStrVal: + of mNSetStrVal: unused(n, dest) genBinaryStmt(c, n, opcNSetStrVal) of mNNewNimNode: genBinaryABC(c, n, dest, opcNNewNimNode) @@ -990,10 +990,10 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent) of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode) of mNLineInfo: genUnaryABC(c, n, dest, opcNLineInfo) - of mNHint: + of mNHint: unused(n, dest) genUnaryStmt(c, n, opcNHint) - of mNWarning: + of mNWarning: unused(n, dest) genUnaryStmt(c, n, opcNWarning) of mNError: @@ -1024,7 +1024,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = else: globalError(n.info, "expandToAst requires a call expression") else: - # mGCref, mGCunref, + # mGCref, mGCunref, internalError(n.info, "cannot generate code for: " & $m) const @@ -1056,7 +1056,7 @@ proc unneededIndirection(n: PNode): bool = n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind == tyRef proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; - flags: TGenFlags) = + flags: TGenFlags) = # a nop for certain types let isAddr = opc in {opcAddrNode, opcAddrReg} let newflags = if isAddr: flags+{gfAddrOf} else: flags @@ -1144,7 +1144,7 @@ proc checkCanEval(c: PCtx; n: PNode) = # proc foo() = var x ... let s = n.sym if {sfCompileTime, sfGlobal} <= s.flags: return - if s.kind in {skVar, skTemp, skLet, skParam, skResult} and + if s.kind in {skVar, skTemp, skLet, skParam, skResult} and not s.isOwnedBy(c.prc.sym) and s.owner != c.module: cannotEval(n) @@ -1338,27 +1338,27 @@ proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = else: genArrAccess2(c, n, dest, opcLdArr, flags) -proc getNullValueAux(obj: PNode, result: PNode) = +proc getNullValueAux(obj: PNode, result: PNode) = case obj.kind of nkRecList: for i in countup(0, sonsLen(obj) - 1): getNullValueAux(obj.sons[i], result) of nkRecCase: getNullValueAux(obj.sons[0], result) - for i in countup(1, sonsLen(obj) - 1): + for i in countup(1, sonsLen(obj) - 1): getNullValueAux(lastSon(obj.sons[i]), result) of nkSym: addSon(result, getNullValue(obj.sym.typ, result.info)) else: internalError(result.info, "getNullValueAux") - -proc getNullValue(typ: PType, info: TLineInfo): PNode = + +proc getNullValue(typ: PType, info: TLineInfo): PNode = var t = skipTypes(typ, abstractRange-{tyTypeDesc}) result = emptyNode case t.kind - of tyBool, tyEnum, tyChar, tyInt..tyInt64: + of tyBool, tyEnum, tyChar, tyInt..tyInt64: result = newNodeIT(nkIntLit, info, t) of tyUInt..tyUInt64: result = newNodeIT(nkUIntLit, info, t) - of tyFloat..tyFloat128: + of tyFloat..tyFloat128: result = newNodeIT(nkFloatLit, info, t) of tyCString, tyString: result = newNodeIT(nkStrLit, info, t) @@ -1372,7 +1372,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode = result = newNodeIT(nkPar, info, t) result.add(newNodeIT(nkNilLit, info, t)) result.add(newNodeIT(nkNilLit, info, t)) - of tyObject: + of tyObject: result = newNodeIT(nkPar, info, t) getNullValueAux(t.n, result) # initialize inherited fields: @@ -1380,9 +1380,9 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode = while base != nil: getNullValueAux(skipTypes(base, skipPtrs).n, result) base = base.sons[0] - of tyArray, tyArrayConstr: + of tyArray, tyArrayConstr: result = newNodeIT(nkBracket, info, t) - for i in countup(0, int(lengthOrd(t)) - 1): + for i in countup(0, int(lengthOrd(t)) - 1): addSon(result, getNullValue(elemType(t), info)) of tyTuple: result = newNodeIT(nkPar, info, t) @@ -1459,7 +1459,7 @@ proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) = c.gABx(n, opcNewSeq, dest, c.genType(seqType)) c.gABx(n, opcNewSeq, tmp, 0) c.freeTemp(tmp) - + if n.len > 0: var tmp = getTemp(c, intType) c.gABx(n, opcLdNullReg, tmp, c.genType(intType)) @@ -1536,7 +1536,7 @@ proc procIsCallback(c: PCtx; s: PSym): bool = if s.offset < -1: return true var i = -2 for key, value in items(c.callbacks): - if s.matches(key): + if s.matches(key): doAssert s.offset == -1 s.offset = i return true @@ -1584,7 +1584,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = of nkNilLit: if not n.typ.isEmptyType: genLit(c, getNullValue(n.typ, n.info), dest) else: unused(n, dest) - of nkAsgn, nkFastAsgn: + of nkAsgn, nkFastAsgn: unused(n, dest) genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn) of nkDotExpr: genObjAccess(c, n, dest, flags) @@ -1633,7 +1633,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = let s = n.sons[namePos].sym discard genProc(c, s) genLit(c, n.sons[namePos], dest) - of nkChckRangeF, nkChckRange64, nkChckRange: + of nkChckRangeF, nkChckRange64, nkChckRange: let tmp0 = c.genx(n.sons[0]) tmp1 = c.genx(n.sons[1]) diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index ae036bc0c..393798947 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -13,44 +13,44 @@ # does not support strings. Without this the code would # be slow and unreadable. -import +import hashes, strutils, idents # Keywords must be kept sorted and within a range type - TSpecialWord* = enum - wInvalid, - - wAddr, wAnd, wAs, wAsm, wAtomic, - wBind, wBlock, wBreak, wCase, wCast, wConst, - wContinue, wConverter, wDefer, wDiscard, wDistinct, wDiv, wDo, + TSpecialWord* = enum + wInvalid, + + wAddr, wAnd, wAs, wAsm, wAtomic, + wBind, wBlock, wBreak, wCase, wCast, wConst, + wContinue, wConverter, wDefer, wDiscard, wDistinct, wDiv, wDo, wElif, wElse, wEnd, wEnum, wExcept, wExport, - wFinally, wFor, wFrom, wFunc, wGeneric, wIf, wImport, wIn, + wFinally, wFor, wFrom, wFunc, wGeneric, wIf, wImport, wIn, wInclude, wInterface, wIs, wIsnot, wIterator, wLet, - wMacro, wMethod, wMixin, wMod, wNil, - wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, - wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar, + wMacro, wMethod, wMixin, wMod, wNil, + wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, + wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar, wWhen, wWhile, wWith, wWithout, wXor, wYield, - + wColon, wColonColon, wEquals, wDot, wDotDot, wStar, wMinus, wMagic, wThread, wFinal, wProfiler, wObjChecks, wDestroy, - - wImmediate, wDestructor, wDelegator, wOverride, + + wImmediate, wConstructor, wDestructor, wDelegator, wOverride, wImportCpp, wImportObjC, wImportCompilerProc, wImportc, wExportc, wIncompleteStruct, wRequiresInit, wAlign, wNodecl, wPure, wSideeffect, wHeader, - wNosideeffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib, - wCompilerproc, wProcVar, - wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef, - wLinedir, wStacktrace, wLinetrace, wLink, wCompile, - wLinksys, wDeprecated, wVarargs, wCallconv, wBreakpoint, wDebugger, - wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline, - wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangechecks, + wNosideeffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib, + wCompilerproc, wProcVar, + wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef, + wLinedir, wStacktrace, wLinetrace, wLink, wCompile, + wLinksys, wDeprecated, wVarargs, wCallconv, wBreakpoint, wDebugger, + wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline, + wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangechecks, wBoundchecks, wOverflowchecks, wNilchecks, wFloatchecks, wNanChecks, wInfChecks, wAssertions, wPatterns, wWarnings, @@ -59,11 +59,11 @@ type wPragma, wCompileTime, wNoInit, wPassc, wPassl, wBorrow, wDiscardable, - wFieldChecks, - wWatchPoint, wSubsChar, - wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, + wFieldChecks, + wWatchPoint, wSubsChar, + wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wInjectStmt, wExperimental, - wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, + wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, wAsmNoStackFrame, wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks, @@ -82,38 +82,38 @@ type wStdIn, wStdOut, wStdErr, wInOut, wByCopy, wByRef, wOneWay, - + TSpecialWords* = set[TSpecialWord] -const +const oprLow* = ord(wColon) oprHigh* = ord(wDotDot) - + nimKeywordsLow* = ord(wAsm) nimKeywordsHigh* = ord(wYield) - + ccgKeywordsLow* = ord(wAuto) ccgKeywordsHigh* = ord(wOneWay) - + cppNimSharedKeywords* = { wAsm, wBreak, wCase, wConst, wContinue, wDo, wElse, wEnum, wExport, wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile, wUsing} - specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["", - - "addr", "and", "as", "asm", "atomic", - "bind", "block", "break", "case", "cast", + specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["", + + "addr", "and", "as", "asm", "atomic", + "bind", "block", "break", "case", "cast", "const", "continue", "converter", "defer", "discard", "distinct", "div", "do", - "elif", "else", "end", "enum", "except", "export", - "finally", "for", "from", "func", "generic", "if", + "elif", "else", "end", "enum", "except", "export", + "finally", "for", "from", "func", "generic", "if", "import", "in", "include", "interface", "is", "isnot", "iterator", "let", "macro", "method", "mixin", "mod", "nil", "not", "notin", - "object", "of", "or", + "object", "of", "or", "out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "static", - "template", "try", "tuple", "type", "using", "var", + "template", "try", "tuple", "type", "using", "var", "when", "while", "with", "without", "xor", "yield", @@ -122,22 +122,22 @@ const "magic", "thread", "final", "profiler", "objchecks", "destroy", - - "immediate", "destructor", "delegator", "override", + + "immediate", "constructor", "destructor", "delegator", "override", "importcpp", "importobjc", "importcompilerproc", "importc", "exportc", "incompletestruct", "requiresinit", "align", "nodecl", "pure", "sideeffect", - "header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib", - "compilerproc", "procvar", "fatal", "error", "warning", "hint", "line", - "push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace", - "link", "compile", "linksys", "deprecated", "varargs", - "callconv", "breakpoint", "debugger", "nimcall", "stdcall", + "header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib", + "compilerproc", "procvar", "fatal", "error", "warning", "hint", "line", + "push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace", + "link", "compile", "linksys", "deprecated", "varargs", + "callconv", "breakpoint", "debugger", "nimcall", "stdcall", "cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "closure", - "noconv", "on", "off", "checks", "rangechecks", "boundchecks", + "noconv", "on", "off", "checks", "rangechecks", "boundchecks", "overflowchecks", "nilchecks", "floatchecks", "nanchecks", "infchecks", - "assertions", "patterns", "warnings", "hints", + "assertions", "patterns", "warnings", "hints", "optimization", "raises", "writes", "reads", "size", "effects", "tags", "deadcodeelim", "safecode", "noforward", "pragma", @@ -149,7 +149,7 @@ const "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked", "guard", "locks", - + "auto", "bool", "catch", "char", "class", "const_cast", "default", "delete", "double", "dynamic_cast", "explicit", "extern", "false", @@ -169,22 +169,22 @@ const "inout", "bycopy", "byref", "oneway", ] -proc findStr*(a: openArray[string], s: string): int = - for i in countup(low(a), high(a)): - if cmpIgnoreStyle(a[i], s) == 0: +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: PIdent): TSpecialWord = +proc whichKeyword*(id: PIdent): TSpecialWord = if id.id < 0: result = wInvalid else: result = TSpecialWord(id.id) -proc whichKeyword*(id: string): TSpecialWord = +proc whichKeyword*(id: string): TSpecialWord = result = whichKeyword(getIdent(id)) - -proc initSpecials() = + +proc initSpecials() = # initialize the keywords: - for s in countup(succ(low(specialWords)), high(specialWords)): + for s in countup(succ(low(specialWords)), high(specialWords)): getIdent(specialWords[s], hashIgnoreStyle(specialWords[s])).id = ord(s) - + initSpecials() diff --git a/doc/nimc.txt b/doc/nimc.txt index c6b0b5255..831fce567 100644 --- a/doc/nimc.txt +++ b/doc/nimc.txt @@ -545,6 +545,20 @@ instead: let x = newFoo(3, 4) +Wrapping constructors +~~~~~~~~~~~~~~~~~~~~~ + +Sometimes a C++ class has a private copy constructor and so code like +``Class c = Class(1,2);`` must not be generated but instead ``Class c(1,2);``. +For this purpose the Nim proc that wraps a C++ constructor needs to be +annotated with the `constructor`:idx: pragma. This pragma also helps to generate +faster C++ code since construction then doesn't invoke the copy constructor: + +.. code-block:: nim + # a better constructor of 'Foo': + proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)", constructor.} + + Wrapping destructors ~~~~~~~~~~~~~~~~~~~~ @@ -608,7 +622,7 @@ allows *sloppy* interfacing with libraries written in Objective C: - (void)greet:(long)x y:(long)dummy { - printf("Hello, World!\n"); + printf("Hello, World!\n"); } @end diff --git a/lib/core/macros.nim b/lib/core/macros.nim index f73dbd241..c18e805e0 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -85,11 +85,11 @@ type ntyInt8, ntyInt16, ntyInt32, ntyInt64, ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128, ntyUInt, ntyUInt8, ntyUInt16, ntyUInt32, ntyUInt64, - ntyBigNum, - ntyConst, ntyMutable, ntyVarargs, + ntyBigNum, + ntyConst, ntyMutable, ntyVarargs, ntyIter, ntyError - + TNimTypeKinds* {.deprecated.} = set[NimTypeKind] NimSymKind* = enum nskUnknown, nskConditional, nskDynLib, nskParam, @@ -120,12 +120,10 @@ const nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand, nnkCallStrLit} -{.push warning[deprecated]: off.} - -proc `[]`*(n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild", noSideEffect.} +proc `[]`*(n: NimNode, i: int): NimNode {.magic: "NChild", noSideEffect.} ## get `n`'s `i`'th child. -proc `[]=`*(n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild", +proc `[]=`*(n: NimNode, i: int, child: NimNode) {.magic: "NSetChild", noSideEffect.} ## set `n`'s `i`'th child to `child`. @@ -141,34 +139,34 @@ proc `$`*(s: NimSym): string {.magic: "IdentToStr", noSideEffect.} proc `==`*(a, b: NimIdent): bool {.magic: "EqIdent", noSideEffect.} ## compares two Nim identifiers -proc `==`*(a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.} +proc `==`*(a, b: NimNode): bool {.magic: "EqNimrodNode", noSideEffect.} ## compares two Nim nodes -proc len*(n: PNimrodNode): int {.magic: "NLen", noSideEffect.} +proc len*(n: NimNode): int {.magic: "NLen", noSideEffect.} ## returns the number of children of `n`. -proc add*(father, child: PNimrodNode): PNimrodNode {.magic: "NAdd", discardable, +proc add*(father, child: NimNode): NimNode {.magic: "NAdd", discardable, noSideEffect, locks: 0.} ## Adds the `child` to the `father` node. Returns the ## father node so that calls can be nested. -proc add*(father: PNimrodNode, children: varargs[PNimrodNode]): PNimrodNode {. +proc add*(father: NimNode, children: varargs[NimNode]): NimNode {. magic: "NAddMultiple", discardable, noSideEffect, locks: 0.} ## Adds each child of `children` to the `father` node. ## Returns the `father` node so that calls can be nested. -proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel", noSideEffect.} +proc del*(father: NimNode, idx = 0, n = 1) {.magic: "NDel", noSideEffect.} ## deletes `n` children of `father` starting at index `idx`. -proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind", noSideEffect.} +proc kind*(n: NimNode): NimNodeKind {.magic: "NKind", noSideEffect.} ## returns the `kind` of the node `n`. -proc intVal*(n: PNimrodNode): BiggestInt {.magic: "NIntVal", noSideEffect.} -proc floatVal*(n: PNimrodNode): BiggestFloat {.magic: "NFloatVal", noSideEffect.} -proc symbol*(n: PNimrodNode): NimSym {.magic: "NSymbol", noSideEffect.} -proc ident*(n: PNimrodNode): NimIdent {.magic: "NIdent", noSideEffect.} +proc intVal*(n: NimNode): BiggestInt {.magic: "NIntVal", noSideEffect.} +proc floatVal*(n: NimNode): BiggestFloat {.magic: "NFloatVal", noSideEffect.} +proc symbol*(n: NimNode): NimSym {.magic: "NSymbol", noSideEffect.} +proc ident*(n: NimNode): NimIdent {.magic: "NIdent", noSideEffect.} -proc getType*(n: PNimrodNode): PNimrodNode {.magic: "NGetType", noSideEffect.} +proc getType*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.} ## with 'getType' you can access the node's `type`:idx:. A Nim type is ## mapped to a Nim AST too, so it's slightly confusing but it means the same ## API can be used to traverse types. Recursive types are flattened for you @@ -176,30 +174,30 @@ proc getType*(n: PNimrodNode): PNimrodNode {.magic: "NGetType", noSideEffect.} ## resolve recursive types, you have to call 'getType' again. To see what ## kind of type it is, call `typeKind` on getType's result. -proc typeKind*(n: PNimrodNode): NimTypeKind {.magic: "NGetType", noSideEffect.} +proc typeKind*(n: NimNode): NimTypeKind {.magic: "NGetType", noSideEffect.} ## Returns the type kind of the node 'n' that should represent a type, that ## means the node should have been obtained via `getType`. -proc strVal*(n: PNimrodNode): string {.magic: "NStrVal", noSideEffect.} +proc strVal*(n: NimNode): string {.magic: "NStrVal", noSideEffect.} -proc `intVal=`*(n: PNimrodNode, val: BiggestInt) {.magic: "NSetIntVal", noSideEffect.} -proc `floatVal=`*(n: PNimrodNode, val: BiggestFloat) {.magic: "NSetFloatVal", noSideEffect.} -proc `symbol=`*(n: PNimrodNode, val: NimSym) {.magic: "NSetSymbol", noSideEffect.} -proc `ident=`*(n: PNimrodNode, val: NimIdent) {.magic: "NSetIdent", noSideEffect.} -#proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".} +proc `intVal=`*(n: NimNode, val: BiggestInt) {.magic: "NSetIntVal", noSideEffect.} +proc `floatVal=`*(n: NimNode, val: BiggestFloat) {.magic: "NSetFloatVal", noSideEffect.} +proc `symbol=`*(n: NimNode, val: NimSym) {.magic: "NSetSymbol", noSideEffect.} +proc `ident=`*(n: NimNode, val: NimIdent) {.magic: "NSetIdent", noSideEffect.} +#proc `typ=`*(n: NimNode, typ: typedesc) {.magic: "NSetType".} # this is not sound! Unfortunately forbidding 'typ=' is not enough, as you # can easily do: # let bracket = semCheck([1, 2]) # let fake = semCheck(2.0) # bracket[0] = fake # constructs a mixed array with ints and floats! -proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal", noSideEffect.} +proc `strVal=`*(n: NimNode, val: string) {.magic: "NSetStrVal", noSideEffect.} -proc newNimNode*(kind: TNimrodNodeKind, - n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode", noSideEffect.} +proc newNimNode*(kind: NimNodeKind, + n: NimNode=nil): NimNode {.magic: "NNewNimNode", noSideEffect.} -proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode", noSideEffect.} -proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree", noSideEffect.} +proc copyNimNode*(n: NimNode): NimNode {.magic: "NCopyNimNode", noSideEffect.} +proc copyNimTree*(n: NimNode): NimNode {.magic: "NCopyNimTree", noSideEffect.} proc error*(msg: string) {.magic: "NError", benign.} ## writes an error message at compile time @@ -210,27 +208,27 @@ proc warning*(msg: string) {.magic: "NWarning", benign.} proc hint*(msg: string) {.magic: "NHint", benign.} ## writes a hint message at compile time -proc newStrLitNode*(s: string): PNimrodNode {.compileTime, noSideEffect.} = +proc newStrLitNode*(s: string): NimNode {.compileTime, noSideEffect.} = ## creates a string literal node from `s` result = newNimNode(nnkStrLit) result.strVal = s -proc newIntLitNode*(i: BiggestInt): PNimrodNode {.compileTime.} = +proc newIntLitNode*(i: BiggestInt): NimNode {.compileTime.} = ## creates a int literal node from `i` result = newNimNode(nnkIntLit) result.intVal = i -proc newFloatLitNode*(f: BiggestFloat): PNimrodNode {.compileTime.} = +proc newFloatLitNode*(f: BiggestFloat): NimNode {.compileTime.} = ## creates a float literal node from `f` result = newNimNode(nnkFloatLit) result.floatVal = f -proc newIdentNode*(i: NimIdent): PNimrodNode {.compileTime.} = +proc newIdentNode*(i: NimIdent): NimNode {.compileTime.} = ## creates an identifier node from `i` result = newNimNode(nnkIdent) result.ident = i -proc newIdentNode*(i: string): PNimrodNode {.compileTime.} = +proc newIdentNode*(i: string): NimNode {.compileTime.} = ## creates an identifier node from `i` result = newNimNode(nnkIdent) result.ident = !i @@ -247,7 +245,7 @@ type {.deprecated: [TBindSymRule: BindSymRule].} -proc bindSym*(ident: string, rule: BindSymRule = brClosed): PNimrodNode {. +proc bindSym*(ident: string, rule: BindSymRule = brClosed): NimNode {. magic: "NBindSym", noSideEffect.} ## creates a node that binds `ident` to a symbol node. The bound symbol ## may be an overloaded symbol. @@ -258,48 +256,48 @@ proc bindSym*(ident: string, rule: BindSymRule = brClosed): PNimrodNode {. ## If ``rule == brForceOpen`` always an ``nkOpenSymChoice`` tree is ## returned even if the symbol is not ambiguous. -proc genSym*(kind: NimSymKind = nskLet; ident = ""): PNimrodNode {. +proc genSym*(kind: NimSymKind = nskLet; ident = ""): NimNode {. magic: "NGenSym", noSideEffect.} ## generates a fresh symbol that is guaranteed to be unique. The symbol ## needs to occur in a declaration context. -proc callsite*(): PNimrodNode {.magic: "NCallSite", benign.} +proc callsite*(): NimNode {.magic: "NCallSite", benign.} ## returns the AST of the invocation expression that invoked this macro. -proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} = +proc toStrLit*(n: NimNode): NimNode {.compileTime.} = ## converts the AST `n` to the concrete Nim code and wraps that ## in a string literal node return newStrLitNode(repr(n)) -proc lineinfo*(n: PNimrodNode): string {.magic: "NLineInfo", noSideEffect.} +proc lineinfo*(n: NimNode): string {.magic: "NLineInfo", noSideEffect.} ## returns the position the node appears in the original source file ## in the form filename(line, col) -proc internalParseExpr(s: string): PNimrodNode {. +proc internalParseExpr(s: string): NimNode {. magic: "ParseExprToAst", noSideEffect.} -proc internalParseStmt(s: string): PNimrodNode {. +proc internalParseStmt(s: string): NimNode {. magic: "ParseStmtToAst", noSideEffect.} proc internalErrorFlag*(): string {.magic: "NError", noSideEffect.} ## Some builtins set an error flag. This is then turned into a proper ## exception. **Note**: Ordinary application code should not call this. -proc parseExpr*(s: string): PNimrodNode {.noSideEffect, compileTime.} = +proc parseExpr*(s: string): NimNode {.noSideEffect, compileTime.} = ## Compiles the passed string to its AST representation. ## Expects a single expression. Raises ``ValueError`` for parsing errors. result = internalParseExpr(s) let x = internalErrorFlag() if x.len > 0: raise newException(ValueError, x) -proc parseStmt*(s: string): PNimrodNode {.noSideEffect, compileTime.} = +proc parseStmt*(s: string): NimNode {.noSideEffect, compileTime.} = ## Compiles the passed string to its AST representation. ## Expects one or more statements. Raises ``ValueError`` for parsing errors. result = internalParseStmt(s) let x = internalErrorFlag() if x.len > 0: raise newException(ValueError, x) -proc getAst*(macroOrTemplate: expr): PNimrodNode {.magic: "ExpandToAst", noSideEffect.} +proc getAst*(macroOrTemplate: expr): NimNode {.magic: "ExpandToAst", noSideEffect.} ## Obtains the AST nodes returned from a macro or template invocation. ## Example: ## @@ -308,10 +306,10 @@ proc getAst*(macroOrTemplate: expr): PNimrodNode {.magic: "ExpandToAst", noSideE ## macro FooMacro() = ## var ast = getAst(BarTemplate()) -proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst", noSideEffect.} +proc quote*(bl: stmt, op = "``"): NimNode {.magic: "QuoteAst", noSideEffect.} ## Quasi-quoting operator. ## Accepts an expression or a block and returns the AST that represents it. - ## Within the quoted AST, you are able to interpolate PNimrodNode expressions + ## Within the quoted AST, you are able to interpolate NimNode expressions ## from the surrounding scope. If no operator is given, quoting is done using ## backticks. Otherwise, the given operator must be used as a prefix operator ## for any interpolated expression. The original meaning of the interpolation @@ -339,26 +337,26 @@ proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst", noSideEffect. ## if not `ex`: ## echo `info` & ": Check failed: " & `expString` -proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} = +proc expectKind*(n: NimNode, k: NimNodeKind) {.compileTime.} = ## checks that `n` is of kind `k`. If this is not the case, ## compilation aborts with an error message. This is useful for writing ## macros that check the AST that is passed to them. if n.kind != k: error("Expected a node of kind " & $k & ", got " & $n.kind) -proc expectMinLen*(n: PNimrodNode, min: int) {.compileTime.} = +proc expectMinLen*(n: NimNode, min: int) {.compileTime.} = ## checks that `n` has at least `min` children. If this is not the case, ## compilation aborts with an error message. This is useful for writing ## macros that check its number of arguments. if n.len < min: error("macro expects a node with " & $min & " children") -proc expectLen*(n: PNimrodNode, len: int) {.compileTime.} = +proc expectLen*(n: NimNode, len: int) {.compileTime.} = ## checks that `n` has exactly `len` children. If this is not the case, ## compilation aborts with an error message. This is useful for writing ## macros that check its number of arguments. if n.len != len: error("macro expects a node with " & $len & " children") -proc newCall*(theProc: PNimrodNode, - args: varargs[PNimrodNode]): PNimrodNode {.compileTime.} = +proc newCall*(theProc: NimNode, + args: varargs[NimNode]): NimNode {.compileTime.} = ## produces a new call node. `theProc` is the proc that is called with ## the arguments ``args[0..]``. result = newNimNode(nnkCall) @@ -366,7 +364,7 @@ proc newCall*(theProc: PNimrodNode, result.add(args) proc newCall*(theProc: NimIdent, - args: varargs[PNimrodNode]): PNimrodNode {.compileTime.} = + args: varargs[NimNode]): NimNode {.compileTime.} = ## produces a new call node. `theProc` is the proc that is called with ## the arguments ``args[0..]``. result = newNimNode(nnkCall) @@ -374,35 +372,35 @@ proc newCall*(theProc: NimIdent, result.add(args) proc newCall*(theProc: string, - args: varargs[PNimrodNode]): PNimrodNode {.compileTime.} = + args: varargs[NimNode]): NimNode {.compileTime.} = ## produces a new call node. `theProc` is the proc that is called with ## the arguments ``args[0..]``. result = newNimNode(nnkCall) result.add(newIdentNode(theProc)) result.add(args) -proc newLit*(c: char): PNimrodNode {.compileTime.} = +proc newLit*(c: char): NimNode {.compileTime.} = ## produces a new character literal node. result = newNimNode(nnkCharLit) result.intVal = ord(c) -proc newLit*(i: BiggestInt): PNimrodNode {.compileTime.} = +proc newLit*(i: BiggestInt): NimNode {.compileTime.} = ## produces a new integer literal node. result = newNimNode(nnkIntLit) result.intVal = i -proc newLit*(f: BiggestFloat): PNimrodNode {.compileTime.} = +proc newLit*(f: BiggestFloat): NimNode {.compileTime.} = ## produces a new float literal node. result = newNimNode(nnkFloatLit) result.floatVal = f -proc newLit*(s: string): PNimrodNode {.compileTime.} = +proc newLit*(s: string): NimNode {.compileTime.} = ## produces a new string literal node. result = newNimNode(nnkStrLit) result.strVal = s proc nestList*(theProc: NimIdent, - x: PNimrodNode): PNimrodNode {.compileTime.} = + x: NimNode): NimNode {.compileTime.} = ## nests the list `x` into a tree of call expressions: ## ``[a, b, c]`` is transformed into ``theProc(a, theProc(c, d))``. var L = x.len @@ -413,11 +411,11 @@ proc nestList*(theProc: NimIdent, # This could easily user code and so should be fixed in evals.nim somehow. result = newCall(theProc, x[i], copyNimTree(result)) -proc treeRepr*(n: PNimrodNode): string {.compileTime, benign.} = +proc treeRepr*(n: NimNode): string {.compileTime, benign.} = ## Convert the AST `n` to a human-readable tree-like string. ## ## See also `repr` and `lispRepr`. - proc traverse(res: var string, level: int, n: PNimrodNode) {.benign.} = + proc traverse(res: var string, level: int, n: NimNode) {.benign.} = for i in 0..level-1: res.add " " res.add(($n.kind).substr(3)) @@ -438,7 +436,7 @@ proc treeRepr*(n: PNimrodNode): string {.compileTime, benign.} = result = "" traverse(result, 0, n) -proc lispRepr*(n: PNimrodNode): string {.compileTime, benign.} = +proc lispRepr*(n: NimNode): string {.compileTime, benign.} = ## Convert the AST `n` to a human-readable lisp-like string, ## ## See also `repr` and `treeRepr`. @@ -485,56 +483,56 @@ macro dumpLispImm*(s: stmt): stmt {.immediate, deprecated.} = echo s.lispRepr ## The ``immediate`` version of `dumpLisp`. -proc newEmptyNode*(): PNimrodNode {.compileTime, noSideEffect.} = +proc newEmptyNode*(): NimNode {.compileTime, noSideEffect.} = ## Create a new empty node result = newNimNode(nnkEmpty) -proc newStmtList*(stmts: varargs[PNimrodNode]): PNimrodNode {.compileTime.}= +proc newStmtList*(stmts: varargs[NimNode]): NimNode {.compileTime.}= ## Create a new statement list result = newNimNode(nnkStmtList).add(stmts) -proc newPar*(exprs: varargs[PNimrodNode]): PNimrodNode {.compileTime.}= +proc newPar*(exprs: varargs[NimNode]): NimNode {.compileTime.}= ## Create a new parentheses-enclosed expression newNimNode(nnkPar).add(exprs) -proc newBlockStmt*(label, body: PNimrodNode): PNimrodNode {.compileTime.} = +proc newBlockStmt*(label, body: NimNode): NimNode {.compileTime.} = ## Create a new block statement with label return newNimNode(nnkBlockStmt).add(label, body) -proc newBlockStmt*(body: PNimrodNode): PNimrodNode {.compiletime.} = +proc newBlockStmt*(body: NimNode): NimNode {.compiletime.} = ## Create a new block: stmt return newNimNode(nnkBlockStmt).add(newEmptyNode(), body) -proc newVarStmt*(name, value: PNimrodNode): PNimrodNode {.compiletime.} = +proc newVarStmt*(name, value: NimNode): NimNode {.compiletime.} = ## Create a new var stmt return newNimNode(nnkVarSection).add( newNimNode(nnkIdentDefs).add(name, newNimNode(nnkEmpty), value)) -proc newLetStmt*(name, value: PNimrodNode): PNimrodNode {.compiletime.} = +proc newLetStmt*(name, value: NimNode): NimNode {.compiletime.} = ## Create a new let stmt return newNimNode(nnkLetSection).add( newNimNode(nnkIdentDefs).add(name, newNimNode(nnkEmpty), value)) -proc newConstStmt*(name, value: PNimrodNode): PNimrodNode {.compileTime.} = +proc newConstStmt*(name, value: NimNode): NimNode {.compileTime.} = ## Create a new const stmt newNimNode(nnkConstSection).add( newNimNode(nnkConstDef).add(name, newNimNode(nnkEmpty), value)) -proc newAssignment*(lhs, rhs: PNimrodNode): PNimrodNode {.compileTime.} = +proc newAssignment*(lhs, rhs: NimNode): NimNode {.compileTime.} = return newNimNode(nnkAsgn).add(lhs, rhs) -proc newDotExpr*(a, b: PNimrodNode): PNimrodNode {.compileTime.} = +proc newDotExpr*(a, b: NimNode): NimNode {.compileTime.} = ## Create new dot expression ## a.dot(b) -> `a.b` return newNimNode(nnkDotExpr).add(a, b) -proc newColonExpr*(a, b: PNimrodNode): PNimrodNode {.compileTime.} = +proc newColonExpr*(a, b: NimNode): NimNode {.compileTime.} = ## Create new colon expression ## newColonExpr(a, b) -> `a: b` newNimNode(nnkExprColonExpr).add(a, b) -proc newIdentDefs*(name, kind: PNimrodNode; - default = newEmptyNode()): PNimrodNode {.compileTime.} = +proc newIdentDefs*(name, kind: NimNode; + default = newEmptyNode()): NimNode {.compileTime.} = ## Creates a new ``nnkIdentDefs`` node of a specific kind and value. ## ## ``nnkIdentDefs`` need to have at least three children, but they can have @@ -565,13 +563,13 @@ proc newIdentDefs*(name, kind: PNimrodNode; ## newStrLitNode("Hello")) newNimNode(nnkIdentDefs).add(name, kind, default) -proc newNilLit*(): PNimrodNode {.compileTime.} = +proc newNilLit*(): NimNode {.compileTime.} = ## New nil literal shortcut result = newNimNode(nnkNilLit) -proc high*(node: PNimrodNode): int {.compileTime.} = len(node) - 1 +proc high*(node: NimNode): int {.compileTime.} = len(node) - 1 ## Return the highest index available for a node -proc last*(node: PNimrodNode): PNimrodNode {.compileTime.} = node[node.high] +proc last*(node: NimNode): NimNode {.compileTime.} = node[node.high] ## Return the last item in nodes children. Same as `node[node.high()]` @@ -581,11 +579,11 @@ const CallNodes* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand, nnkCallStrLit, nnkHiddenCallConv} -proc expectKind*(n: PNimrodNode; k: set[TNimrodNodeKind]) {.compileTime.} = +proc expectKind*(n: NimNode; k: set[NimNodeKind]) {.compileTime.} = assert n.kind in k, "Expected one of " & $k & ", got " & $n.kind -proc newProc*(name = newEmptyNode(); params: openArray[PNimrodNode] = [newEmptyNode()]; - body: PNimrodNode = newStmtList(), procType = nnkProcDef): PNimrodNode {.compileTime.} = +proc newProc*(name = newEmptyNode(); params: openArray[NimNode] = [newEmptyNode()]; + body: NimNode = newStmtList(), procType = nnkProcDef): NimNode {.compileTime.} = ## shortcut for creating a new proc ## ## The ``params`` array must start with the return type of the proc, @@ -600,8 +598,8 @@ proc newProc*(name = newEmptyNode(); params: openArray[PNimrodNode] = [newEmptyN newEmptyNode(), body) -proc newIfStmt*(branches: varargs[tuple[cond, body: PNimrodNode]]): - PNimrodNode {.compiletime.} = +proc newIfStmt*(branches: varargs[tuple[cond, body: NimNode]]): + NimNode {.compiletime.} = ## Constructor for ``if`` statements. ## ## .. code-block:: nim @@ -616,35 +614,35 @@ proc newIfStmt*(branches: varargs[tuple[cond, body: PNimrodNode]]): result.add(newNimNode(nnkElifBranch).add(i.cond, i.body)) -proc copyChildrenTo*(src, dest: PNimrodNode) {.compileTime.}= +proc copyChildrenTo*(src, dest: NimNode) {.compileTime.}= ## Copy all children from `src` to `dest` for i in 0 .. < src.len: dest.add src[i].copyNimTree -template expectRoutine(node: PNimrodNode): stmt = +template expectRoutine(node: NimNode): stmt = expectKind(node, RoutineNodes) -proc name*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = +proc name*(someProc: NimNode): NimNode {.compileTime.} = someProc.expectRoutine result = someProc[0] -proc `name=`*(someProc: PNimrodNode; val: PNimrodNode) {.compileTime.} = +proc `name=`*(someProc: NimNode; val: NimNode) {.compileTime.} = someProc.expectRoutine someProc[0] = val -proc params*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = +proc params*(someProc: NimNode): NimNode {.compileTime.} = someProc.expectRoutine result = someProc[3] -proc `params=`* (someProc: PNimrodNode; params: PNimrodNode) {.compileTime.}= +proc `params=`* (someProc: NimNode; params: NimNode) {.compileTime.}= someProc.expectRoutine assert params.kind == nnkFormalParams someProc[3] = params -proc pragma*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = +proc pragma*(someProc: NimNode): NimNode {.compileTime.} = ## Get the pragma of a proc type ## These will be expanded someProc.expectRoutine result = someProc[4] -proc `pragma=`*(someProc: PNimrodNode; val: PNimrodNode){.compileTime.}= +proc `pragma=`*(someProc: NimNode; val: NimNode){.compileTime.}= ## Set the pragma of a proc type someProc.expectRoutine assert val.kind in {nnkEmpty, nnkPragma} @@ -654,7 +652,7 @@ proc `pragma=`*(someProc: PNimrodNode; val: PNimrodNode){.compileTime.}= template badNodeKind(k; f): stmt{.immediate.} = assert false, "Invalid node kind " & $k & " for macros.`" & $f & "`" -proc body*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = +proc body*(someProc: NimNode): NimNode {.compileTime.} = case someProc.kind: of RoutineNodes: return someProc[6] @@ -665,7 +663,7 @@ proc body*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = else: badNodeKind someProc.kind, "body" -proc `body=`*(someProc: PNimrodNode, val: PNimrodNode) {.compileTime.} = +proc `body=`*(someProc: NimNode, val: NimNode) {.compileTime.} = case someProc.kind of RoutineNodes: someProc[6] = val @@ -676,10 +674,10 @@ proc `body=`*(someProc: PNimrodNode, val: PNimrodNode) {.compileTime.} = else: badNodeKind someProc.kind, "body=" -proc basename*(a: PNimrodNode): PNimrodNode {.compiletime, benign.} +proc basename*(a: NimNode): NimNode {.compiletime, benign.} -proc `$`*(node: PNimrodNode): string {.compileTime.} = +proc `$`*(node: NimNode): string {.compileTime.} = ## Get the string of an identifier node case node.kind of nnkIdent: @@ -693,14 +691,14 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} = else: badNodeKind node.kind, "$" -proc ident*(name: string): PNimrodNode {.compileTime,inline.} = newIdentNode(name) +proc ident*(name: string): NimNode {.compileTime,inline.} = newIdentNode(name) ## Create a new ident node from a string -iterator children*(n: PNimrodNode): PNimrodNode {.inline.}= +iterator children*(n: NimNode): NimNode {.inline.}= for i in 0 .. high(n): yield n[i] -template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {. +template findChild*(n: NimNode; cond: expr): NimNode {. immediate, dirty.} = ## Find the first child node matching condition (or nil). ## @@ -708,14 +706,14 @@ template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {. ## var res = findChild(n, it.kind == nnkPostfix and ## it.basename.ident == !"foo") block: - var result: PNimrodNode + var result: NimNode for it in n.children: if cond: result = it break result -proc insert*(a: PNimrodNode; pos: int; b: PNimrodNode) {.compileTime.} = +proc insert*(a: NimNode; pos: int; b: NimNode) {.compileTime.} = ## Insert node B into A at pos if high(a) < pos: ## add some empty nodes first @@ -730,7 +728,7 @@ proc insert*(a: PNimrodNode; pos: int; b: PNimrodNode) {.compileTime.} = a[i + 1] = a[i] a[pos] = b -proc basename*(a: PNimrodNode): PNimrodNode = +proc basename*(a: NimNode): NimNode = ## Pull an identifier from prefix/postfix expressions case a.kind of nnkIdent: return a @@ -738,39 +736,39 @@ proc basename*(a: PNimrodNode): PNimrodNode = else: quit "Do not know how to get basename of ("& treeRepr(a) &")\n"& repr(a) -proc `basename=`*(a: PNimrodNode; val: string) {.compileTime.}= +proc `basename=`*(a: NimNode; val: string) {.compileTime.}= case a.kind of nnkIdent: macros.`ident=`(a, !val) of nnkPostfix, nnkPrefix: a[1] = ident(val) else: quit "Do not know how to get basename of ("& treeRepr(a)& ")\n"& repr(a) -proc postfix*(node: PNimrodNode; op: string): PNimrodNode {.compileTime.} = +proc postfix*(node: NimNode; op: string): NimNode {.compileTime.} = newNimNode(nnkPostfix).add(ident(op), node) -proc prefix*(node: PNimrodNode; op: string): PNimrodNode {.compileTime.} = +proc prefix*(node: NimNode; op: string): NimNode {.compileTime.} = newNimNode(nnkPrefix).add(ident(op), node) -proc infix*(a: PNimrodNode; op: string; - b: PNimrodNode): PNimrodNode {.compileTime.} = +proc infix*(a: NimNode; op: string; + b: NimNode): NimNode {.compileTime.} = newNimNode(nnkInfix).add(ident(op), a, b) -proc unpackPostfix*(node: PNimrodNode): tuple[node: PNimrodNode; op: string] {. +proc unpackPostfix*(node: NimNode): tuple[node: NimNode; op: string] {. compileTime.} = node.expectKind nnkPostfix result = (node[0], $node[1]) -proc unpackPrefix*(node: PNimrodNode): tuple[node: PNimrodNode; op: string] {. +proc unpackPrefix*(node: NimNode): tuple[node: NimNode; op: string] {. compileTime.} = node.expectKind nnkPrefix result = (node[0], $node[1]) -proc unpackInfix*(node: PNimrodNode): tuple[left: PNimrodNode; op: string; - right: PNimrodNode] {.compileTime.} = +proc unpackInfix*(node: NimNode): tuple[left: NimNode; op: string; + right: NimNode] {.compileTime.} = assert node.kind == nnkInfix result = (node[0], $node[1], node[2]) -proc copy*(node: PNimrodNode): PNimrodNode {.compileTime.} = +proc copy*(node: NimNode): NimNode {.compileTime.} = ## An alias for copyNimTree(). return node.copyNimTree() @@ -793,7 +791,7 @@ proc cmpIgnoreStyle(a, b: cstring): int {.noSideEffect.} = proc eqIdent* (a, b: string): bool = cmpIgnoreStyle(a, b) == 0 ## Check if two idents are identical. -proc hasArgOfName* (params: PNimrodNode; name: string): bool {.compiletime.}= +proc hasArgOfName* (params: NimNode; name: string): bool {.compiletime.}= ## Search nnkFormalParams for an argument. assert params.kind == nnkFormalParams for i in 1 .. <params.len: @@ -801,7 +799,7 @@ proc hasArgOfName* (params: PNimrodNode; name: string): bool {.compiletime.}= if name.eqIdent( $ node[0]): return true -proc addIdentIfAbsent*(dest: PNimrodNode, ident: string) {.compiletime.} = +proc addIdentIfAbsent*(dest: NimNode, ident: string) {.compiletime.} = ## Add ident to dest if it is not present. This is intended for use ## with pragmas. for node in dest.children: @@ -825,5 +823,3 @@ when not defined(booting): macro payload: stmt {.gensym.} = result = parseStmt(e) payload() - -{.pop.} diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim index dab84c2d5..b8180cd87 100644 --- a/lib/impure/db_mysql.nim +++ b/lib/impure/db_mysql.nim @@ -229,3 +229,9 @@ proc open*(connection, user, password, database: string): TDbConn {. var errmsg = $mysql.error(result) db_mysql.close(result) dbError(errmsg) + +proc setEncoding*(connection: TDbConn, encoding: string): bool {. + tags: [FDb].} = + ## sets the encoding of a database connection, returns true for + ## success, false for failure. + result = mysql.set_character_set(connection, encoding) == 0 \ No newline at end of file diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim index d8ccc4c16..ffb8bbcda 100644 --- a/lib/impure/db_postgres.nim +++ b/lib/impure/db_postgres.nim @@ -260,3 +260,9 @@ proc open*(connection, user, password, database: string): TDbConn {. ## the nim db api. result = pqsetdbLogin(nil, nil, nil, nil, database, user, password) if pqStatus(result) != CONNECTION_OK: dbError(result) # result = nil + +proc setEncoding*(connection: TDbConn, encoding: string): bool {. + tags: [FDb].} = + ## sets the encoding of a database connection, returns true for + ## success, false for failure. + return pqsetClientEncoding(connection, encoding) == 0 \ No newline at end of file diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim index bf1ce75ef..4be692f39 100644 --- a/lib/impure/db_sqlite.nim +++ b/lib/impure/db_sqlite.nim @@ -192,7 +192,19 @@ proc open*(connection, user, password, database: string): TDbConn {. result = db else: dbError(db) - + +proc setEncoding*(connection: TDbConn, encoding: string): bool {. + tags: [FDb].} = + ## sets the encoding of a database connection, returns true for + ## success, false for failure. + ## + ## Note that the encoding cannot be changed once it's been set. + ## According to SQLite3 documentation, any attempt to change + ## the encoding after the database is created will be silently + ## ignored. + exec(connection, sql"PRAGMA encoding = ?", [encoding]) + result = connection.getValue(sql"PRAGMA encoding") == encoding + when isMainModule: var db = open("db.sql", "", "", "") exec(db, sql"create table tbl1(one varchar(10), two smallint)", []) diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index a8caf809e..8e0ac8d21 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -1064,13 +1064,13 @@ proc accept*(socket: TAsyncFD, # -- Await Macro -proc skipUntilStmtList(node: PNimrodNode): PNimrodNode {.compileTime.} = +proc skipUntilStmtList(node: NimNode): NimNode {.compileTime.} = # Skips a nest of StmtList's. result = node if node[0].kind == nnkStmtList: result = skipUntilStmtList(node[0]) -proc skipStmtList(node: PNimrodNode): PNimrodNode {.compileTime.} = +proc skipStmtList(node: NimNode): NimNode {.compileTime.} = result = node if node[0].kind == nnkStmtList: result = node[0] @@ -1098,11 +1098,11 @@ template createCb(retFutureSym, iteratorNameSym, cb() #{.pop.} proc generateExceptionCheck(futSym, - tryStmt, rootReceiver, fromNode: PNimrodNode): PNimrodNode {.compileTime.} = + tryStmt, rootReceiver, fromNode: NimNode): NimNode {.compileTime.} = if tryStmt.kind == nnkNilLit: result = rootReceiver else: - var exceptionChecks: seq[tuple[cond, body: PNimrodNode]] = @[] + var exceptionChecks: seq[tuple[cond, body: NimNode]] = @[] let errorNode = newDotExpr(futSym, newIdentNode("error")) for i in 1 .. <tryStmt.len: let exceptBranch = tryStmt[i] @@ -1110,7 +1110,7 @@ proc generateExceptionCheck(futSym, exceptionChecks.add((newIdentNode("true"), exceptBranch[0])) else: var exceptIdentCount = 0 - var ifCond: PNimrodNode + var ifCond: NimNode for i in 0 .. <exceptBranch.len: let child = exceptBranch[i] if child.kind == nnkIdent: @@ -1144,10 +1144,10 @@ proc generateExceptionCheck(futSym, ) result.add elseNode -template createVar(result: var PNimrodNode, futSymName: string, - asyncProc: PNimrodNode, +template createVar(result: var NimNode, futSymName: string, + asyncProc: NimNode, valueReceiver, rootReceiver: expr, - fromNode: PNimrodNode) = + fromNode: NimNode) = result = newNimNode(nnkStmtList, fromNode) var futSym = genSym(nskVar, "future") result.add newVarStmt(futSym, asyncProc) # -> var future<x> = y @@ -1155,9 +1155,9 @@ template createVar(result: var PNimrodNode, futSymName: string, valueReceiver = newDotExpr(futSym, newIdentNode("read")) # -> future<x>.read result.add generateExceptionCheck(futSym, tryStmt, rootReceiver, fromNode) -proc processBody(node, retFutureSym: PNimrodNode, +proc processBody(node, retFutureSym: NimNode, subTypeIsVoid: bool, - tryStmt: PNimrodNode): PNimrodNode {.compileTime.} = + tryStmt: NimNode): NimNode {.compileTime.} = #echo(node.treeRepr) result = node case node.kind @@ -1183,7 +1183,7 @@ proc processBody(node, retFutureSym: PNimrodNode, result = newNimNode(nnkYieldStmt, node).add(node[1]) # -> yield x of nnkCall, nnkCommand: # await foo(p, x) - var futureValue: PNimrodNode + var futureValue: NimNode result.createVar("future" & $node[1][0].toStrLit, node[1], futureValue, futureValue, node) else: @@ -1232,8 +1232,8 @@ proc processBody(node, retFutureSym: PNimrodNode, # working in ``except``? tryBody[1] = processBody(n[1], retFutureSym, subTypeIsVoid, nil) - proc processForTry(n: PNimrodNode, i: var int, - res: PNimrodNode): bool {.compileTime.} = + proc processForTry(n: NimNode, i: var int, + res: NimNode): bool {.compileTime.} = ## Transforms the body of the tryStmt. Does not transform the ## body in ``except``. ## Returns true if the tryStmt node was transformed into an ifStmt. @@ -1275,7 +1275,7 @@ proc processBody(node, retFutureSym: PNimrodNode, for i in 0 .. <result.len: result[i] = processBody(result[i], retFutureSym, subTypeIsVoid, tryStmt) -proc getName(node: PNimrodNode): string {.compileTime.} = +proc getName(node: NimNode): string {.compileTime.} = case node.kind of nnkPostfix: return $node[1].ident diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 93a7591ac..feb965af3 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -95,12 +95,12 @@ proc len*[A, B](t: Table[A, B]): int = ## returns the number of keys in `t`. result = t.counter -iterator pairs*[A, B](t: Table[A, B]): tuple[key: A, val: B] = +iterator pairs*[A, B](t: Table[A, B]): (A, B) = ## iterates over any (key, value) pair in the table `t`. for h in 0..high(t.data): if isFilled(t.data[h].hcode): yield (t.data[h].key, t.data[h].val) -iterator mpairs*[A, B](t: var Table[A, B]): tuple[key: A, val: var B] = +iterator mpairs*[A, B](t: var Table[A, B]): (A, var B) = ## iterates over any (key, value) pair in the table `t`. The values ## can be modified. for h in 0..high(t.data): @@ -314,8 +314,8 @@ proc initTable*[A, B](initialSize=64): Table[A, B] = result.counter = 0 newSeq(result.data, initialSize) -proc toTable*[A, B](pairs: openArray[tuple[key: A, - val: B]]): Table[A, B] = +proc toTable*[A, B](pairs: openArray[(A, + B)]): Table[A, B] = ## creates a new hash table that contains the given `pairs`. result = initTable[A, B](rightSize(pairs.len)) for key, val in items(pairs): result[key] = val @@ -360,12 +360,12 @@ proc len*[A, B](t: TableRef[A, B]): int = ## returns the number of keys in `t`. result = t.counter -iterator pairs*[A, B](t: TableRef[A, B]): tuple[key: A, val: B] = +iterator pairs*[A, B](t: TableRef[A, B]): (A, B) = ## iterates over any (key, value) pair in the table `t`. for h in 0..high(t.data): if isFilled(t.data[h].hcode): yield (t.data[h].key, t.data[h].val) -iterator mpairs*[A, B](t: TableRef[A, B]): tuple[key: A, val: var B] = +iterator mpairs*[A, B](t: TableRef[A, B]): (A, var B) = ## iterates over any (key, value) pair in the table `t`. The values ## can be modified. for h in 0..high(t.data): @@ -427,7 +427,7 @@ proc newTable*[A, B](initialSize=64): TableRef[A, B] = new(result) result[] = initTable[A, B](initialSize) -proc newTable*[A, B](pairs: openArray[tuple[key: A, val: B]]): TableRef[A, B] = +proc newTable*[A, B](pairs: openArray[(A, B)]): TableRef[A, B] = ## creates a new hash table that contains the given `pairs`. new(result) result[] = toTable[A, B](pairs) @@ -473,13 +473,13 @@ template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} = if isFilled(t.data[h].hcode): yieldStmt h = nxt -iterator pairs*[A, B](t: OrderedTable[A, B]): tuple[key: A, val: B] = +iterator pairs*[A, B](t: OrderedTable[A, B]): (A, B) = ## iterates over any (key, value) pair in the table `t` in insertion ## order. forAllOrderedPairs: yield (t.data[h].key, t.data[h].val) -iterator mpairs*[A, B](t: var OrderedTable[A, B]): tuple[key: A, val: var B] = +iterator mpairs*[A, B](t: var OrderedTable[A, B]): (A, var B) = ## iterates over any (key, value) pair in the table `t` in insertion ## order. The values can be modified. forAllOrderedPairs: @@ -584,8 +584,8 @@ proc initOrderedTable*[A, B](initialSize=64): OrderedTable[A, B] = result.last = -1 newSeq(result.data, initialSize) -proc toOrderedTable*[A, B](pairs: openArray[tuple[key: A, - val: B]]): OrderedTable[A, B] = +proc toOrderedTable*[A, B](pairs: openArray[(A, + B)]): OrderedTable[A, B] = ## creates a new ordered hash table that contains the given `pairs`. result = initOrderedTable[A, B](rightSize(pairs.len)) for key, val in items(pairs): result[key] = val @@ -595,7 +595,7 @@ proc `$`*[A, B](t: OrderedTable[A, B]): string = dollarImpl() proc sort*[A, B](t: var OrderedTable[A, B], - cmp: proc (x,y: tuple[key: A, val: B]): int) = + cmp: proc (x,y: (A, B)): int) = ## sorts `t` according to `cmp`. This modifies the internal list ## that kept the insertion order, so insertion order is lost after this ## call but key lookup and insertions remain possible after `sort` (in @@ -651,13 +651,13 @@ template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} = if isFilled(t.data[h].hcode): yieldStmt h = nxt -iterator pairs*[A, B](t: OrderedTableRef[A, B]): tuple[key: A, val: B] = +iterator pairs*[A, B](t: OrderedTableRef[A, B]): (A, B) = ## iterates over any (key, value) pair in the table `t` in insertion ## order. forAllOrderedPairs: yield (t.data[h].key, t.data[h].val) -iterator mpairs*[A, B](t: OrderedTableRef[A, B]): tuple[key: A, val: var B] = +iterator mpairs*[A, B](t: OrderedTableRef[A, B]): (A, var B) = ## iterates over any (key, value) pair in the table `t` in insertion ## order. The values can be modified. forAllOrderedPairs: @@ -721,8 +721,7 @@ proc newOrderedTable*[A, B](initialSize=64): OrderedTableRef[A, B] = new(result) result[] = initOrderedTable[A, B]() -proc newOrderedTable*[A, B](pairs: openArray[tuple[key: A, - val: B]]): OrderedTableRef[A, B] = +proc newOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTableRef[A, B] = ## creates a new ordered hash table that contains the given `pairs`. result = newOrderedTable[A, B](rightSize(pairs.len)) for key, val in items(pairs): result[key] = val @@ -732,7 +731,7 @@ proc `$`*[A, B](t: OrderedTableRef[A, B]): string = dollarImpl() proc sort*[A, B](t: OrderedTableRef[A, B], - cmp: proc (x,y: tuple[key: A, val: B]): int) = + cmp: proc (x,y: (A, B)): int) = ## sorts `t` according to `cmp`. This modifies the internal list ## that kept the insertion order, so insertion order is lost after this ## call but key lookup and insertions remain possible after `sort` (in @@ -754,12 +753,12 @@ proc len*[A](t: CountTable[A]): int = ## returns the number of keys in `t`. result = t.counter -iterator pairs*[A](t: CountTable[A]): tuple[key: A, val: int] = +iterator pairs*[A](t: CountTable[A]): (A, int) = ## iterates over any (key, value) pair in the table `t`. for h in 0..high(t.data): if t.data[h].val != 0: yield (t.data[h].key, t.data[h].val) -iterator mpairs*[A](t: var CountTable[A]): tuple[key: A, val: var int] = +iterator mpairs*[A](t: var CountTable[A]): (A, var int) = ## iterates over any (key, value) pair in the table `t`. The values can ## be modified. for h in 0..high(t.data): @@ -902,12 +901,12 @@ proc len*[A](t: CountTableRef[A]): int = ## returns the number of keys in `t`. result = t.counter -iterator pairs*[A](t: CountTableRef[A]): tuple[key: A, val: int] = +iterator pairs*[A](t: CountTableRef[A]): (A, int) = ## iterates over any (key, value) pair in the table `t`. for h in 0..high(t.data): if t.data[h].val != 0: yield (t.data[h].key, t.data[h].val) -iterator mpairs*[A](t: CountTableRef[A]): tuple[key: A, val: var int] = +iterator mpairs*[A](t: CountTableRef[A]): (A, var int) = ## iterates over any (key, value) pair in the table `t`. The values can ## be modified. for h in 0..high(t.data): @@ -970,11 +969,11 @@ proc inc*[A](t: CountTableRef[A], key: A, val = 1) = ## increments `t[key]` by `val`. t[].inc(key, val) -proc smallest*[A](t: CountTableRef[A]): tuple[key: A, val: int] = +proc smallest*[A](t: CountTableRef[A]): (A, int) = ## returns the largest (key,val)-pair. Efficiency: O(n) t[].smallest -proc largest*[A](t: CountTableRef[A]): tuple[key: A, val: int] = +proc largest*[A](t: CountTableRef[A]): (A, int) = ## returns the (key,val)-pair with the largest `val`. Efficiency: O(n) t[].largest diff --git a/lib/pure/future.nim b/lib/pure/future.nim index 05f25d29f..661afd7b3 100644 --- a/lib/pure/future.nim +++ b/lib/pure/future.nim @@ -12,7 +12,7 @@ import macros -proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} = +proc createProcType(p, b: NimNode): NimNode {.compileTime.} = #echo treeRepr(p) #echo treeRepr(b) result = newNimNode(nnkProcTy) @@ -44,7 +44,7 @@ proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} = formalParams.add identDefs else: error("Incorrect type list in proc type declaration.") - + result.add formalParams result.add newEmptyNode() #echo(treeRepr(result)) @@ -59,10 +59,10 @@ macro `=>`*(p, b: expr): expr {.immediate.} = ## f(2, 2) ## ## passTwoAndTwo((x, y) => x + y) # 4 - + #echo treeRepr(p) #echo(treeRepr(b)) - var params: seq[PNimrodNode] = @[newIdentNode("auto")] + var params: seq[NimNode] = @[newIdentNode("auto")] case p.kind of nnkPar: @@ -118,7 +118,7 @@ macro `->`*(p, b: expr): expr {.immediate.} = ## ## proc pass2(f: (float, float) -> float): float = ## f(2, 2) - ## + ## ## # is the same as: ## ## proc pass2(f: proc (x, y: float): float): float = diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim index aeb93bebe..d712e53f3 100644 --- a/lib/pure/htmlgen.nim +++ b/lib/pure/htmlgen.nim @@ -12,7 +12,7 @@ ## as ``from htmlgen import nil`` and then fully qualify the macros. ## ## -## This module implements a simple `XML`:idx: and `HTML`:idx: code +## This module implements a simple `XML`:idx: and `HTML`:idx: code ## generator. Each commonly used HTML tag has a corresponding macro ## that generates a string with its HTML representation. ## @@ -21,9 +21,9 @@ ## .. code-block:: Nim ## var nim = "Nim" ## echo h1(a(href="http://nim-lang.org", nim)) -## +## ## Writes the string:: -## +## ## <h1><a href="http://nim-lang.org">Nim</a></h1> ## @@ -36,16 +36,16 @@ const "onmouseover onmousemove onmouseout onkeypress onkeydown onkeyup " commonAttr* = coreAttr & eventAttr -proc getIdent(e: PNimrodNode): string {.compileTime.} = +proc getIdent(e: NimNode): string {.compileTime.} = case e.kind of nnkIdent: result = normalize($e.ident) - of nnkAccQuoted: + of nnkAccQuoted: result = getIdent(e[0]) for i in 1 .. e.len-1: result.add getIdent(e[i]) else: error("cannot extract identifier from node: " & toStrLit(e).strVal) -proc delete[T](s: var seq[T], attr: T): bool = +proc delete[T](s: var seq[T], attr: T): bool = var idx = find(s, attr) if idx >= 0: var L = s.len @@ -53,10 +53,10 @@ proc delete[T](s: var seq[T], attr: T): bool = setLen(s, L-1) result = true -proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "", - isLeaf = false): PNimrodNode {.compileTime.} = +proc xmlCheckedTag*(e: NimNode, tag: string, optAttr = "", reqAttr = "", + isLeaf = false): NimNode {.compileTime.} = ## use this procedure to define a new XML tag - + # copy the attributes; when iterating over them these lists # will be modified, so that each attribute is only given one value var req = split(reqAttr) @@ -66,7 +66,7 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "", result.add(newStrLitNode(tag)) # first pass over attributes: for i in 1..e.len-1: - if e[i].kind == nnkExprEqExpr: + if e[i].kind == nnkExprEqExpr: var name = getIdent(e[i][0]) if delete(req, name) or delete(opt, name): result.add(newStrLitNode(" ")) @@ -81,7 +81,7 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "", error(req[0] & " attribute for '" & tag & "' element expected") if isLeaf: for i in 1..e.len-1: - if e[i].kind != nnkExprEqExpr: + if e[i].kind != nnkExprEqExpr: error("element " & tag & " cannot be nested") result.add(newStrLitNode(" />")) else: @@ -95,389 +95,389 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "", result = nestList(!"&", result) -macro a*(e: expr): expr {.immediate.} = +macro a*(e: expr): expr {.immediate.} = ## generates the HTML ``a`` element. let e = callsite() result = xmlCheckedTag(e, "a", "href charset type hreflang rel rev " & "accesskey tabindex" & commonAttr) -macro acronym*(e: expr): expr {.immediate.} = +macro acronym*(e: expr): expr {.immediate.} = ## generates the HTML ``acronym`` element. let e = callsite() result = xmlCheckedTag(e, "acronym", commonAttr) -macro address*(e: expr): expr {.immediate.} = +macro address*(e: expr): expr {.immediate.} = ## generates the HTML ``address`` element. let e = callsite() result = xmlCheckedTag(e, "address", commonAttr) -macro area*(e: expr): expr {.immediate.} = +macro area*(e: expr): expr {.immediate.} = ## generates the HTML ``area`` element. let e = callsite() result = xmlCheckedTag(e, "area", "shape coords href nohref" & " accesskey tabindex" & commonAttr, "alt", true) -macro b*(e: expr): expr {.immediate.} = +macro b*(e: expr): expr {.immediate.} = ## generates the HTML ``b`` element. let e = callsite() result = xmlCheckedTag(e, "b", commonAttr) -macro base*(e: expr): expr {.immediate.} = +macro base*(e: expr): expr {.immediate.} = ## generates the HTML ``base`` element. let e = callsite() result = xmlCheckedTag(e, "base", "", "href", true) -macro big*(e: expr): expr {.immediate.} = +macro big*(e: expr): expr {.immediate.} = ## generates the HTML ``big`` element. let e = callsite() result = xmlCheckedTag(e, "big", commonAttr) -macro blockquote*(e: expr): expr {.immediate.} = +macro blockquote*(e: expr): expr {.immediate.} = ## generates the HTML ``blockquote`` element. let e = callsite() result = xmlCheckedTag(e, "blockquote", " cite" & commonAttr) -macro body*(e: expr): expr {.immediate.} = +macro body*(e: expr): expr {.immediate.} = ## generates the HTML ``body`` element. let e = callsite() result = xmlCheckedTag(e, "body", commonAttr) -macro br*(e: expr): expr {.immediate.} = +macro br*(e: expr): expr {.immediate.} = ## generates the HTML ``br`` element. let e = callsite() result = xmlCheckedTag(e, "br", "", "", true) -macro button*(e: expr): expr {.immediate.} = +macro button*(e: expr): expr {.immediate.} = ## generates the HTML ``button`` element. let e = callsite() result = xmlCheckedTag(e, "button", "accesskey tabindex " & "disabled name type value" & commonAttr) -macro caption*(e: expr): expr {.immediate.} = +macro caption*(e: expr): expr {.immediate.} = ## generates the HTML ``caption`` element. let e = callsite() result = xmlCheckedTag(e, "caption", commonAttr) -macro cite*(e: expr): expr {.immediate.} = +macro cite*(e: expr): expr {.immediate.} = ## generates the HTML ``cite`` element. let e = callsite() result = xmlCheckedTag(e, "cite", commonAttr) -macro code*(e: expr): expr {.immediate.} = +macro code*(e: expr): expr {.immediate.} = ## generates the HTML ``code`` element. let e = callsite() result = xmlCheckedTag(e, "code", commonAttr) -macro col*(e: expr): expr {.immediate.} = +macro col*(e: expr): expr {.immediate.} = ## generates the HTML ``col`` element. let e = callsite() result = xmlCheckedTag(e, "col", "span align valign" & commonAttr, "", true) -macro colgroup*(e: expr): expr {.immediate.} = +macro colgroup*(e: expr): expr {.immediate.} = ## generates the HTML ``colgroup`` element. let e = callsite() result = xmlCheckedTag(e, "colgroup", "span align valign" & commonAttr) -macro dd*(e: expr): expr {.immediate.} = +macro dd*(e: expr): expr {.immediate.} = ## generates the HTML ``dd`` element. let e = callsite() result = xmlCheckedTag(e, "dd", commonAttr) -macro del*(e: expr): expr {.immediate.} = +macro del*(e: expr): expr {.immediate.} = ## generates the HTML ``del`` element. let e = callsite() result = xmlCheckedTag(e, "del", "cite datetime" & commonAttr) -macro dfn*(e: expr): expr {.immediate.} = +macro dfn*(e: expr): expr {.immediate.} = ## generates the HTML ``dfn`` element. let e = callsite() result = xmlCheckedTag(e, "dfn", commonAttr) -macro `div`*(e: expr): expr {.immediate.} = +macro `div`*(e: expr): expr {.immediate.} = ## generates the HTML ``div`` element. let e = callsite() result = xmlCheckedTag(e, "div", commonAttr) -macro dl*(e: expr): expr {.immediate.} = +macro dl*(e: expr): expr {.immediate.} = ## generates the HTML ``dl`` element. let e = callsite() result = xmlCheckedTag(e, "dl", commonAttr) -macro dt*(e: expr): expr {.immediate.} = +macro dt*(e: expr): expr {.immediate.} = ## generates the HTML ``dt`` element. let e = callsite() result = xmlCheckedTag(e, "dt", commonAttr) -macro em*(e: expr): expr {.immediate.} = +macro em*(e: expr): expr {.immediate.} = ## generates the HTML ``em`` element. let e = callsite() result = xmlCheckedTag(e, "em", commonAttr) -macro fieldset*(e: expr): expr {.immediate.} = +macro fieldset*(e: expr): expr {.immediate.} = ## generates the HTML ``fieldset`` element. let e = callsite() result = xmlCheckedTag(e, "fieldset", commonAttr) -macro form*(e: expr): expr {.immediate.} = +macro form*(e: expr): expr {.immediate.} = ## generates the HTML ``form`` element. let e = callsite() - result = xmlCheckedTag(e, "form", "method encype accept accept-charset" & + result = xmlCheckedTag(e, "form", "method encype accept accept-charset" & commonAttr, "action") -macro h1*(e: expr): expr {.immediate.} = +macro h1*(e: expr): expr {.immediate.} = ## generates the HTML ``h1`` element. let e = callsite() result = xmlCheckedTag(e, "h1", commonAttr) -macro h2*(e: expr): expr {.immediate.} = +macro h2*(e: expr): expr {.immediate.} = ## generates the HTML ``h2`` element. let e = callsite() result = xmlCheckedTag(e, "h2", commonAttr) -macro h3*(e: expr): expr {.immediate.} = +macro h3*(e: expr): expr {.immediate.} = ## generates the HTML ``h3`` element. let e = callsite() result = xmlCheckedTag(e, "h3", commonAttr) -macro h4*(e: expr): expr {.immediate.} = +macro h4*(e: expr): expr {.immediate.} = ## generates the HTML ``h4`` element. let e = callsite() result = xmlCheckedTag(e, "h4", commonAttr) -macro h5*(e: expr): expr {.immediate.} = +macro h5*(e: expr): expr {.immediate.} = ## generates the HTML ``h5`` element. let e = callsite() result = xmlCheckedTag(e, "h5", commonAttr) -macro h6*(e: expr): expr {.immediate.} = +macro h6*(e: expr): expr {.immediate.} = ## generates the HTML ``h6`` element. let e = callsite() result = xmlCheckedTag(e, "h6", commonAttr) -macro head*(e: expr): expr {.immediate.} = +macro head*(e: expr): expr {.immediate.} = ## generates the HTML ``head`` element. let e = callsite() result = xmlCheckedTag(e, "head", "profile") -macro html*(e: expr): expr {.immediate.} = +macro html*(e: expr): expr {.immediate.} = ## generates the HTML ``html`` element. let e = callsite() result = xmlCheckedTag(e, "html", "xmlns", "") -macro hr*(): expr {.immediate.} = +macro hr*(): expr {.immediate.} = ## generates the HTML ``hr`` element. let e = callsite() result = xmlCheckedTag(e, "hr", commonAttr, "", true) -macro i*(e: expr): expr {.immediate.} = +macro i*(e: expr): expr {.immediate.} = ## generates the HTML ``i`` element. let e = callsite() result = xmlCheckedTag(e, "i", commonAttr) -macro img*(e: expr): expr {.immediate.} = +macro img*(e: expr): expr {.immediate.} = ## generates the HTML ``img`` element. let e = callsite() result = xmlCheckedTag(e, "img", "longdesc height width", "src alt", true) -macro input*(e: expr): expr {.immediate.} = +macro input*(e: expr): expr {.immediate.} = ## generates the HTML ``input`` element. let e = callsite() result = xmlCheckedTag(e, "input", "name type value checked maxlength src" & " alt accept disabled readonly accesskey tabindex" & commonAttr, "", true) -macro ins*(e: expr): expr {.immediate.} = +macro ins*(e: expr): expr {.immediate.} = ## generates the HTML ``ins`` element. let e = callsite() result = xmlCheckedTag(e, "ins", "cite datetime" & commonAttr) -macro kbd*(e: expr): expr {.immediate.} = +macro kbd*(e: expr): expr {.immediate.} = ## generates the HTML ``kbd`` element. let e = callsite() result = xmlCheckedTag(e, "kbd", commonAttr) -macro label*(e: expr): expr {.immediate.} = +macro label*(e: expr): expr {.immediate.} = ## generates the HTML ``label`` element. let e = callsite() result = xmlCheckedTag(e, "label", "for accesskey" & commonAttr) -macro legend*(e: expr): expr {.immediate.} = +macro legend*(e: expr): expr {.immediate.} = ## generates the HTML ``legend`` element. let e = callsite() result = xmlCheckedTag(e, "legend", "accesskey" & commonAttr) -macro li*(e: expr): expr {.immediate.} = +macro li*(e: expr): expr {.immediate.} = ## generates the HTML ``li`` element. let e = callsite() result = xmlCheckedTag(e, "li", commonAttr) -macro link*(e: expr): expr {.immediate.} = +macro link*(e: expr): expr {.immediate.} = ## generates the HTML ``link`` element. let e = callsite() - result = xmlCheckedTag(e, "link", "href charset hreflang type rel rev media" & + result = xmlCheckedTag(e, "link", "href charset hreflang type rel rev media" & commonAttr, "", true) -macro map*(e: expr): expr {.immediate.} = +macro map*(e: expr): expr {.immediate.} = ## generates the HTML ``map`` element. let e = callsite() result = xmlCheckedTag(e, "map", "class title" & eventAttr, "id", false) -macro meta*(e: expr): expr {.immediate.} = +macro meta*(e: expr): expr {.immediate.} = ## generates the HTML ``meta`` element. let e = callsite() result = xmlCheckedTag(e, "meta", "name http-equiv scheme", "content", true) -macro noscript*(e: expr): expr {.immediate.} = +macro noscript*(e: expr): expr {.immediate.} = ## generates the HTML ``noscript`` element. let e = callsite() result = xmlCheckedTag(e, "noscript", commonAttr) -macro `object`*(e: expr): expr {.immediate.} = +macro `object`*(e: expr): expr {.immediate.} = ## generates the HTML ``object`` element. let e = callsite() result = xmlCheckedTag(e, "object", "classid data codebase declare type " & "codetype archive standby width height name tabindex" & commonAttr) -macro ol*(e: expr): expr {.immediate.} = +macro ol*(e: expr): expr {.immediate.} = ## generates the HTML ``ol`` element. let e = callsite() result = xmlCheckedTag(e, "ol", commonAttr) -macro optgroup*(e: expr): expr {.immediate.} = +macro optgroup*(e: expr): expr {.immediate.} = ## generates the HTML ``optgroup`` element. let e = callsite() result = xmlCheckedTag(e, "optgroup", "disabled" & commonAttr, "label", false) -macro option*(e: expr): expr {.immediate.} = +macro option*(e: expr): expr {.immediate.} = ## generates the HTML ``option`` element. let e = callsite() result = xmlCheckedTag(e, "option", "selected value" & commonAttr) -macro p*(e: expr): expr {.immediate.} = +macro p*(e: expr): expr {.immediate.} = ## generates the HTML ``p`` element. let e = callsite() result = xmlCheckedTag(e, "p", commonAttr) -macro param*(e: expr): expr {.immediate.} = +macro param*(e: expr): expr {.immediate.} = ## generates the HTML ``param`` element. let e = callsite() result = xmlCheckedTag(e, "param", "value id type valuetype", "name", true) -macro pre*(e: expr): expr {.immediate.} = +macro pre*(e: expr): expr {.immediate.} = ## generates the HTML ``pre`` element. let e = callsite() result = xmlCheckedTag(e, "pre", commonAttr) -macro q*(e: expr): expr {.immediate.} = +macro q*(e: expr): expr {.immediate.} = ## generates the HTML ``q`` element. let e = callsite() result = xmlCheckedTag(e, "q", "cite" & commonAttr) -macro samp*(e: expr): expr {.immediate.} = +macro samp*(e: expr): expr {.immediate.} = ## generates the HTML ``samp`` element. let e = callsite() result = xmlCheckedTag(e, "samp", commonAttr) -macro script*(e: expr): expr {.immediate.} = +macro script*(e: expr): expr {.immediate.} = ## generates the HTML ``script`` element. let e = callsite() result = xmlCheckedTag(e, "script", "src charset defer", "type", false) -macro select*(e: expr): expr {.immediate.} = +macro select*(e: expr): expr {.immediate.} = ## generates the HTML ``select`` element. let e = callsite() - result = xmlCheckedTag(e, "select", "name size multiple disabled tabindex" & + result = xmlCheckedTag(e, "select", "name size multiple disabled tabindex" & commonAttr) -macro small*(e: expr): expr {.immediate.} = +macro small*(e: expr): expr {.immediate.} = ## generates the HTML ``small`` element. let e = callsite() result = xmlCheckedTag(e, "small", commonAttr) -macro span*(e: expr): expr {.immediate.} = +macro span*(e: expr): expr {.immediate.} = ## generates the HTML ``span`` element. let e = callsite() result = xmlCheckedTag(e, "span", commonAttr) -macro strong*(e: expr): expr {.immediate.} = +macro strong*(e: expr): expr {.immediate.} = ## generates the HTML ``strong`` element. let e = callsite() result = xmlCheckedTag(e, "strong", commonAttr) -macro style*(e: expr): expr {.immediate.} = +macro style*(e: expr): expr {.immediate.} = ## generates the HTML ``style`` element. let e = callsite() result = xmlCheckedTag(e, "style", "media title", "type") -macro sub*(e: expr): expr {.immediate.} = +macro sub*(e: expr): expr {.immediate.} = ## generates the HTML ``sub`` element. let e = callsite() result = xmlCheckedTag(e, "sub", commonAttr) -macro sup*(e: expr): expr {.immediate.} = +macro sup*(e: expr): expr {.immediate.} = ## generates the HTML ``sup`` element. let e = callsite() result = xmlCheckedTag(e, "sup", commonAttr) -macro table*(e: expr): expr {.immediate.} = +macro table*(e: expr): expr {.immediate.} = ## generates the HTML ``table`` element. let e = callsite() result = xmlCheckedTag(e, "table", "summary border cellpadding cellspacing" & " frame rules width" & commonAttr) -macro tbody*(e: expr): expr {.immediate.} = +macro tbody*(e: expr): expr {.immediate.} = ## generates the HTML ``tbody`` element. let e = callsite() result = xmlCheckedTag(e, "tbody", "align valign" & commonAttr) -macro td*(e: expr): expr {.immediate.} = +macro td*(e: expr): expr {.immediate.} = ## generates the HTML ``td`` element. let e = callsite() result = xmlCheckedTag(e, "td", "colspan rowspan abbr axis headers scope" & " align valign" & commonAttr) -macro textarea*(e: expr): expr {.immediate.} = +macro textarea*(e: expr): expr {.immediate.} = ## generates the HTML ``textarea`` element. let e = callsite() result = xmlCheckedTag(e, "textarea", " name disabled readonly accesskey" & " tabindex" & commonAttr, "rows cols", false) -macro tfoot*(e: expr): expr {.immediate.} = +macro tfoot*(e: expr): expr {.immediate.} = ## generates the HTML ``tfoot`` element. let e = callsite() result = xmlCheckedTag(e, "tfoot", "align valign" & commonAttr) -macro th*(e: expr): expr {.immediate.} = +macro th*(e: expr): expr {.immediate.} = ## generates the HTML ``th`` element. let e = callsite() result = xmlCheckedTag(e, "th", "colspan rowspan abbr axis headers scope" & " align valign" & commonAttr) -macro thead*(e: expr): expr {.immediate.} = +macro thead*(e: expr): expr {.immediate.} = ## generates the HTML ``thead`` element. let e = callsite() result = xmlCheckedTag(e, "thead", "align valign" & commonAttr) -macro title*(e: expr): expr {.immediate.} = +macro title*(e: expr): expr {.immediate.} = ## generates the HTML ``title`` element. let e = callsite() result = xmlCheckedTag(e, "title") -macro tr*(e: expr): expr {.immediate.} = +macro tr*(e: expr): expr {.immediate.} = ## generates the HTML ``tr`` element. let e = callsite() result = xmlCheckedTag(e, "tr", "align valign" & commonAttr) -macro tt*(e: expr): expr {.immediate.} = +macro tt*(e: expr): expr {.immediate.} = ## generates the HTML ``tt`` element. let e = callsite() result = xmlCheckedTag(e, "tt", commonAttr) -macro ul*(e: expr): expr {.immediate.} = +macro ul*(e: expr): expr {.immediate.} = ## generates the HTML ``ul`` element. let e = callsite() result = xmlCheckedTag(e, "ul", commonAttr) -macro `var`*(e: expr): expr {.immediate.} = +macro `var`*(e: expr): expr {.immediate.} = ## generates the HTML ``var`` element. let e = callsite() result = xmlCheckedTag(e, "var", commonAttr) diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 5041fe2f6..c3db5bdf8 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -8,8 +8,8 @@ # ## This module implements a simple high performance `JSON`:idx: -## parser. JSON (JavaScript Object Notation) is a lightweight -## data-interchange format that is easy for humans to read and write +## parser. JSON (JavaScript Object Notation) is a lightweight +## data-interchange format that is easy for humans to read and write ## (unlike XML). It is easy for machines to parse and generate. ## JSON is based on a subset of the JavaScript Programming Language, ## Standard ECMA-262 3rd Edition - December 1999. @@ -50,10 +50,10 @@ ## } ## ] -import +import hashes, strutils, lexbase, streams, unicode, macros -type +type JsonEventKind* = enum ## enumeration of all events that may occur when parsing jsonError, ## an error occurred during parsing jsonEof, ## end of file reached @@ -67,7 +67,7 @@ type jsonObjectEnd, ## end of an object: the ``}`` token jsonArrayStart, ## start of an array: the ``[`` token jsonArrayEnd ## start of an array: the ``]`` token - + TTokKind = enum # must be synchronized with TJsonEventKind! tkError, tkEof, @@ -83,7 +83,7 @@ type tkBracketRi, tkColon, tkComma - + JsonError* = enum ## enumeration that lists all errors that can occur errNone, ## no error errInvalidToken, ## invalid token @@ -96,8 +96,8 @@ type errEOC_Expected, ## ``*/`` expected errEofExpected, ## EOF expected errExprExpected ## expr expected - - ParserState = enum + + ParserState = enum stateEof, stateStart, stateObject, stateArray, stateExpectArrayComma, stateExpectObjectComma, stateExpectColon, stateExpectValue @@ -111,7 +111,7 @@ type {.deprecated: [TJsonEventKind: JsonEventKind, TJsonError: JsonError, TJsonParser: JsonParser].} - + const errorMessages: array [JsonError, string] = [ "no error", @@ -146,56 +146,56 @@ proc open*(my: var JsonParser, input: Stream, filename: string) = my.state = @[stateStart] my.kind = jsonError my.a = "" - -proc close*(my: var JsonParser) {.inline.} = + +proc close*(my: var JsonParser) {.inline.} = ## closes the parser `my` and its associated input stream. lexbase.close(my) -proc str*(my: JsonParser): string {.inline.} = - ## returns the character data for the events: ``jsonInt``, ``jsonFloat``, +proc str*(my: JsonParser): string {.inline.} = + ## returns the character data for the events: ``jsonInt``, ``jsonFloat``, ## ``jsonString`` assert(my.kind in {jsonInt, jsonFloat, jsonString}) return my.a -proc getInt*(my: JsonParser): BiggestInt {.inline.} = +proc getInt*(my: JsonParser): BiggestInt {.inline.} = ## returns the number for the event: ``jsonInt`` assert(my.kind == jsonInt) return parseBiggestInt(my.a) -proc getFloat*(my: JsonParser): float {.inline.} = +proc getFloat*(my: JsonParser): float {.inline.} = ## returns the number for the event: ``jsonFloat`` assert(my.kind == jsonFloat) return parseFloat(my.a) -proc kind*(my: JsonParser): JsonEventKind {.inline.} = +proc kind*(my: JsonParser): JsonEventKind {.inline.} = ## returns the current event type for the JSON parser return my.kind - -proc getColumn*(my: JsonParser): int {.inline.} = + +proc getColumn*(my: JsonParser): int {.inline.} = ## get the current column the parser has arrived at. result = getColNumber(my, my.bufpos) -proc getLine*(my: JsonParser): int {.inline.} = +proc getLine*(my: JsonParser): int {.inline.} = ## get the current line the parser has arrived at. result = my.lineNumber -proc getFilename*(my: JsonParser): string {.inline.} = +proc getFilename*(my: JsonParser): string {.inline.} = ## get the filename of the file that the parser processes. result = my.filename - -proc errorMsg*(my: JsonParser): string = + +proc errorMsg*(my: JsonParser): string = ## returns a helpful error message for the event ``jsonError`` assert(my.kind == jsonError) result = "$1($2, $3) Error: $4" % [ my.filename, $getLine(my), $getColumn(my), errorMessages[my.err]] -proc errorMsgExpected*(my: JsonParser, e: string): string = +proc errorMsgExpected*(my: JsonParser, e: string): string = ## returns an error message "`e` expected" in the same format as the - ## other error messages + ## other error messages result = "$1($2, $3) Error: $4" % [ my.filename, $getLine(my), $getColumn(my), e & " expected"] -proc handleHexChar(c: char, x: var int): bool = +proc handleHexChar(c: char, x: var int): bool = result = true # Success case c of '0'..'9': x = (x shl 4) or (ord(c) - ord('0')) @@ -208,8 +208,8 @@ proc parseString(my: var JsonParser): TTokKind = var pos = my.bufpos + 1 var buf = my.buf while true: - case buf[pos] - of '\0': + case buf[pos] + of '\0': my.err = errQuoteExpected result = tkError break @@ -218,21 +218,21 @@ proc parseString(my: var JsonParser): TTokKind = break of '\\': case buf[pos+1] - of '\\', '"', '\'', '/': + of '\\', '"', '\'', '/': add(my.a, buf[pos+1]) inc(pos, 2) of 'b': add(my.a, '\b') - inc(pos, 2) + inc(pos, 2) of 'f': add(my.a, '\f') - inc(pos, 2) + inc(pos, 2) of 'n': add(my.a, '\L') - inc(pos, 2) + inc(pos, 2) of 'r': add(my.a, '\C') - inc(pos, 2) + inc(pos, 2) of 't': add(my.a, '\t') inc(pos, 2) @@ -244,15 +244,15 @@ proc parseString(my: var JsonParser): TTokKind = if handleHexChar(buf[pos], r): inc(pos) if handleHexChar(buf[pos], r): inc(pos) add(my.a, toUTF8(Rune(r))) - else: + else: # don't bother with the error add(my.a, buf[pos]) inc(pos) - of '\c': + of '\c': pos = lexbase.handleCR(my, pos) buf = my.buf add(my.a, '\c') - of '\L': + of '\L': pos = lexbase.handleLF(my, pos) buf = my.buf add(my.a, '\L') @@ -260,25 +260,25 @@ proc parseString(my: var JsonParser): TTokKind = add(my.a, buf[pos]) inc(pos) my.bufpos = pos # store back - -proc skip(my: var JsonParser) = + +proc skip(my: var JsonParser) = var pos = my.bufpos var buf = my.buf - while true: + while true: case buf[pos] - of '/': - if buf[pos+1] == '/': + of '/': + if buf[pos+1] == '/': # skip line comment: inc(pos, 2) while true: - case buf[pos] - of '\0': + case buf[pos] + of '\0': break - of '\c': + of '\c': pos = lexbase.handleCR(my, pos) buf = my.buf break - of '\L': + of '\L': pos = lexbase.handleLF(my, pos) buf = my.buf break @@ -288,44 +288,44 @@ proc skip(my: var JsonParser) = # skip long comment: inc(pos, 2) while true: - case buf[pos] - of '\0': + case buf[pos] + of '\0': my.err = errEOC_Expected break - of '\c': + of '\c': pos = lexbase.handleCR(my, pos) buf = my.buf - of '\L': + of '\L': pos = lexbase.handleLF(my, pos) buf = my.buf of '*': inc(pos) - if buf[pos] == '/': + if buf[pos] == '/': inc(pos) break else: inc(pos) - else: + else: break - of ' ', '\t': + of ' ', '\t': inc(pos) - of '\c': + of '\c': pos = lexbase.handleCR(my, pos) buf = my.buf - of '\L': + of '\L': pos = lexbase.handleLF(my, pos) buf = my.buf else: break my.bufpos = pos -proc parseNumber(my: var JsonParser) = +proc parseNumber(my: var JsonParser) = var pos = my.bufpos var buf = my.buf - if buf[pos] == '-': + if buf[pos] == '-': add(my.a, '-') inc(pos) - if buf[pos] == '.': + if buf[pos] == '.': add(my.a, "0.") inc(pos) else: @@ -350,7 +350,7 @@ proc parseNumber(my: var JsonParser) = inc(pos) my.bufpos = pos -proc parseName(my: var JsonParser) = +proc parseName(my: var JsonParser) = var pos = my.bufpos var buf = my.buf if buf[pos] in IdentStartChars: @@ -359,11 +359,11 @@ proc parseName(my: var JsonParser) = inc(pos) my.bufpos = pos -proc getTok(my: var JsonParser): TTokKind = +proc getTok(my: var JsonParser): TTokKind = setLen(my.a, 0) skip(my) # skip whitespace, comments case my.buf[my.bufpos] - of '-', '.', '0'..'9': + of '-', '.', '0'..'9': parseNumber(my) if {'.', 'e', 'E'} in my.a: result = tkFloat @@ -393,17 +393,17 @@ proc getTok(my: var JsonParser): TTokKind = result = tkEof of 'a'..'z', 'A'..'Z', '_': parseName(my) - case my.a + case my.a of "null": result = tkNull of "true": result = tkTrue of "false": result = tkFalse else: result = tkError - else: + else: inc(my.bufpos) result = tkError my.tok = result -proc next*(my: var JsonParser) = +proc next*(my: var JsonParser) = ## retrieves the first/next event. This controls the parser. var tk = getTok(my) var i = my.state.len-1 @@ -416,13 +416,13 @@ proc next*(my: var JsonParser) = else: my.kind = jsonError my.err = errEofExpected - of stateStart: - # tokens allowed? + of stateStart: + # tokens allowed? case tk of tkString, tkInt, tkFloat, tkTrue, tkFalse, tkNull: my.state[i] = stateEof # expect EOF next! my.kind = JsonEventKind(ord(tk)) - of tkBracketLe: + of tkBracketLe: my.state.add(stateArray) # we expect any my.kind = jsonArrayStart of tkCurlyLe: @@ -433,12 +433,12 @@ proc next*(my: var JsonParser) = else: my.kind = jsonError my.err = errEofExpected - of stateObject: + of stateObject: case tk of tkString, tkInt, tkFloat, tkTrue, tkFalse, tkNull: my.state.add(stateExpectColon) my.kind = JsonEventKind(ord(tk)) - of tkBracketLe: + of tkBracketLe: my.state.add(stateExpectColon) my.state.add(stateArray) my.kind = jsonArrayStart @@ -457,7 +457,7 @@ proc next*(my: var JsonParser) = of tkString, tkInt, tkFloat, tkTrue, tkFalse, tkNull: my.state.add(stateExpectArrayComma) # expect value next! my.kind = JsonEventKind(ord(tk)) - of tkBracketLe: + of tkBracketLe: my.state.add(stateExpectArrayComma) my.state.add(stateArray) my.kind = jsonArrayStart @@ -472,8 +472,8 @@ proc next*(my: var JsonParser) = my.kind = jsonError my.err = errBracketRiExpected of stateExpectArrayComma: - case tk - of tkComma: + case tk + of tkComma: discard my.state.pop() next(my) of tkBracketRi: @@ -484,8 +484,8 @@ proc next*(my: var JsonParser) = my.kind = jsonError my.err = errBracketRiExpected of stateExpectObjectComma: - case tk - of tkComma: + case tk + of tkComma: discard my.state.pop() next(my) of tkCurlyRi: @@ -495,9 +495,9 @@ proc next*(my: var JsonParser) = else: my.kind = jsonError my.err = errCurlyRiExpected - of stateExpectColon: - case tk - of tkColon: + of stateExpectColon: + case tk + of tkColon: my.state[i] = stateExpectValue next(my) else: @@ -508,7 +508,7 @@ proc next*(my: var JsonParser) = of tkString, tkInt, tkFloat, tkTrue, tkFalse, tkNull: my.state[i] = stateExpectObjectComma my.kind = JsonEventKind(ord(tk)) - of tkBracketLe: + of tkBracketLe: my.state[i] = stateExpectObjectComma my.state.add(stateArray) my.kind = jsonArrayStart @@ -532,8 +532,8 @@ type JString, JObject, JArray - - JsonNode* = ref JsonNodeObj ## JSON node + + JsonNode* = ref JsonNodeObj ## JSON node JsonNodeObj* {.acyclic.} = object case kind*: JsonNodeKind of JString: @@ -644,7 +644,7 @@ proc `%`*(elements: openArray[JsonNode]): JsonNode = newSeq(result.elems, elements.len) for i, p in pairs(elements): result.elems[i] = p -proc toJson(x: PNimrodNode): PNimrodNode {.compiletime.} = +proc toJson(x: NimNode): NimNode {.compiletime.} = case x.kind of nnkBracket: result = newNimNode(nnkBracket) @@ -672,7 +672,7 @@ proc `==`* (a,b: JsonNode): bool = if a.isNil: if b.isNil: return true return false - elif b.isNil or a.kind != b.kind: + elif b.isNil or a.kind != b.kind: return false else: return case a.kind @@ -709,7 +709,7 @@ proc hash* (n:JsonNode): THash = of JNull: result = hash(0) -proc len*(n: JsonNode): int = +proc len*(n: JsonNode): int = ## If `n` is a `JArray`, it returns the number of elements. ## If `n` is a `JObject`, it returns the number of pairs. ## Else it returns 0. @@ -727,7 +727,7 @@ proc `[]`*(node: JsonNode, name: string): JsonNode = if key == name: return item return nil - + proc `[]`*(node: JsonNode, index: int): JsonNode = ## Gets the node at `index` in an Array. Result is undefined if `index` ## is out of bounds @@ -744,12 +744,12 @@ proc hasKey*(node: JsonNode, key: string): bool = proc existsKey*(node: JsonNode, key: string): bool {.deprecated.} = node.hasKey(key) ## Deprecated for `hasKey` -proc add*(father, child: JsonNode) = - ## Adds `child` to a JArray node `father`. +proc add*(father, child: JsonNode) = + ## Adds `child` to a JArray node `father`. assert father.kind == JArray father.elems.add(child) -proc add*(obj: JsonNode, key: string, val: JsonNode) = +proc add*(obj: JsonNode, key: string, val: JsonNode) = ## Adds ``(key, val)`` pair to the JObject node `obj`. For speed ## reasons no check for duplicate keys is performed! ## But ``[]=`` performs the check. @@ -760,7 +760,7 @@ proc `[]=`*(obj: JsonNode, key: string, val: JsonNode) = ## Sets a field from a `JObject`. Performs a check for duplicate keys. assert(obj.kind == JObject) for i in 0..obj.fields.len-1: - if obj.fields[i].key == key: + if obj.fields[i].key == key: obj.fields[i].val = val return obj.fields.add((key, val)) @@ -815,17 +815,17 @@ proc copy*(p: JsonNode): JsonNode = # ------------- pretty printing ---------------------------------------------- -proc indent(s: var string, i: int) = +proc indent(s: var string, i: int) = s.add(spaces(i)) proc newIndent(curr, indent: int, ml: bool): int = if ml: return curr + indent else: return indent -proc nl(s: var string, ml: bool) = +proc nl(s: var string, ml: bool) = if ml: s.add("\n") -proc escapeJson*(s: string): string = +proc escapeJson*(s: string): string = ## Converts a string `s` to its JSON representation. result = newStringOfCap(s.len + s.len shr 3) result.add("\"") @@ -842,13 +842,13 @@ proc escapeJson*(s: string): string = result.add(toHex(r, 4)) result.add("\"") -proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true, +proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true, lstArr = false, currIndent = 0) = case node.kind of JObject: if currIndent != 0 and not lstArr: result.nl(ml) result.indent(currIndent) # Indentation - if node.fields.len > 0: + if node.fields.len > 0: result.add("{") result.nl(ml) # New line for i in 0..len(node.fields)-1: @@ -856,17 +856,17 @@ proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true, result.add(", ") result.nl(ml) # New Line # Need to indent more than { - result.indent(newIndent(currIndent, indent, ml)) + result.indent(newIndent(currIndent, indent, ml)) result.add(escapeJson(node.fields[i].key)) result.add(": ") - toPretty(result, node.fields[i].val, indent, ml, false, + toPretty(result, node.fields[i].val, indent, ml, false, newIndent(currIndent, indent, ml)) result.nl(ml) result.indent(currIndent) # indent the same as { result.add("}") else: result.add("{}") - of JString: + of JString: if lstArr: result.indent(currIndent) result.add(escapeJson(node.str)) of JInt: @@ -934,11 +934,11 @@ iterator mpairs*(node: var JsonNode): var tuple[key: string, val: JsonNode] = for keyVal in mitems(node.fields): yield keyVal -proc eat(p: var JsonParser, tok: TTokKind) = +proc eat(p: var JsonParser, tok: TTokKind) = if p.tok == tok: discard getTok(p) else: raiseParseErr(p, tokToStr[tok]) -proc parseJson(p: var JsonParser): JsonNode = +proc parseJson(p: var JsonParser): JsonNode = ## Parses JSON from a JSON Parser `p`. case p.tok of tkString: @@ -955,17 +955,17 @@ proc parseJson(p: var JsonParser): JsonNode = of tkTrue: result = newJBool(true) discard getTok(p) - of tkFalse: + of tkFalse: result = newJBool(false) discard getTok(p) - of tkNull: + of tkNull: result = newJNull() discard getTok(p) - of tkCurlyLe: + of tkCurlyLe: result = newJObject() discard getTok(p) - while p.tok != tkCurlyRi: - if p.tok != tkString: + while p.tok != tkCurlyRi: + if p.tok != tkString: raiseParseErr(p, "string literal as key expected") var key = p.a discard getTok(p) @@ -978,7 +978,7 @@ proc parseJson(p: var JsonParser): JsonNode = of tkBracketLe: result = newJArray() discard getTok(p) - while p.tok != tkBracketRi: + while p.tok != tkBracketRi: result.add(parseJson(p)) if p.tok != tkComma: break discard getTok(p) @@ -1098,10 +1098,10 @@ when false: of jsonObjectEnd: echo("}") of jsonArrayStart: echo("[") of jsonArrayEnd: echo("]") - + close(x) -# { "json": 5 } +# { "json": 5 } # To get that we shall use, obj["json"] when isMainModule: diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim index f4e42ee63..3bf4724b9 100644 --- a/lib/pure/unittest.nim +++ b/lib/pure/unittest.nim @@ -47,7 +47,7 @@ type {.deprecated: [TTestStatus: TestStatus, TOutputLevel: OutputLevel]} -var +var abortOnError* {.threadvar.}: bool outputLevel* {.threadvar.}: OutputLevel colorOutput* {.threadvar.}: bool @@ -144,7 +144,7 @@ macro check*(conditions: stmt): stmt {.immediate.} = when compiles(string($value)): checkpoint(name & " was " & $value) - proc inspectArgs(exp: PNimrodNode) = + proc inspectArgs(exp: NimNode) = for i in 1 .. <exp.len: if exp[i].kind notin nnkLiterals: inc counter @@ -202,7 +202,7 @@ template require*(conditions: stmt): stmt {.immediate, dirty.} = macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} = let exp = callsite() template expectBody(errorTypes, lineInfoLit: expr, - body: stmt): PNimrodNode {.dirty.} = + body: stmt): NimNode {.dirty.} = try: body checkpoint(lineInfoLit & ": Expect Failed, no exception was thrown.") diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim index c783158ea..0bf5b52a4 100644 --- a/lib/pure/xmltree.nim +++ b/lib/pure/xmltree.nim @@ -12,20 +12,20 @@ import macros, strtabs type - XmlNode* = ref XmlNodeObj ## an XML tree consists of ``PXmlNode``'s. - + XmlNode* = ref XmlNodeObj ## an XML tree consists of ``PXmlNode``'s. + XmlNodeKind* = enum ## different kinds of ``PXmlNode``'s xnText, ## a text element xnElement, ## an element with 0 or more children xnCData, ## a CDATA node xnEntity, ## an entity (like ``&thing;``) xnComment ## an XML comment - + XmlAttributes* = StringTableRef ## an alias for a string to string mapping - - XmlNodeObj {.acyclic.} = object + + XmlNodeObj {.acyclic.} = object case k: XmlNodeKind # private, use the kind() proc to read this field. - of xnText, xnComment, xnCData, xnEntity: + of xnText, xnComment, xnCData, xnEntity: fText: string of xnElement: fTag: string @@ -41,34 +41,34 @@ proc newXmlNode(kind: XmlNodeKind): XmlNode = new(result) result.k = kind -proc newElement*(tag: string): XmlNode = +proc newElement*(tag: string): XmlNode = ## creates a new ``PXmlNode`` of kind ``xnText`` with the given `tag`. result = newXmlNode(xnElement) result.fTag = tag result.s = @[] # init attributes lazily to safe memory -proc newText*(text: string): XmlNode = +proc newText*(text: string): XmlNode = ## creates a new ``PXmlNode`` of kind ``xnText`` with the text `text`. result = newXmlNode(xnText) result.fText = text -proc newComment*(comment: string): XmlNode = +proc newComment*(comment: string): XmlNode = ## creates a new ``PXmlNode`` of kind ``xnComment`` with the text `comment`. result = newXmlNode(xnComment) result.fText = comment -proc newCData*(cdata: string): XmlNode = +proc newCData*(cdata: string): XmlNode = ## creates a new ``PXmlNode`` of kind ``xnComment`` with the text `cdata`. result = newXmlNode(xnCData) result.fText = cdata -proc newEntity*(entity: string): XmlNode = +proc newEntity*(entity: string): XmlNode = ## creates a new ``PXmlNode`` of kind ``xnEntity`` with the text `entity`. result = newXmlNode(xnCData) result.fText = entity -proc text*(n: XmlNode): string {.inline.} = +proc text*(n: XmlNode): string {.inline.} = ## gets the associated text with the node `n`. `n` can be a CDATA, Text, ## comment, or entity node. assert n.k in {xnText, xnComment, xnCData, xnEntity} @@ -93,16 +93,16 @@ proc innerText*(n: XmlNode): string = for i in 0 .. n.s.len-1: if n.s[i].k in {xnText, xnEntity}: result.add(n.s[i].fText) -proc tag*(n: XmlNode): string {.inline.} = +proc tag*(n: XmlNode): string {.inline.} = ## gets the tag name of `n`. `n` has to be an ``xnElement`` node. assert n.k == xnElement result = n.fTag - -proc add*(father, son: XmlNode) {.inline.} = + +proc add*(father, son: XmlNode) {.inline.} = ## adds the child `son` to `father`. add(father.s, son) - -proc len*(n: XmlNode): int {.inline.} = + +proc len*(n: XmlNode): int {.inline.} = ## returns the number `n`'s children. if n.k == xnElement: result = len(n.s) @@ -110,38 +110,38 @@ proc kind*(n: XmlNode): XmlNodeKind {.inline.} = ## returns `n`'s kind. result = n.k -proc `[]`* (n: XmlNode, i: int): XmlNode {.inline.} = +proc `[]`* (n: XmlNode, i: int): XmlNode {.inline.} = ## returns the `i`'th child of `n`. assert n.k == xnElement result = n.s[i] -proc mget* (n: var XmlNode, i: int): var XmlNode {.inline.} = +proc mget* (n: var XmlNode, i: int): var XmlNode {.inline.} = ## returns the `i`'th child of `n` so that it can be modified assert n.k == xnElement result = n.s[i] -iterator items*(n: XmlNode): XmlNode {.inline.} = +iterator items*(n: XmlNode): XmlNode {.inline.} = ## iterates over any child of `n`. assert n.k == xnElement for i in 0 .. n.len-1: yield n[i] -iterator mitems*(n: var XmlNode): var XmlNode {.inline.} = +iterator mitems*(n: var XmlNode): var XmlNode {.inline.} = ## iterates over any child of `n`. assert n.k == xnElement for i in 0 .. n.len-1: yield mget(n, i) -proc attrs*(n: XmlNode): XmlAttributes {.inline.} = +proc attrs*(n: XmlNode): XmlAttributes {.inline.} = ## gets the attributes belonging to `n`. ## Returns `nil` if attributes have not been initialised for this node. assert n.k == xnElement result = n.fAttr - -proc `attrs=`*(n: XmlNode, attr: XmlAttributes) {.inline.} = + +proc `attrs=`*(n: XmlNode, attr: XmlAttributes) {.inline.} = ## sets the attributes belonging to `n`. assert n.k == xnElement n.fAttr = attr -proc attrsLen*(n: XmlNode): int {.inline.} = +proc attrsLen*(n: XmlNode): int {.inline.} = ## returns the number of `n`'s attributes. assert n.k == xnElement if not isNil(n.fAttr): result = len(n.fAttr) @@ -151,12 +151,12 @@ proc clientData*(n: XmlNode): int {.inline.} = ## parser and generator. result = n.fClientData -proc `clientData=`*(n: XmlNode, data: int) {.inline.} = +proc `clientData=`*(n: XmlNode, data: int) {.inline.} = ## sets the client data of `n`. The client data field is used by the HTML ## parser and generator. n.fClientData = data -proc addEscaped*(result: var string, s: string) = +proc addEscaped*(result: var string, s: string) = ## same as ``result.add(escape(s))``, but more efficient. for c in items(s): case c @@ -168,8 +168,8 @@ proc addEscaped*(result: var string, s: string) = of '/': result.add("/") else: result.add(c) -proc escape*(s: string): string = - ## escapes `s` for inclusion into an XML document. +proc escape*(s: string): string = + ## escapes `s` for inclusion into an XML document. ## Escapes these characters: ## ## ------------ ------------------- @@ -184,26 +184,26 @@ proc escape*(s: string): string = ## ------------ ------------------- result = newStringOfCap(s.len) addEscaped(result, s) - -proc addIndent(result: var string, indent: int) = + +proc addIndent(result: var string, indent: int) = result.add("\n") for i in 1..indent: result.add(' ') - + proc noWhitespace(n: XmlNode): bool = #for i in 1..n.len-1: # if n[i].kind != n[0].kind: return true for i in 0..n.len-1: if n[i].kind in {xnText, xnEntity}: return true - -proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) = + +proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) = ## adds the textual representation of `n` to `result`. if n == nil: return case n.k of xnElement: result.add('<') result.add(n.fTag) - if not isNil(n.fAttr): - for key, val in pairs(n.fAttr): + if not isNil(n.fAttr): + for key, val in pairs(n.fAttr): result.add(' ') result.add(key) result.add("=\"") @@ -217,7 +217,7 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) = # because this would be wrong. For example: ``a<b>b</b>`` is # different from ``a <b>b</b>``. for i in 0..n.len-1: result.add(n[i], indent+indWidth, indWidth) - else: + else: for i in 0..n.len-1: result.addIndent(indent+indWidth) result.add(n[i], indent+indWidth, indWidth) @@ -227,7 +227,7 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) = result.add("</") result.add(n.fTag) result.add(">") - else: + else: result.add(" />") of xnText: result.addEscaped(n.fText) @@ -245,7 +245,7 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) = result.add(';') const - xmlHeader* = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + xmlHeader* = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" ## header to use for complete XML output proc `$`*(n: XmlNode): string = @@ -255,21 +255,21 @@ proc `$`*(n: XmlNode): string = result.add(n) proc newXmlTree*(tag: string, children: openArray[XmlNode], - attributes: XmlAttributes = nil): XmlNode = + attributes: XmlAttributes = nil): XmlNode = ## creates a new XML tree with `tag`, `children` and `attributes` result = newXmlNode(xnElement) result.fTag = tag newSeq(result.s, children.len) for i in 0..children.len-1: result.s[i] = children[i] result.fAttr = attributes - -proc xmlConstructor(e: PNimrodNode): PNimrodNode {.compileTime.} = + +proc xmlConstructor(e: NimNode): NimNode {.compileTime.} = expectLen(e, 2) var a = e[1] if a.kind == nnkCall: result = newCall("newXmlTree", toStrLit(a[0])) var attrs = newNimNode(nnkBracket, a) - var newStringTabCall = newCall("newStringTable", attrs, + var newStringTabCall = newCall("newStringTable", attrs, newIdentNode("modeCaseSensitive")) var elements = newNimNode(nnkBracket, a) for i in 1..a.len-1: @@ -280,13 +280,13 @@ proc xmlConstructor(e: PNimrodNode): PNimrodNode {.compileTime.} = else: elements.add(a[i]) result.add(elements) - if attrs.len > 1: + if attrs.len > 1: #echo repr(newStringTabCall) result.add(newStringTabCall) else: result = newCall("newXmlTree", toStrLit(a)) -macro `<>`*(x: expr): expr {.immediate.} = +macro `<>`*(x: expr): expr {.immediate.} = ## Constructor macro for XML. Example usage: ## ## .. code-block:: nim diff --git a/lib/system.nim b/lib/system.nim index ea35bd54a..23c911a19 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1224,7 +1224,7 @@ type # these work for most platforms: ## This is the same as the type ``unsigned char`` in *C*. cushort* {.importc: "unsigned short", nodecl.} = uint16 ## This is the same as the type ``unsigned short`` in *C*. - cuint* {.importc: "int", nodecl.} = uint32 + cuint* {.importc: "unsigned int", nodecl.} = uint32 ## This is the same as the type ``unsigned int`` in *C*. culonglong* {.importc: "unsigned long long", nodecl.} = uint64 ## This is the same as the type ``unsigned long long`` in *C*. @@ -3149,15 +3149,9 @@ proc shallow*(s: var string) {.noSideEffect, inline.} = type NimNodeObj = object -when defined(nimnode): - type - NimNode* {.magic: "PNimrodNode".} = ref NimNodeObj - ## represents a Nim AST node. Macros operate on this type. - {.deprecated: [PNimrodNode: NimNode].} -else: - type - PNimrodNode* {.magic: "PNimrodNode".} = ref NimNodeObj - ## represents a Nim AST node. Macros operate on this type. + NimNode* {.magic: "PNimrodNode".} = ref NimNodeObj + ## represents a Nim AST node. Macros operate on this type. +{.deprecated: [PNimrodNode: NimNode].} when false: template eval*(blk: stmt): stmt = diff --git a/tests/caas/idetools_api.nim b/tests/caas/idetools_api.nim index 8f1061e27..281e562d7 100644 --- a/tests/caas/idetools_api.nim +++ b/tests/caas/idetools_api.nim @@ -58,7 +58,7 @@ macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} = ## Expect docstrings let exp = callsite() template expectBody(errorTypes, lineInfoLit: expr, - body: stmt): PNimrodNode {.dirty.} = + body: stmt): NimNode {.dirty.} = try: body assert false diff --git a/tests/collections/ttablesref.nim b/tests/collections/ttablesref.nim index b57aedf4a..16b0d831e 100644 --- a/tests/collections/ttablesref.nim +++ b/tests/collections/ttablesref.nim @@ -2,7 +2,7 @@ discard """ output: '''true''' """ -import hashes, tables +import hashes, tables, sequtils const data = { @@ -103,9 +103,10 @@ block countTableTest1: block SyntaxTest: var x = newTable[int, string]({:}) + discard x block nilTest: - var i, j: PTable[int, int] = nil + var i, j: TableRef[int, int] = nil assert i == j j = newTable[int, int]() assert i != j @@ -131,6 +132,10 @@ proc orderedTableSortTest() = # check that insert still works: t["newKeyHere"] = 80 +block anonZipTest: + let keys = @['a','b','c'] + let values = @[1, 2, 3] + doAssert "{a: 1, b: 2, c: 3}" == $ toTable zip(keys, values) orderedTableSortTest() echo "true" diff --git a/tests/metatype/udtcmanual.nim b/tests/concepts/tmanual.nim index dd44298dc..243992aed 100644 --- a/tests/metatype/udtcmanual.nim +++ b/tests/concepts/tmanual.nim @@ -12,6 +12,7 @@ e s t ''' + disabled: "true" """ template accept(e: expr) = diff --git a/tests/metatype/swizzle.nim b/tests/concepts/tswizzle.nim index ce18fa234..9bbdb67e6 100644 --- a/tests/metatype/swizzle.nim +++ b/tests/concepts/tswizzle.nim @@ -3,6 +3,7 @@ discard """ [1, 3] [2, 1, 2] ''' + disabled: "true" """ import macros, strutils @@ -18,14 +19,14 @@ proc swizzleIdx(c: char): int = of 'x': 0 of 'y': 1 of 'z': 2 - of 'w': 3 + of 'w': 3 of 'r': 0 of 'g': 1 of 'b': 2 - of 'a': 3 + of 'a': 3 else: 0 -proc isSwizzle(s: string): bool = +proc isSwizzle(s: string): bool {.compileTime.} = template trySet(name, set) = block search: for c in s: @@ -35,10 +36,10 @@ proc isSwizzle(s: string): bool = trySet coords, {'x', 'y', 'z', 'w'} trySet colors, {'r', 'g', 'b', 'a'} - + return false -type +type StringIsSwizzle = generic value value.isSwizzle @@ -47,33 +48,33 @@ type proc foo(x: SwizzleStr) = echo "sw" -accept foo("xx") +#foo("xx") reject foo("xe") -type +type Vec[N: static[int]; T] = array[N, T] +when false: + proc card(x: Vec): int = x.N + proc `$`(x: Vec): string = x.repr.strip -proc card(x: Vec): int = x.N -proc `$`(x: Vec): string = x.repr.strip + macro `.`(x: Vec, swizzle: SwizzleStr): expr = + var + cardinality = swizzle.len + values = newNimNode(nnkBracket) + v = genSym() -macro `.`(x: Vec, swizzle: SwizzleStr): expr = - var - cardinality = swizzle.len - values = newNimNode(nnkBracket) - v = genSym() + for c in swizzle: + values.add newNimNode(nnkBracketExpr).add( + v, c.swizzleIdx.newIntLitNode) - for c in swizzle: - values.add newNimNode(nnkBracketExpr).add( - v, c.swizzleIdx.newIntLitNode) - - return quote do: - let `v` = `x` - Vec[`cardinality`, `v`.T](`values`) + return quote do: + let `v` = `x` + Vec[`cardinality`, `v`.T](`values`) var z = Vec([1, 2, 3]) -echo z.card -echo z.xz -echo z.yxy +#echo z.card +#echo z.xz +#echo z.yxy diff --git a/tests/metatype/tusertypeclasses.nim b/tests/concepts/tusertypeclasses.nim index 4e5e6221c..4e5e6221c 100644 --- a/tests/metatype/tusertypeclasses.nim +++ b/tests/concepts/tusertypeclasses.nim diff --git a/tests/metatype/tusertypeclasses2.nim b/tests/concepts/tusertypeclasses2.nim index 77c70d7a6..77c70d7a6 100644 --- a/tests/metatype/tusertypeclasses2.nim +++ b/tests/concepts/tusertypeclasses2.nim diff --git a/tests/converter/ttypeconverter1.nim b/tests/converter/ttypeconverter1.nim index fd3a0318a..510b84700 100644 --- a/tests/converter/ttypeconverter1.nim +++ b/tests/converter/ttypeconverter1.nim @@ -1,5 +1,5 @@ discard """ - ouput: '''foo + output: '''foo true''' """ diff --git a/tests/generics/tarray_with_somenumber.nim b/tests/generics/tarray_with_somenumber.nim new file mode 100644 index 000000000..0bf2537a1 --- /dev/null +++ b/tests/generics/tarray_with_somenumber.nim @@ -0,0 +1,11 @@ +discard """ + output: '''@[0.9, 0.1]''' +""" + +# bug #2304 + +type TV2*[T:SomeNumber] = array[0..1, T] +proc newV2T*[T](x, y: T=0): TV2[T] = [x, y] + +let x = newV2T[float](0.9, 0.1) +echo(@x) diff --git a/tests/generics/tunique_type.nim b/tests/generics/tunique_type.nim index 29367181c..e78640caa 100644 --- a/tests/generics/tunique_type.nim +++ b/tests/generics/tunique_type.nim @@ -20,13 +20,13 @@ import strutils # This serves the same purpose as D's `alias` parameters for types, used heavily # in its popular `ranges` and `algorithm` modules. -var exprNodes {.compileTime.} = newSeq[PNimrodNode]() +var exprNodes {.compileTime.} = newSeq[NimNode]() -proc refExpr(exprNode: PNimrodNode): string {.compileTime.} = +proc refExpr(exprNode: NimNode): string {.compileTime.} = exprNodes.add exprNode.copy "expr" & $(exprNodes.len - 1) -proc derefExpr(exprRef: string): PNimrodNode {.compileTime.} = +proc derefExpr(exprRef: string): NimNode {.compileTime.} = exprNodes[parseInt(exprRef[4 .. -1])] #=============================================================================== diff --git a/tests/let/tlet2.nim b/tests/let/tlet2.nim index 8b1ddf940..66dd5a55b 100644 --- a/tests/let/tlet2.nim +++ b/tests/let/tlet2.nim @@ -1,6 +1,6 @@ discard """ line: "13" - errormsg: "for a 'var' type a variable needs to be passed" + errormsg: "type mismatch: got (int literal(8), int literal(5), int, int)" """ proc divmod(a, b: int, res, remainder: var int) = diff --git a/tests/macros/tbugs.nim b/tests/macros/tbugs.nim index 3db851dd1..1ecb0d4cc 100644 --- a/tests/macros/tbugs.nim +++ b/tests/macros/tbugs.nim @@ -46,13 +46,13 @@ echotest() # bug #1103 -type +type Td = tuple a:string b:int proc get_data(d: Td) : string {.compileTime.} = - result = d.a # Works if a literal string is used here. + result = d.a # Works if a literal string is used here. # Bugs if line A or B is active. Works with C result &= "aa" # A #result.add("aa") # B @@ -69,7 +69,7 @@ m(s) # bug #933 -proc nilcheck(): PNimrodNode {.compileTime.} = +proc nilcheck(): NimNode {.compileTime.} = echo(result == nil) # true echo(result.isNil) # true echo(repr(result)) # nil diff --git a/tests/macros/tdumpast.nim b/tests/macros/tdumpast.nim index 160e4e194..e3388591a 100644 --- a/tests/macros/tdumpast.nim +++ b/tests/macros/tdumpast.nim @@ -1,4 +1,4 @@ -# Dump the contents of a PNimrodNode +# Dump the contents of a NimNode import macros @@ -7,7 +7,7 @@ template plus(a, b: expr): expr {.dirty} = macro call(e: expr): expr = result = newCall("foo", newStrLitNode("bar")) - + macro dumpAST(n: stmt): stmt {.immediate.} = # dump AST as a side-effect and return the inner node let n = callsite() @@ -24,10 +24,10 @@ macro dumpAST(n: stmt): stmt {.immediate.} = echo e.lispRepr result = n[1] - + dumpAST: proc add(x, y: int): int = return x + y - + proc sub(x, y: int): int = return x - y diff --git a/tests/macros/tdumpast2.nim b/tests/macros/tdumpast2.nim index 2a7024a01..6b694fa77 100644 --- a/tests/macros/tdumpast2.nim +++ b/tests/macros/tdumpast2.nim @@ -1,13 +1,13 @@ -# Dump the contents of a PNimrodNode +# Dump the contents of a NimNode import macros -proc dumpit(n: PNimrodNode): string {.compileTime.} = +proc dumpit(n: NimNode): string {.compileTime.} = if n == nil: return "nil" result = $n.kind add(result, "(") case n.kind - of nnkEmpty: discard # same as nil node in this representation + of nnkEmpty: discard # same as nil node in this representation of nnkNilLit: add(result, "nil") of nnkCharLit..nnkInt64Lit: add(result, $n.intVal) of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal) @@ -20,17 +20,17 @@ proc dumpit(n: PNimrodNode): string {.compileTime.} = add(result, ", ") add(result, dumpit(n[j])) add(result, ")") - -macro dumpAST(n: stmt): stmt {.immediate.} = + +macro dumpAST(n: stmt): stmt {.immediate.} = # dump AST as a side-effect and return the inner node let n = callsite() echo dumpit(n) result = n[1] - + dumpAST: proc add(x, y: int): int = return x + y - + proc sub(x, y: int): int = return x - y diff --git a/tests/macros/tgensym.nim b/tests/macros/tgensym.nim index 3f4140ff4..b3aef0a2c 100644 --- a/tests/macros/tgensym.nim +++ b/tests/macros/tgensym.nim @@ -2,7 +2,7 @@ import rawsockets, asyncdispatch, macros var p = newDispatcher() var sock = newAsyncRawSocket() -proc convertReturns(node, retFutureSym: PNimrodNode): PNimrodNode {.compileTime.} = +proc convertReturns(node, retFutureSym: NimNode): NimNode {.compileTime.} = case node.kind of nnkReturnStmt: result = newCall(newIdentNode("complete"), retFutureSym, node[0]) @@ -19,19 +19,19 @@ macro async2(prc: stmt): stmt {.immediate.} = # -> var retFuture = newFuture[T]() var retFutureSym = newIdentNode("retFuture") #genSym(nskVar, "retFuture") outerProcBody.add( - newVarStmt(retFutureSym, + newVarStmt(retFutureSym, newCall( newNimNode(nnkBracketExpr).add( newIdentNode("newFuture"), prc[3][0][1])))) # Get type from return type of this proc. - # -> iterator nameIter(): PFutureBase {.closure.} = <proc_body> + # -> iterator nameIter(): FutureBase {.closure.} = <proc_body> # Changing this line to: newIdentNode($prc[0].ident & "Iter") # will make it work. var iteratorNameSym = genSym(nskIterator, $prc[0].ident & "Iter") #var iteratorNameSym = newIdentNode($prc[0].ident & "Iter") var procBody = prc[6].convertReturns(retFutureSym) - var closureIterator = newProc(iteratorNameSym, [newIdentNode("PFutureBase")], + var closureIterator = newProc(iteratorNameSym, [newIdentNode("FutureBase")], procBody, nnkIteratorDef) closureIterator[4] = newNimNode(nnkPragma).add(newIdentNode("closure")) outerProcBody.add(closureIterator) @@ -55,8 +55,8 @@ macro async2(prc: stmt): stmt {.immediate.} = result[6] = outerProcBody -proc readStuff(): PFuture[string] {.async2.} = - var fut = connect(sock, "irc.freenode.org", TPort(6667)) +proc readStuff(): Future[string] {.async2.} = + var fut = connect(sock, "irc.freenode.org", Port(6667)) yield fut var fut2 = recv(sock, 50) yield fut2 diff --git a/tests/macros/tgentemplates.nim b/tests/macros/tgentemplates.nim index a7727c597..764b94bc7 100644 --- a/tests/macros/tgentemplates.nim +++ b/tests/macros/tgentemplates.nim @@ -2,7 +2,7 @@ import parseutils, macros -proc parse_until_symbol(node: PNimrodNode, value: string, index: var int): bool {.compiletime.} = +proc parse_until_symbol(node: NimNode, value: string, index: var int): bool {.compiletime.} = var splitValue: string var read = value.parseUntil(splitValue, '$', index) @@ -15,7 +15,7 @@ proc parse_until_symbol(node: PNimrodNode, value: string, index: var int): bool if splitValue.len > 0: node.insert node.len, newCall("add", ident("result"), newStrLitNode(splitValue)) -proc parse_template(node: PNimrodNode, value: string) {.compiletime.} = +proc parse_template(node: NimNode, value: string) {.compiletime.} = var index = 0 while index < value.len and parse_until_symbol(node, value, index): discard diff --git a/tests/macros/tmacro1.nim b/tests/macros/tmacro1.nim index 3a67c2611..2dd5c31df 100644 --- a/tests/macros/tmacro1.nim +++ b/tests/macros/tmacro1.nim @@ -3,17 +3,17 @@ import macros from uri import `/` macro test*(a: stmt): stmt {.immediate.} = - var nodes: tuple[a, b: int] + var nodes: tuple[a, b: int] nodes.a = 4 nodes[1] = 45 - + type TTypeEx = object x, y: int case b: bool of false: nil of true: z: float - + var t: TTypeEx t.b = true t.z = 4.5 diff --git a/tests/macros/tmacro3.nim b/tests/macros/tmacro3.nim index 162212326..d7421ff7f 100644 --- a/tests/macros/tmacro3.nim +++ b/tests/macros/tmacro3.nim @@ -4,7 +4,7 @@ discard """ import macros -type +type TA = tuple[a: int] PA = ref TA @@ -19,7 +19,7 @@ test: macro test2*(a: stmt): stmt {.immediate.} = proc testproc(recurse: int) = echo "Thats weird" - var o : PNimrodNode = nil + var o : NimNode = nil echo " no its not!" o = newNimNode(nnkNone) if recurse > 0: diff --git a/tests/macros/tmacro4.nim b/tests/macros/tmacro4.nim index 10a23b159..a56369369 100644 --- a/tests/macros/tmacro4.nim +++ b/tests/macros/tmacro4.nim @@ -7,7 +7,7 @@ import macro test_macro*(n: stmt): stmt {.immediate.} = result = newNimNode(nnkStmtList) - var ass : PNimrodNode = newNimNode(nnkAsgn) + var ass : NimNode = newNimNode(nnkAsgn) add(ass, newIdentNode("str")) add(ass, newStrLitNode("after")) add(result, ass) diff --git a/tests/macros/tmacro5.nim b/tests/macros/tmacro5.nim index 9882ad90d..d7a4fe8c8 100644 --- a/tests/macros/tmacro5.nim +++ b/tests/macros/tmacro5.nim @@ -1,7 +1,7 @@ import macros,json -var decls{.compileTime.}: seq[PNimrodNode] = @[] -var impls{.compileTime.}: seq[PNimrodNode] = @[] +var decls{.compileTime.}: seq[NimNode] = @[] +var impls{.compileTime.}: seq[NimNode] = @[] macro importImpl_forward(name, returns): stmt {.immediate.} = result = newNimNode(nnkEmpty) @@ -38,7 +38,7 @@ macro importImpl_forward(name, returns): stmt {.immediate.} = decls.add res echo(repr(res)) -macro importImpl(name, returns: expr, body: stmt): stmt {.immediate.} = +macro importImpl(name, returns: expr, body: stmt): stmt {.immediate.} = #var res = getAST(importImpl_forward(name, returns)) discard getAST(importImpl_forward(name, returns)) var res = copyNimTree(decls[decls.high]) @@ -56,4 +56,4 @@ importImpl(Item, int): importImpl(Foo, int16): echo 77 -okayy \ No newline at end of file +okayy diff --git a/tests/macros/tmacros1.nim b/tests/macros/tmacros1.nim index 3c814ad6d..1a1073a44 100644 --- a/tests/macros/tmacros1.nim +++ b/tests/macros/tmacros1.nim @@ -15,10 +15,10 @@ macro outterMacro*(n: stmt): stmt {.immediate.} = expectKind(n, TNimrodNodeKind.nnkCall) if n.len != 3 or n[1].kind != TNimrodNodeKind.nnkIdent: error("Macro " & callNode.repr & - " requires the ident passed as parameter (eg: " & callNode.repr & + " requires the ident passed as parameter (eg: " & callNode.repr & "(the_name_you_want)): statements.") result = newNimNode(TNimrodNodeKind.nnkStmtList) - var ass : PNimrodNode = newNimNode(nnkAsgn) + var ass : NimNode = newNimNode(nnkAsgn) ass.add(newIdentNode(n[1].ident)) ass.add(newStrLitNode(innerProc(4))) result.add(ass) diff --git a/tests/macros/tnimnode_for_runtime.nim b/tests/macros/tnimnode_for_runtime.nim index 69c7aedd2..0520cd0dd 100644 --- a/tests/macros/tnimnode_for_runtime.nim +++ b/tests/macros/tnimnode_for_runtime.nim @@ -3,7 +3,7 @@ discard """ """ import macros -proc makeMacro: PNimrodNode = +proc makeMacro: NimNode = result = nil var p = makeMacro() diff --git a/tests/macros/tstringinterp.nim b/tests/macros/tstringinterp.nim index a500ed56e..bc79cdaba 100644 --- a/tests/macros/tstringinterp.nim +++ b/tests/macros/tstringinterp.nim @@ -19,7 +19,7 @@ template processInterpolations(e: expr) = macro formatStyleInterpolation(e: expr): expr = let e = callsite() - var + var formatString = "" arrayNode = newNimNode(nnkBracket) idx = 1 @@ -27,14 +27,14 @@ macro formatStyleInterpolation(e: expr): expr = proc addString(s: string) = formatString.add(s) - proc addExpr(e: PNimrodNode) = + proc addExpr(e: NimNode) = arrayNode.add(e) formatString.add("$" & $(idx)) inc idx proc addDollar() = formatString.add("$$") - + processInterpolations(e) result = parseExpr("\"x\" % [y]") @@ -43,11 +43,11 @@ macro formatStyleInterpolation(e: expr): expr = macro concatStyleInterpolation(e: expr): expr = let e = callsite() - var args: seq[PNimrodNode] + var args: seq[NimNode] newSeq(args, 0) proc addString(s: string) = args.add(newStrLitNode(s)) - proc addExpr(e: PNimrodNode) = args.add(e) + proc addExpr(e: NimNode) = args.add(e) proc addDollar() = args.add(newStrLitNode"$") processInterpolations(e) @@ -59,7 +59,7 @@ macro concatStyleInterpolation(e: expr): expr = proc sum(a, b, c: int): int = return (a + b + c) -var +var alice = "Alice" bob = "Bob" a = 10 diff --git a/tests/macros/tvarnimnode.nim b/tests/macros/tvarnimnode.nim index 73fcc16ea..ab0f66caa 100644 --- a/tests/macros/tvarnimnode.nim +++ b/tests/macros/tvarnimnode.nim @@ -6,7 +6,7 @@ discard """ import macros -proc test(f: var PNimrodNode) {.compileTime.} = +proc test(f: var NimNode) {.compileTime.} = f = newNimNode(nnkStmtList) f.add newCall(newIdentNode("echo"), newLit(10)) diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim index ae9dfb39f..3026cc4b9 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim @@ -18,9 +18,9 @@ proc `$`*[T](x: seq[T]): string = result.add($x[i]) result.add ']' -macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = +macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = result = newNimNode(nnkStmtList) - let + let typeName = quoted2ident(typeNameN) packetID = ^"p" streamID = ^"s" @@ -66,7 +66,7 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = readBody = newNimNode(nnkStmtList) lenNames = 0 for i in 0.. typeFields.len - 1: - let + let name = typeFields[i][0] dotName = packetID.dot(name) resName = newIdentNode(!"result").dot(name) @@ -91,11 +91,11 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = newNimNode(nnkDiscardStmt).und( newCall("readData", streamID, newNimNode(nnkAddr).und(resName), newCall("sizeof", resName)))) packBody.add( - newCall("writeData", streamID, newNimNode(nnkAddr).und(dotName), newCall("sizeof", dotName))) + newCall("writeData", streamID, newNimNode(nnkAddr).und(dotName), newCall("sizeof", dotName))) of "seq": ## let lenX = readInt16(s) newLenName() - let + let item = ^"item" ## item name in our iterators seqType = typeFields[i][1][1] ## type of seq readName = newIdentNode("read"& $seqType.ident) @@ -107,7 +107,7 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = readBody.add( ## result.name = @[] resName := ("@".prefix(newNimNode(nnkBracket))), newNimNode(nnkForStmt).und( ## for item in 1..len: - item, + item, infix(1.lit, "..", lenName), newNimNode(nnkStmtList).und( newCall( ## add(result.name, unpack[seqType](stream)) @@ -117,7 +117,7 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = newNimNode(nnkVarSection).und(newNimNode(nnkIdentDefs).und( lenName, ## var lenName = int16(len(p.name)) newIdentNode("int16"), - newCall("int16", newCall("len", dotName)))), + newCall("int16", newCall("len", dotName)))), newCall("writeData", streamID, newNimNode(nnkAddr).und(lenName), 2.lit), newNimNode(nnkForStmt).und( ## for item in 0..length - 1: pack(p.name[item], stream) item, @@ -143,8 +143,8 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = readBody.add(resName := newCall("read"& $typeFields[i][1].ident, streamID)) else: error("I dont know what to do with: "& treerepr(typeFields[i])) - - var + + var toStringFunc = newNimNode(nnkProcDef).und( newNimNode(nnkPostfix).und( ^"*", @@ -161,12 +161,12 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = emptyNode(), newNimNode(nnkStmtList).und(#[6] newNimNode(nnkAsgn).und( - ^"result", ## result = + ^"result", ## result = newNimNode(nnkCall).und(#[6][0][1] ^"format", ## format emptyNode())))) ## "[TypeName $1 $2]" formatStr = "["& $typeName.ident - + const emptyFields = {nnkEmpty, nnkNilLit} var objFields = newNimNode(nnkRecList) for i in 0.. < len(typeFields): @@ -186,10 +186,10 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = prefix("$", packetID.dot(fname))) formatStr.add " $" formatStr.add($(i + 1)) - + formatStr.add ']' toStringFunc[6][0][1][1] = formatStr.lit() - + result.add( newNimNode(nnkTypeSection).und( newNimNode(nnkTypeDef).und( @@ -206,15 +206,15 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = when defined(GenPacketShowOutput): echo(repr(result)) -proc `->`(a: string, b: string): PNimrodNode {.compileTime.} = +proc `->`(a: string, b: string): NimNode {.compileTime.} = result = newNimNode(nnkIdentDefs).und(^a, ^b, newNimNode(nnkEmpty)) -proc `->`(a: string, b: PNimrodNode): PNimrodNode {.compileTime.} = +proc `->`(a: string, b: NimNode): NimNode {.compileTime.} = result = newNimNode(nnkIdentDefs).und(^a, b, newNimNode(nnkEmpty)) -proc `->`(a, b: PNimrodNode): PNimrodNode {.compileTime.} = +proc `->`(a, b: NimNode): NimNode {.compileTime.} = a[2] = b result = a -proc newProc*(name: string, params: varargs[PNimrodNode], resultType: PNimrodNode): PNimrodNode {.compileTime.} = +proc newProc*(name: string, params: varargs[NimNode], resultType: NimNode): NimNode {.compileTime.} = result = newNimNode(nnkProcDef).und( ^name, emptyNode(), @@ -227,7 +227,7 @@ proc newProc*(name: string, params: varargs[PNimrodNode], resultType: PNimrodNod macro forwardPacket*(typeName: expr, underlyingType: typedesc): stmt {.immediate.} = result = newNimNode(nnkStmtList).und( newProc( - "read"& $typeName.ident, + "read"& $typeName.ident, ["s" -> "PStream" -> newNimNode(nnkNilLit)], typeName), newProc( @@ -258,21 +258,21 @@ when isMainModule: A = 0'i8, B, C forwardPacket(SomeEnum, int8) - - + + defPacket(Foo, tuple[x: array[0..4, int8]]) var f = newFoo([4'i8, 3'i8, 2'i8, 1'i8, 0'i8]) var s2 = newStringStream("") f.pack(s2) assert s2.data == "\4\3\2\1\0" - + var s = newStringStream() s.flushImpl = proc(s: PStream) = var z = PStringStream(s) z.setPosition(0) z.data.setLen(0) - - + + s.setPosition(0) s.data.setLen(0) var o = B @@ -283,7 +283,7 @@ when isMainModule: o.pack(s) assert s.data == "\1\0\2" s.flush - + defPacket(Y, tuple[z: int8]) proc `$`(z: Y): string = result = "Y("& $z.z &")" defPacket(TestPkt, tuple[x: seq[Y]]) @@ -292,4 +292,4 @@ when isMainModule: for itm in test.x: echo(itm) test.pack(s) - echo(repr(s.data)) \ No newline at end of file + echo(repr(s.data)) diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim index 4f2fb1ea3..7cfd67c49 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim @@ -9,9 +9,9 @@ template defPacketImports*(): stmt {.immediate, dirty.} = import macros, macro_dsl, estreams from strutils import format -macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = +macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = result = newNimNode(nnkStmtList) - let + let typeName = quoted2ident(typeNameN) packetID = ^"p" streamID = ^"s" @@ -57,7 +57,7 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = readBody = newNimNode(nnkStmtList) lenNames = 0 for i in 0.. typeFields.len - 1: - let + let name = typeFields[i][0] dotName = packetID.dot(name) resName = newIdentNode(!"result").dot(name) @@ -67,7 +67,7 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = of "seq": ## let lenX = readInt16(s) newLenName() - let + let item = ^"item" ## item name in our iterators seqType = typeFields[i][1][1] ## type of seq readName = newIdentNode("read"& $seqType.ident) @@ -79,7 +79,7 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = readBody.add( ## result.name = @[] resName := ("@".prefix(newNimNode(nnkBracket))), newNimNode(nnkForStmt).und( ## for item in 1..len: - item, + item, infix(1.lit, "..", lenName), newNimNode(nnkStmtList).und( newCall( ## add(result.name, unpack[seqType](stream)) @@ -89,7 +89,7 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = newNimNode(nnkVarSection).und(newNimNode(nnkIdentDefs).und( lenName, ## var lenName = int16(len(p.name)) newIdentNode("int16"), - newCall("int16", newCall("len", dotName)))), + newCall("int16", newCall("len", dotName)))), newCall("writeBE", streamID, lenName), newNimNode(nnkForStmt).und( ## for item in 0..length - 1: pack(p.name[item], stream) item, @@ -115,8 +115,8 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = readBody.add(resName := newCall("read"& $typeFields[i][1].ident, streamID)) else: error("I dont know what to do with: "& treerepr(typeFields[i])) - - var + + var toStringFunc = newNimNode(nnkProcDef).und( newNimNode(nnkPostfix).und( ^"*", @@ -133,12 +133,12 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = emptyNode(), newNimNode(nnkStmtList).und(#[6] newNimNode(nnkAsgn).und( - ^"result", ## result = + ^"result", ## result = newNimNode(nnkCall).und(#[6][0][1] ^"format", ## format emptyNode())))) ## "[TypeName $1 $2]" formatStr = "["& $typeName.ident - + const emptyFields = {nnkEmpty, nnkNilLit} var objFields = newNimNode(nnkRecList) for i in 0.. < len(typeFields): @@ -158,10 +158,10 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = prefix("$", packetID.dot(fname))) formatStr.add " $" formatStr.add($(i + 1)) - + formatStr.add ']' toStringFunc[6][0][1][1] = formatStr.lit() - + result.add( newNimNode(nnkTypeSection).und( newNimNode(nnkTypeDef).und( @@ -178,7 +178,7 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = when defined(GenPacketShowOutput): echo(repr(result)) -proc newProc*(name: PNimrodNode; params: varargs[PNimrodNode]; resultType: PNimrodNode): PNimrodNode {.compileTime.} = +proc newProc*(name: NimNode; params: varargs[NimNode]; resultType: NimNode): NimNode {.compileTime.} = result = newNimNode(nnkProcDef).und( name, emptyNode(), @@ -189,15 +189,15 @@ proc newProc*(name: PNimrodNode; params: varargs[PNimrodNode]; resultType: PNimr newNimNode(nnkStmtList)) result[3].add(params) -proc body*(procNode: PNimrodNode): PNimrodNode {.compileTime.} = +proc body*(procNode: NimNode): NimNode {.compileTime.} = assert procNode.kind == nnkProcDef and procNode[6].kind == nnkStmtList result = procNode[6] -proc iddefs*(a, b: string; c: PNimrodNode): PNimrodNode {.compileTime.} = +proc iddefs*(a, b: string; c: NimNode): NimNode {.compileTime.} = result = newNimNode(nnkIdentDefs).und(^a, ^b, c) -proc iddefs*(a: string; b: PNimrodNode): PNimrodNode {.compileTime.} = +proc iddefs*(a: string; b: NimNode): NimNode {.compileTime.} = result = newNimNode(nnkIdentDefs).und(^a, b, emptyNode()) -proc varTy*(a: PNimrodNode): PNimrodNode {.compileTime.} = +proc varTy*(a: NimNode): NimNode {.compileTime.} = result = newNimNode(nnkVarTy).und(a) macro forwardPacket*(typeName: expr, underlyingType: expr): stmt {.immediate.} = @@ -206,7 +206,7 @@ macro forwardPacket*(typeName: expr, underlyingType: expr): stmt {.immediate.} = streamID = ^"s" result = newNimNode(nnkStmtList).und( newProc( - (^("read"& $typeName.ident)).postfix("*"), + (^("read"& $typeName.ident)).postfix("*"), [ iddefs("s", "PBuffer", newNimNode(nnkNilLit)) ], typeName), newProc( @@ -218,7 +218,7 @@ macro forwardPacket*(typeName: expr, underlyingType: expr): stmt {.immediate.} = readBody = result[0][6] packBody = result[1][6] resName = ^"result" - + case underlyingType.kind of nnkBracketExpr: case $underlyingType[0].ident @@ -250,21 +250,21 @@ when isMainModule: A = 0'i8, B, C forwardPacket(SomeEnum, int8) - - + + defPacket(Foo, tuple[x: array[0..4, int8]]) var f = newFoo([4'i8, 3'i8, 2'i8, 1'i8, 0'i8]) var s2 = newStringStream("") f.pack(s2) assert s2.data == "\4\3\2\1\0" - + var s = newStringStream() s.flushImpl = proc(s: PStream) = var z = PStringStream(s) z.setPosition(0) z.data.setLen(0) - - + + s.setPosition(0) s.data.setLen(0) var o = B @@ -275,7 +275,7 @@ when isMainModule: o.pack(s) assert s.data == "\1\0\2" s.flush - + defPacket(Y, tuple[z: int8]) proc `$`(z: Y): string = result = "Y("& $z.z &")" defPacket(TestPkt, tuple[x: seq[Y]]) diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim index c7b577b3d..d3a0c701d 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim @@ -1,42 +1,42 @@ import macros {.deadCodeElim: on.} #Inline macro.add() to allow for easier nesting -proc und*(a: PNimrodNode; b: PNimrodNode): PNimrodNode {.compileTime.} = +proc und*(a: NimNode; b: NimNode): NimNode {.compileTime.} = a.add(b) result = a -proc und*(a: PNimrodNode; b: varargs[PNimrodNode]): PNimrodNode {.compileTime.} = +proc und*(a: NimNode; b: varargs[NimNode]): NimNode {.compileTime.} = a.add(b) result = a -proc `^`*(a: string): PNimrodNode {.compileTime.} = +proc `^`*(a: string): NimNode {.compileTime.} = ## new ident node result = newIdentNode(!a) -proc `[]`*(a, b: PNimrodNode): PNimrodNode {.compileTime.} = +proc `[]`*(a, b: NimNode): NimNode {.compileTime.} = ## new bracket expression: node[node] not to be confused with node[indx] result = newNimNode(nnkBracketExpr).und(a, b) -proc `:=`*(left, right: PNimrodNode): PNimrodNode {.compileTime.} = +proc `:=`*(left, right: NimNode): NimNode {.compileTime.} = ## new Asgn node: left = right result = newNimNode(nnkAsgn).und(left, right) -proc lit*(a: string): PNimrodNode {.compileTime.} = +proc lit*(a: string): NimNode {.compileTime.} = result = newStrLitNode(a) -proc lit*(a: int): PNimrodNode {.compileTime.} = +proc lit*(a: int): NimNode {.compileTime.} = result = newIntLitNode(a) -proc lit*(a: float): PNimrodNode {.compileTime.} = +proc lit*(a: float): NimNode {.compileTime.} = result = newFloatLitNode(a) -proc lit*(a: char): PNimrodNode {.compileTime.} = +proc lit*(a: char): NimNode {.compileTime.} = result = newNimNode(nnkCharLit) result.intval = a.ord -proc emptyNode*(): PNimrodNode {.compileTime.} = +proc emptyNode*(): NimNode {.compileTime.} = result = newNimNode(nnkEmpty) -proc dot*(left, right: PNimrodNode): PNimrodNode {.compileTime.} = +proc dot*(left, right: NimNode): NimNode {.compileTime.} = result = newNimNode(nnkDotExpr).und(left, right) -proc prefix*(a: string, b: PNimrodNode): PNimrodNode {.compileTime.} = +proc prefix*(a: string, b: NimNode): NimNode {.compileTime.} = result = newNimNode(nnkPrefix).und(newIdentNode(!a), b) -proc quoted2ident*(a: PNimrodNode): PNimrodNode {.compileTime.} = +proc quoted2ident*(a: NimNode): NimNode {.compileTime.} = if a.kind != nnkAccQuoted: return a var pname = "" diff --git a/tests/manyloc/named_argument_bug/tri_engine/gfx/color.nim b/tests/manyloc/named_argument_bug/tri_engine/gfx/color.nim index 8e47c1f2f..cdd5aaf03 100644 --- a/tests/manyloc/named_argument_bug/tri_engine/gfx/color.nim +++ b/tests/manyloc/named_argument_bug/tri_engine/gfx/color.nim @@ -5,7 +5,8 @@ import from strutils import formatFloat, TFloatFormat, - `%` + `%`, + ffDecimal from unsigned import `shr`, diff --git a/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/gl.nim b/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/gl.nim index e731969c1..22d36ef4d 100644 --- a/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/gl.nim +++ b/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/gl.nim @@ -54,7 +54,7 @@ else: glRealType* = cGLfloat proc setUniformV4*[T](loc: GLint, vecs: var openarray[TV4[T]]) = - glUniform4fv(loc, vecs.len.GLsizei, cast[PGLfloat](vecs[0].addr)) + glUniform4fv(loc, vecs.len.GLsizei, cast[ptr GLfloat](vecs[0].addr)) proc setUniformV4*[T](loc: GLint, vec: TV4[T]) = var vecs = [vec] diff --git a/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/primitive.nim b/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/primitive.nim index c67748967..8c26c04eb 100644 --- a/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/primitive.nim +++ b/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/primitive.nim @@ -16,7 +16,7 @@ type i* : GLuint size* : GLint stride* : GLsizei - offset* : PGLvoid + offset* : GLvoid TVertMode* = enum vmTriStrip = GLtriangleStrip, vmTriFan = GLtriangleFan @@ -44,7 +44,7 @@ proc newVertQuad*(min, minRight, maxLeft, max: TV2[TR]): seq[TVert] = proc newVert*(rect: rect.TRect): seq[TVert] = newVertQuad(rect.min, newV2(rect.max.x, rect.min.y), newV2(rect.min.x, rect.max.y), rect.max) -proc newVertAttrib(i: GLuint, size: GLint, stride: GLsizei, offset: PGLvoid): TVertAttrib = +proc newVertAttrib(i: GLuint, size: GLint, stride: GLsizei, offset: GLvoid): TVertAttrib = TVertAttrib(i: i, size: size, stride: stride, offset: offset) proc genBuf*[T](vboTarget, objUsage: GLenum, data: var openarray[T]): GLuint = @@ -90,7 +90,7 @@ proc disableVertAttribArrs*() = proc setVertAttribPointers*() = let vertSize {.global.} = TVert.sizeof.GLint ?glVertexAttribPointer(0, 2, glRealType, false, vertSize, nil) - ?glVertexAttribPointer(1, 2, glRealType, false, vertSize, cast[PGLvoid](TR.sizeof * 2)) + ?glVertexAttribPointer(1, 2, glRealType, false, vertSize, cast[GLvoid](TR.sizeof * 2)) proc updVerts*(o: PPrimitive, start, `end`: int, f: proc(i: int, vert: var TVert)) = assert start <= `end` @@ -105,7 +105,7 @@ proc updVerts*(o: PPrimitive, start, `end`: int, f: proc(i: int, vert: var TVert ?glBufferSubData(GLarrayBuffer, byteOffset.GLintptr, # Offset. Is this right? byteLen.GLsizeiptr, # Size. - cast[PGLvoid](cast[int](o.verts[0].addr) + byteOffset)) + cast[GLvoid](cast[int](o.verts[0].addr) + byteOffset)) proc updAllVerts(o: PPrimitive, f: proc(i: int, vert: var TVert)) = for i in 0 .. <o.verts.len: diff --git a/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/shader.nim b/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/shader.nim index 5972aa4fb..89bb76064 100644 --- a/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/shader.nim +++ b/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/shader.nim @@ -25,7 +25,7 @@ proc setSrc*(shader: TShader, src: string) = ?glShaderSource(shader.id, 1, cast[cstringarray](s.addr), nil) proc newShader*(id: GL_handle): TShader = - if id != 0 and not (?glIsShader(id)).bool: + if id.int != 0 and not (?glIsShader(id)).bool: raise newException(E_GL, "Invalid shader ID: " & $id) result.id = id @@ -33,7 +33,7 @@ proc newShader*(id: GL_handle): TShader = proc shaderInfoLog*(o: TShader): string = var log {.global.}: array[0..1024, char] var logLen: GLsizei - ?glGetShaderInfoLog(o.id, log.len.GLsizei, logLen, cast[PGLchar](log.addr)) + ?glGetShaderInfoLog(o.id.GLuint, log.len.GLsizei, addr logLen, cast[cstring](log.addr)) cast[string](log.addr).substr(0, logLen) proc compile*(shader: TShader, path="") = @@ -67,7 +67,7 @@ proc attach*(o: TProgram, shader: TShader) = proc infoLog*(o: TProgram): string = var log {.global.}: array[0..1024, char] var logLen: GLsizei - ?glGetProgramInfoLog(o.id, log.len.GLsizei, logLen, cast[PGLchar](log.addr)) + ?glGetProgramInfoLog(o.id.GLuint, log.len.GLsizei, addr logLen, cast[cstring](log.addr)) cast[string](log.addr).substr(0, logLen) proc link*(o: TProgram) = @@ -86,11 +86,11 @@ proc validate*(o: TProgram) = proc newProgram*(shaders: seq[TShader]): TProgram = result.id = ?glCreateProgram() - if result.id == 0: + if result.id.int == 0: return for shader in shaders: - if shader.id == 0: + if shader.id.int == 0: return ?result.attach(shader) diff --git a/tests/misc/tinc.nim b/tests/misc/tinc.nim index 8038a2a01..b74f85591 100644 --- a/tests/misc/tinc.nim +++ b/tests/misc/tinc.nim @@ -1,7 +1,7 @@ discard """ file: "tinc.nim" line: 8 - errormsg: "for a \'var\' type a variable needs to be passed" + errormsg: "type mismatch: got (int)" """ var x = 0 diff --git a/tests/misc/tinout.nim b/tests/misc/tinout.nim index 034c496f5..4e5908428 100644 --- a/tests/misc/tinout.nim +++ b/tests/misc/tinout.nim @@ -1,7 +1,7 @@ discard """ file: "tinout.nim" line: 12 - errormsg: "for a \'var\' type a variable needs to be passed" + errormsg: "type mismatch: got (int literal(3))" """ # Test in out checking for parameters diff --git a/tests/notnil/tnotnil4.nim b/tests/notnil/tnotnil4.nim index 23968ee48..2fa888357 100644 --- a/tests/notnil/tnotnil4.nim +++ b/tests/notnil/tnotnil4.nim @@ -11,4 +11,10 @@ proc doit() = if x[0] != nil: check(x[0]) -doit() \ No newline at end of file +doit() + +# bug #2352 + +proc p(x: proc() {.noconv.} not nil) = discard +p(proc() {.noconv.} = discard) +# Error: cannot prove 'proc () {.noconv.} = discard ' is not nil diff --git a/tests/objvariant/tadrdisc.nim b/tests/objvariant/tadrdisc.nim index 0e0324562..1afe7d04f 100644 --- a/tests/objvariant/tadrdisc.nim +++ b/tests/objvariant/tadrdisc.nim @@ -1,7 +1,7 @@ discard """ file: "tadrdisc.nim" line: 20 - errormsg: "for a \'var\' type a variable needs to be passed" + errormsg: "type mismatch: got (TKind)" """ # Test that the address of a dicriminants cannot be taken @@ -12,12 +12,9 @@ type of ka: x, y: int of kb: a, b: string of kc: c, d: float - -proc setKind(k: var TKind) = - k = kc - -var a: TA -setKind(a.k) #ERROR_MSG for a 'var' type a variable needs to be passed - +proc setKind(k: var TKind) = + k = kc +var a: TA +setKind(a.k) diff --git a/tests/overload/tspec.nim b/tests/overload/tspec.nim new file mode 100644 index 000000000..685df503a --- /dev/null +++ b/tests/overload/tspec.nim @@ -0,0 +1,81 @@ +discard """ + output: '''not a var +not a var +a var +B +int +T +int16 +T +ref T +123 +2 +1 +@[123, 2, 1]''' +""" + +# Things that's even in the spec now! + +proc byvar(x: var int) = echo "a var" +proc byvar(x: int) = echo "not a var" +byvar(89) + +let letSym = 0 +var varSym = 13 + +byvar(letSym) +byvar(varSym) + +type + A = object of RootObj + B = object of A + C = object of B + +proc p(obj: A) = + echo "A" + +proc p(obj: B) = + echo "B" + +var c = C() +# not ambiguous, calls 'B', not 'A' since B is a subtype of A +# but not vice versa: +p(c) + +proc pp(obj: A, obj2: B) = echo "A B" +proc pp(obj: B, obj2: A) = echo "B A" + +# but this is ambiguous: +#pp(c, c) + +proc takesInt(x: int) = echo "int" +proc takesInt[T](x: T) = echo "T" +proc takesInt(x: int16) = echo "int16" + +takesInt(4) # "int" +var x: int32 +takesInt(x) # "T" +var y: int16 +takesInt(y) # "int16" +var z: range[0..4] = 0 +takesInt(z) # "T" + +proc gen[T](x: ref ref T) = echo "ref ref T" +proc gen[T](x: ref T) = echo "ref T" +proc gen[T](x: T) = echo "T" + +var ri: ref int +gen(ri) # "ref T" + + +template rem(x: expr) = discard +#proc rem[T](x: T) = discard + +rem unresolvedExpression(undeclaredIdentifier) + + +proc takeV[T](a: varargs[T]) = + for x in a: echo x + +takeV([123, 2, 1]) # takeV's T is "int", not "array of int" +echo(@[123, 2, 1]) diff --git a/tests/parallel/tarray_of_channels.nim b/tests/parallel/tarray_of_channels.nim new file mode 100644 index 000000000..11b523401 --- /dev/null +++ b/tests/parallel/tarray_of_channels.nim @@ -0,0 +1,26 @@ +# bug #2257 +import threadpool + +type StringChannel = TChannel[string] +var channels: array[1..3, StringChannel] + +type + MyObject[T] = object + x: T + +var global: MyObject[string] +var globalB: MyObject[float] + +proc consumer(ix : int) {.thread.} = + echo channels[ix].recv() ###### not GC-safe: 'channels' + echo globalB + +proc main = + for ix in 1..3: channels[ix].open() + for ix in 1..3: spawn consumer(ix) + for ix in 1..3: channels[ix].send("test") + sync() + for ix in 1..3: channels[ix].close() + +when isMainModule: + main() diff --git a/tests/parallel/tdont_be_stupid.nim b/tests/parallel/tdont_be_stupid.nim new file mode 100644 index 000000000..a7e82466a --- /dev/null +++ b/tests/parallel/tdont_be_stupid.nim @@ -0,0 +1,15 @@ + +import threadpool, os + +proc single(time: int) = + sleep time + echo time + +proc sleepsort(nums: openArray[int]) = + parallel: + var i = 0 + while i <= len(nums) + -1: + spawn single(nums[i]) + i += 1 + +sleepsort([50,3,40,25]) diff --git a/tests/parallel/tgc_unsafe.nim b/tests/parallel/tgc_unsafe.nim new file mode 100644 index 000000000..6548bbec8 --- /dev/null +++ b/tests/parallel/tgc_unsafe.nim @@ -0,0 +1,32 @@ +discard """ + errormsg: "'consumer' is not GC-safe" + line: 19 +""" + +# bug #2257 +import threadpool + +type StringChannel = TChannel[string] +var channels: array[1..3, StringChannel] + +type + MyObject[T] = object + x: T + +var global: MyObject[string] +var globalB: MyObject[float] + +proc consumer(ix : int) {.thread.} = + echo channels[ix].recv() ###### not GC-safe: 'channels' + echo global + echo globalB + +proc main = + for ix in 1..3: channels[ix].open() + for ix in 1..3: spawn consumer(ix) + for ix in 1..3: channels[ix].send("test") + sync() + for ix in 1..3: channels[ix].close() + +when isMainModule: + main() diff --git a/tests/showoff/tdrdobbs_examples.nim b/tests/showoff/tdrdobbs_examples.nim index 13a685950..78f711325 100644 --- a/tests/showoff/tdrdobbs_examples.nim +++ b/tests/showoff/tdrdobbs_examples.nim @@ -13,7 +13,7 @@ var g = 70 ++g g ++ 7 g.`++`(10, 20) -echo g +echo g #let lv = stdin.readline @@ -56,7 +56,7 @@ type fkLit, ## element is a literal like 0.1 fkAdd, ## element is an addition operation fkMul, ## element is a multiplication operation - fkExp ## element is an exponentiation operation + fkExp ## element is an exponentiation operation type Formula = ref object @@ -78,16 +78,16 @@ proc evaluate(n: Formula, varToVal: proc (name: string): float): float = echo evaluate(Formula(kind: fkLit, value: 0.4), nil) proc isPolyTerm(n: Formula): bool = - n.kind == fkMul and n.left.kind == fkLit and (let e = n.right; + n.kind == fkMul and n.left.kind == fkLit and (let e = n.right; e.kind == fkExp and e.left.kind == fkVar and e.right.kind == fkLit) proc isPolynomial(n: Formula): bool = - isPolyTerm(n) or + isPolyTerm(n) or (n.kind == fkAdd and isPolynomial(n.left) and isPolynomial(n.right)) let myFormula = Formula(kind: fkMul, left: Formula(kind: fkLit, value: 2.0), - right: Formula(kind: fkExp, + right: Formula(kind: fkExp, left: Formula(kind: fkVar, name: "x"), right: Formula(kind: fkLit, value: 5.0))) @@ -104,7 +104,7 @@ proc pat2kind(pattern: string): FormulaKind = import macros -proc matchAgainst(n, pattern: PNimrodNode): PNimrodNode {.compileTime.} = +proc matchAgainst(n, pattern: NimNode): NimNode {.compileTime.} = template `@`(current, field: expr): expr = newDotExpr(current, newIdentNode(astToStr(field))) diff --git a/tests/template/t_otemplates.nim b/tests/template/t_otemplates.nim index 1a9075d20..db535d818 100644 --- a/tests/template/t_otemplates.nim +++ b/tests/template/t_otemplates.nim @@ -18,7 +18,7 @@ const identChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'} # Procedure Declarations -proc parse_template(node: PNimrodNode, value: string) {.compiletime.} +proc parse_template(node: NimNode, value: string) {.compiletime.} # Procedure Definitions @@ -166,7 +166,7 @@ iterator parse_compound_statements(value, identifier: string, index: int): strin get_next_ident(["try", "$except", "$finally"]) -proc parse_complex_stmt(value, identifier: string, index: var int): PNimrodNode {.compiletime.} = +proc parse_complex_stmt(value, identifier: string, index: var int): NimNode {.compiletime.} = ## Parses if/when/try /elif /else /except /finally statements # Build up complex statement string @@ -218,7 +218,7 @@ proc parse_complex_stmt(value, identifier: string, index: var int): PNimrodNode inc(resultIndex) -proc parse_simple_statement(value: string, index: var int): PNimrodNode {.compiletime.} = +proc parse_simple_statement(value: string, index: var int): NimNode {.compiletime.} = ## Parses for/while # Detect indentation @@ -252,7 +252,7 @@ proc parse_simple_statement(value: string, index: var int): PNimrodNode {.compil inc(index, value.parse_thru_eol(index)) -proc parse_until_symbol(node: PNimrodNode, value: string, index: var int): bool {.compiletime.} = +proc parse_until_symbol(node: NimNode, value: string, index: var int): bool {.compiletime.} = ## Parses a string until a $ symbol is encountered, if ## two $$'s are encountered in a row, a split will happen ## removing one of the $'s from the resulting output @@ -311,7 +311,7 @@ proc parse_until_symbol(node: PNimrodNode, value: string, index: var int): bool node.insert insertionPoint, newCall("add", ident("result"), newStrLitNode(splitValue)) -proc parse_template(node: PNimrodNode, value: string) = +proc parse_template(node: NimNode, value: string) = ## Parses through entire template, outputing valid ## Nim code into the input `node` AST. var index = 0 diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim index c293be7e8..cb3649a38 100644 --- a/tests/testament/categories.nim +++ b/tests/testament/categories.nim @@ -215,7 +215,7 @@ proc manyLoc(r: var TResults, cat: Category, options: string) = for kind, dir in os.walkDir("tests/manyloc"): if kind == pcDir: let mainfile = findMainFile(dir) - if mainfile != ".nim": + if mainfile != "": testNoSpec r, makeTest(mainfile, options, cat) proc compileExample(r: var TResults, pattern, options: string, cat: Category) = diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim index 7cf902704..4c1173fe3 100644 --- a/tests/testament/tester.nim +++ b/tests/testament/tester.nim @@ -146,7 +146,6 @@ proc codegenCheck(test: TTest, check: string, given: var TSpec) = try: let (path, name, ext2) = test.name.splitFile let genFile = generatedFile(path, name, test.target) - echo genFile let contents = readFile(genFile).string if check[0] == '\\': # little hack to get 'match' support: diff --git a/tests/usingstmt/tusingstatement.nim b/tests/usingstmt/tusingstatement.nim index b58478d74..0d76b2423 100644 --- a/tests/usingstmt/tusingstatement.nim +++ b/tests/usingstmt/tusingstatement.nim @@ -3,13 +3,13 @@ discard """ output: "Using test.Closing test." """ -import +import macros # This macro mimics the using statement from C# # # It's kept only as a test for the macro system -# Nim's destructors offer a mechanism for automatic +# Nim's destructors offer a mechanism for automatic # disposal of resources. # macro autoClose(e: expr): stmt {.immediate.} = @@ -20,19 +20,19 @@ macro autoClose(e: expr): stmt {.immediate.} = var args = e var body = e[2] - - var - variables : seq[PNimrodNode] - closingCalls : seq[PNimrodNode] + + var + variables : seq[NimNode] + closingCalls : seq[NimNode] newSeq(variables, 0) newSeq(closingCalls, 0) - + for i in countup(1, args.len-2): if args[i].kind == nnkExprEqExpr: var varName = args[i][0] var varValue = args[i][1] - + var varAssignment = newNimNode(nnkIdentDefs) varAssignment.add(varName) varAssignment.add(newNimNode(nnkEmpty)) # empty means no type @@ -43,7 +43,7 @@ macro autoClose(e: expr): stmt {.immediate.} = else: error "Using statement: Unexpected expression. Got " & $args[i].kind & " instead of assignment." - + var varSection = newNimNode(nnkVarSection) varSection.add(variables) @@ -67,10 +67,10 @@ macro autoClose(e: expr): stmt {.immediate.} = targetAst[0][1][0] = varSection targetAst[0][1][1][0] = body targetAst[0][1][1][1][0] = finallyBlock - + result = targetAst -type +type TResource* = object field*: string diff --git a/tests/vm/tstringnil.nim b/tests/vm/tstringnil.nim index 61ce60ee5..bb546b698 100644 --- a/tests/vm/tstringnil.nim +++ b/tests/vm/tstringnil.nim @@ -8,9 +8,9 @@ type suiteDesc: string testName: string testDesc: string - testBlock: PNimrodNode + testBlock: NimNode -proc buildSuiteContents(suiteName, suiteDesc, suiteBloc: PNimrodNode): tuple[tests: seq[SuiteTest]] {.compileTime.} = +proc buildSuiteContents(suiteName, suiteDesc, suiteBloc: NimNode): tuple[tests: seq[SuiteTest]] {.compileTime.} = var tests:seq[SuiteTest] = @[] @@ -40,7 +40,7 @@ proc buildSuiteContents(suiteName, suiteDesc, suiteBloc: PNimrodNode): tuple[tes discard return (tests: tests) - + macro suite(suiteName, suiteDesc: expr, suiteBloc: stmt): stmt {.immediate.} = let contents = buildSuiteContents(suiteName, suiteDesc, suiteBloc) diff --git a/todo.txt b/todo.txt index b77c276b7..e8a393a47 100644 --- a/todo.txt +++ b/todo.txt @@ -5,6 +5,7 @@ version 0.10.4 - make 'nil' work for 'add' and 'len' - disallow negative indexing - improve the parser; deal with echo $foo gotcha +- add "all threads are blocked" detection to 'spawn' version 1.0 diff --git a/web/news.txt b/web/news.txt index 7cf1ae28f..a76f0e8bc 100644 --- a/web/news.txt +++ b/web/news.txt @@ -11,8 +11,21 @@ News ----------------------------------------- - Parameter names are finally properly ``gensym``'ed. This can break - templates though that used to rely on the fact that they are not. However - we found none such beast in the wild. (Bug #1915.) + templates though that used to rely on the fact that they are not. + (Bug #1915.) This means this doesn't compile anymore: + + .. code-block:: nim + + template doIt(body: stmt) {.immediate.} = + # this used to inject the 'str' parameter: + proc res(str: string) = + body + + doIt: + echo str # Error: undeclared identifier: 'str' + + Declare the ``doIt`` template as ``immediate, dirty`` to get the old + behaviour. - Tuple field names are not ignored anymore, this caused too many problems in practice so now the behaviour as it was for version 0.9.6: If field names exist for the tuple type, they are checked. |