diff options
author | Andrii Riabushenko <cdome@bk.ru> | 2018-10-24 22:16:25 +0100 |
---|---|---|
committer | Andrii Riabushenko <cdome@bk.ru> | 2018-10-24 22:16:25 +0100 |
commit | 4c53d4567458cf367e607316fb90df1310026cdd (patch) | |
tree | a76244cd2e69d39a3e3a4c33b4e80c1d64a15565 /compiler | |
parent | a54e0703a9de7df522c9f50aa3ef70f30405eddf (diff) | |
parent | f5a2c6e19d8c789ad1211264bac89bce7e569e54 (diff) | |
download | Nim-4c53d4567458cf367e607316fb90df1310026cdd.tar.gz |
Merge branch 'devel' into vm_float_casts
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgstmts.nim | 83 | ||||
-rw-r--r-- | compiler/condsyms.nim | 1 | ||||
-rw-r--r-- | compiler/destroyer.nim | 11 | ||||
-rw-r--r-- | compiler/lexer.nim | 12 | ||||
-rw-r--r-- | compiler/semtypes.nim | 16 |
5 files changed, 86 insertions, 37 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 6c2e8ebc8..907b56dac 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -400,6 +400,16 @@ proc genGotoForCase(p: BProc; caseStmt: PNode) = genStmts(p, it.lastSon) endBlock(p) + +iterator fieldValuePairs(n: PNode): tuple[memberSym, valueSym: PNode] = + assert(n.kind in {nkLetSection, nkVarSection}) + for identDefs in n: + if identDefs.kind == nkIdentDefs: + let valueSym = identDefs[^1] + for i in 0 ..< identDefs.len-2: + let memberSym = identDefs[i] + yield((memberSym: memberSym, valueSym: valueSym)) + proc genComputedGoto(p: BProc; n: PNode) = # first pass: Generate array of computed labels: var casePos = -1 @@ -429,22 +439,12 @@ proc genComputedGoto(p: BProc; n: PNode) = let tmp = "TMP$1_" % [id.rope] var gotoArray = "static void* $#[$#] = {" % [tmp, arraySize.rope] for i in 1..arraySize-1: - gotoArray.addf("&&TMP$#_, ", [(id+i).rope]) - gotoArray.addf("&&TMP$#_};$n", [(id+arraySize).rope]) + gotoArray.addf("&&TMP$#_, ", [rope(id+i)]) + gotoArray.addf("&&TMP$#_};$n", [rope(id+arraySize)]) line(p, cpsLocals, gotoArray) - 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] - - p.blocks[topBlock].sections[cpsStmts] = nil - for j in 0 .. casePos-1: genStmts(p, n.sons[j]) - let tailA = p.blocks[topBlock].sections[cpsStmts] - - p.blocks[topBlock].sections[cpsStmts] = oldBody & tailA + for j in 0 ..< casePos: + genStmts(p, n.sons[j]) let caseStmt = n.sons[casePos] var a: TLoc @@ -459,19 +459,40 @@ proc genComputedGoto(p: BProc; n: PNode) = if it.sons[j].kind == nkRange: localError(p.config, it.info, "range notation not available for computed goto") return + let val = getOrdValue(it.sons[j]) lineF(p, cpsStmts, "TMP$#_:$n", [intLiteral(val+id+1)]) + genStmts(p, it.lastSon) - #for j in casePos+1 ..< n.len: genStmts(p, n.sons[j]) # tailB - #for j in 0 .. casePos-1: genStmts(p, n.sons[j]) # tailA - add(p.s(cpsStmts), tailB) - add(p.s(cpsStmts), tailA) + + for j in casePos+1 ..< n.sons.len: + genStmts(p, n.sons[j]) + + for j in 0 ..< casePos: + # prevent new local declarations + # compile declarations as assignments + let it = n.sons[j] + if it.kind in {nkLetSection, nkVarSection}: + let asgn = copyNode(it) + asgn.kind = nkAsgn + asgn.sons.setLen 2 + for sym, value in it.fieldValuePairs: + if value.kind != nkEmpty: + asgn.sons[0] = sym + asgn.sons[1] = value + genStmts(p, asgn) + else: + genStmts(p, it) var a: TLoc initLocExpr(p, caseStmt.sons[0], a) lineF(p, cpsStmts, "goto *$#[$#];$n", [tmp, a.rdLoc]) endBlock(p) + for j in casePos+1 ..< n.sons.len: + genStmts(p, n.sons[j]) + + proc genWhileStmt(p: BProc, t: PNode) = # we don't generate labels here as for example GCC would produce # significantly worse code @@ -482,26 +503,26 @@ proc genWhileStmt(p: BProc, t: PNode) = genLineDir(p, t) preserveBreakIdx: - 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): - let label = assignLabel(p.blocks[p.breakIdx]) - lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label]) var loopBody = t.sons[1] if loopBody.stmtsContainPragma(wComputedGoto) and - hasComputedGoto in CC[p.config.cCompiler].props: - # for closure support weird loop bodies are generated: + hasComputedGoto in CC[p.config.cCompiler].props: + # for closure support weird loop bodies are generated: if loopBody.len == 2 and loopBody.sons[0].kind == nkEmpty: loopBody = loopBody.sons[1] - genComputedGoto(p, loopBody) + genComputedGoto(p, loopBody) # TODO foobar else: + 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): + let label = assignLabel(p.blocks[p.breakIdx]) + lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label]) genStmts(p, loopBody) - if optProfiler in p.options: - # invoke at loop body exit: - linefmt(p, cpsStmts, "#nimProfile();$n") - endBlock(p) + if optProfiler in p.options: + # invoke at loop body exit: + linefmt(p, cpsStmts, "#nimProfile();$n") + endBlock(p) dec(p.withinLoop) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 13e0d0d11..648dcd8c4 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -84,6 +84,7 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimNoNilSeqs2") defineSymbol("nimHasUserErrors") defineSymbol("nimUncheckedArrayTyp") + defineSymbol("nimHasTypeof") defineSymbol("nimHasNilSeqs") for f in low(Feature)..high(Feature): diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 2a82b6f3b..b621e99b9 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -268,9 +268,6 @@ proc patchHead(n: PNode) = if sfFromGeneric in s.flags: excl(s.flags, sfFromGeneric) patchHead(s.getBody) - if n[1].typ.isNil: - # XXX toptree crashes without this workaround. Figure out why. - return let t = n[1].typ.skipTypes({tyVar, tyLent, tyGenericInst, tyAlias, tySink, tyInferred}) template patch(op, field) = if s.name.s == op and field != nil and field != s: @@ -296,6 +293,10 @@ proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) = m.add c.graph.config $ c.otherRead.info localError(c.graph.config, ri.info, errGenerated, m) +proc makePtrType(c: Con, baseType: PType): PType = + result = newType(tyPtr, c.owner) + addSonSkipIntLit(result, baseType) + template genOp(opr, opname, ri) = let op = opr if op == nil: @@ -304,7 +305,9 @@ template genOp(opr, opname, ri) = globalError(c.graph.config, dest.info, "internal error: '" & opname & "' operator is generic") patchHead op if sfError in op.flags: checkForErrorPragma(c, t, ri, opname) - result = newTree(nkCall, newSymNode(op), newTree(nkHiddenAddr, dest)) + let addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ)) + addrExp.add(dest) + result = newTree(nkCall, newSymNode(op), addrExp) proc genSink(c: Con; t: PType; dest, ri: PNode): PNode = let t = t.skipTypes({tyGenericInst, tyAlias, tySink}) diff --git a/compiler/lexer.nim b/compiler/lexer.nim index c62671ee9..47083216a 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -1118,6 +1118,7 @@ proc skip(L: var TLexer, tok: var TToken) = tok.strongSpaceA = 0 when defined(nimpretty): var hasComment = false + var commentIndent = L.currLineIndent tok.commentOffsetA = L.offsetBase + pos tok.commentOffsetB = tok.commentOffsetA tok.line = -1 @@ -1139,13 +1140,18 @@ proc skip(L: var TLexer, tok: var TToken) = inc(pos) inc(indent) elif buf[pos] == '#' and buf[pos+1] == '[': - when defined(nimpretty): hasComment = true + when defined(nimpretty): + hasComment = true + if tok.line < 0: + tok.line = L.lineNumber skipMultiLineComment(L, tok, pos+2, false) pos = L.bufpos buf = L.buf else: break tok.strongSpaceA = 0 + when defined(nimpretty): + if buf[pos] == '#' and tok.line < 0: commentIndent = indent if buf[pos] > ' ' and (buf[pos] != '#' or buf[pos+1] == '#'): tok.indent = indent L.currLineIndent = indent @@ -1155,7 +1161,8 @@ proc skip(L: var TLexer, tok: var TToken) = if buf[pos+1] == '#': break when defined(nimpretty): hasComment = true - if tok.line < 0: tok.line = L.lineNumber + if tok.line < 0: + tok.line = L.lineNumber if buf[pos+1] == '[': skipMultiLineComment(L, tok, pos+2, false) @@ -1177,6 +1184,7 @@ proc skip(L: var TLexer, tok: var TToken) = if hasComment: tok.commentOffsetB = L.offsetBase + pos - 1 tok.tokType = tkComment + tok.indent = commentIndent if gIndentationWidth <= 0: gIndentationWidth = tok.indent diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index bbd966b38..f3ad46a9d 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1414,6 +1414,20 @@ proc semTypeof(c: PContext; n: PNode; prev: PType): PType = fixupTypeOf(c, prev, t) result = t.typ +proc semTypeof2(c: PContext; n: PNode; prev: PType): PType = + openScope(c) + var m = BiggestInt 1 # typeOfIter + if n.len == 3: + let mode = semConstExpr(c, n[2]) + if mode.kind != nkIntLit: + localError(c.config, n.info, "typeof: cannot evaluate 'mode' parameter at compile-time") + else: + m = mode.intVal + let t = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {}) + closeScope(c) + fixupTypeOf(c, prev, t) + result = t.typ + proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = nil inc c.inTypeContext @@ -1494,6 +1508,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = elif op.id == ord(wType): checkSonsLen(n, 2, c.config) result = semTypeof(c, n[1], prev) + elif op.s == "typeof" and n[0].kind == nkSym and n[0].sym.magic == mTypeof: + result = semTypeOf2(c, n, prev) else: if c.inGenericContext > 0 and n.kind == nkCall: result = makeTypeFromExpr(c, n.copyTree) |