diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgstmts.nim | 37 | ||||
-rw-r--r-- | compiler/cgen.nim | 2 | ||||
-rw-r--r-- | compiler/condsyms.nim | 1 | ||||
-rw-r--r-- | compiler/dfa.nim | 2 | ||||
-rw-r--r-- | compiler/jsgen.nim | 8 | ||||
-rw-r--r-- | compiler/optimizer.nim | 2 | ||||
-rw-r--r-- | compiler/sempass2.nim | 2 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | compiler/semtypes.nim | 4 |
9 files changed, 42 insertions, 18 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 0d17031df..0980de98f 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -837,17 +837,27 @@ template genCaseGeneric(p: BProc, t: PNode, d: var TLoc, fixLabel(p, lend) proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel, + stringKind: TTypeKind, branches: var openArray[Rope]) = var x: TLoc for i in 0..<b.len - 1: assert(b[i].kind != nkRange) initLocExpr(p, b[i], x) - assert(b[i].kind in {nkStrLit..nkTripleStrLit}) - var j = int(hashString(p.config, b[i].strVal) and high(branches)) - appcg(p.module, branches[j], "if (#eqStrings($1, $2)) goto $3;$n", + var j: int + case b[i].kind + of nkStrLit..nkTripleStrLit: + j = int(hashString(p.config, b[i].strVal) and high(branches)) + of nkNilLit: j = 0 + else: + assert false, "invalid string case branch node kind" + if stringKind == tyCstring: + appcg(p.module, branches[j], "if (#eqCstrings($1, $2)) goto $3;$n", + [rdLoc(e), rdLoc(x), labl]) + else: + 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) = +proc genStringCase(p: BProc, t: PNode, stringKind: TTypeKind, d: var TLoc) = # count how many constant strings there are in the case: var strings = 0 for i in 1..<t.len: @@ -863,13 +873,17 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) = inc(p.labels) if t[i].kind == nkOfBranch: genCaseStringBranch(p, t[i], a, "LA" & rope(p.labels) & "_", - branches) + stringKind, branches) 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", - [rdLoc(a), bitMask]) + if stringKind == tyCstring: + linefmt(p, cpsStmts, "switch (#hashCstring($1) & $2) {$n", + [rdLoc(a), bitMask]) + else: + linefmt(p, cpsStmts, "switch (#hashString($1) & $2) {$n", + [rdLoc(a), bitMask]) for j in 0..high(branches): if branches[j] != nil: lineF(p, cpsStmts, "case $1: $n$2break;$n", @@ -881,7 +895,10 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) = var lend = genCaseSecondPass(p, t, d, labId, t.len-1) fixLabel(p, lend) else: - genCaseGeneric(p, t, d, "", "if (#eqStrings($1, $2)) goto $3;$n") + if stringKind == tyCstring: + genCaseGeneric(p, t, d, "", "if (#eqCstrings($1, $2)) goto $3;$n") + else: + genCaseGeneric(p, t, d, "", "if (#eqStrings($1, $2)) goto $3;$n") proc branchHasTooBigRange(b: PNode): bool = for it in b: @@ -954,7 +971,9 @@ proc genCase(p: BProc, t: PNode, d: var TLoc) = getTemp(p, t.typ, d) case skipTypes(t[0].typ, abstractVarRange).kind of tyString: - genStringCase(p, t, d) + genStringCase(p, t, tyString, d) + of tyCstring: + genStringCase(p, t, tyCstring, d) of tyFloat..tyFloat128: genCaseGeneric(p, t, d, "if ($1 >= $2 && $1 <= $3) goto $4;$n", "if ($1 == $2) goto $3;$n") diff --git a/compiler/cgen.nim b/compiler/cgen.nim index c0b94ebbb..3896a46ca 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -966,7 +966,7 @@ proc allPathsAsgnResult(n: PNode): InitResultEnum = if containsResult(n[0]): return InitRequired result = InitSkippable var exhaustive = skipTypes(n[0].typ, - abstractVarRange-{tyTypeDesc}).kind notin {tyFloat..tyFloat128, tyString} + abstractVarRange-{tyTypeDesc}).kind notin {tyFloat..tyFloat128, tyString, tyCstring} for i in 1..<n.len: let it = n[i] allPathsInBranch(it.lastSon) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index f1d16c4e4..d811f2d75 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -142,3 +142,4 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimHasEnforceNoRaises") defineSymbol("nimHasTopDownInference") defineSymbol("nimHasTemplateRedefinitionPragma") + defineSymbol("nimHasCstringCase") diff --git a/compiler/dfa.nim b/compiler/dfa.nim index 5b048ff6e..669207151 100644 --- a/compiler/dfa.nim +++ b/compiler/dfa.nim @@ -461,7 +461,7 @@ proc genCase(c: var Con; n: PNode) = # elsePart # Lend: let isExhaustive = skipTypes(n[0].typ, - abstractVarRange-{tyTypeDesc}).kind notin {tyFloat..tyFloat128, tyString} + abstractVarRange-{tyTypeDesc}).kind notin {tyFloat..tyFloat128, tyString, tyCstring} # we generate endings as a set of chained gotos, this is a bit awkward but it # ensures when recursively traversing the CFG for various analysis, we don't diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index bbc64a2f0..a221b3127 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -873,8 +873,9 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) = totalRange = 0 genLineDir(p, n) gen(p, n[0], cond) - let stringSwitch = skipTypes(n[0].typ, abstractVar).kind == tyString - if stringSwitch: + let typeKind = skipTypes(n[0].typ, abstractVar).kind + let anyString = typeKind in {tyString, tyCstring} + if typeKind == tyString: useMagic(p, "toJSStr") lineF(p, "switch (toJSStr($1)) {$n", [cond.rdLoc]) else: @@ -899,10 +900,11 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) = lineF(p, "case $1:$n", [cond.rdLoc]) inc(v.intVal) else: - if stringSwitch: + if anyString: case e.kind of nkStrLit..nkTripleStrLit: lineF(p, "case $1:$n", [makeJSString(e.strVal, false)]) + of nkNilLit: lineF(p, "case null:$n", []) else: internalError(p.config, e.info, "jsgen.genCaseStmt: 2") else: gen(p, e, cond) diff --git a/compiler/optimizer.nim b/compiler/optimizer.nim index f484fdbf5..10b092e11 100644 --- a/compiler/optimizer.nim +++ b/compiler/optimizer.nim @@ -178,7 +178,7 @@ proc analyse(c: var Con; b: var BasicBlock; n: PNode) = of nkCaseStmt: let isExhaustive = skipTypes(n[0].typ, - abstractVarRange-{tyTypeDesc}).kind notin {tyFloat..tyFloat128, tyString} or + abstractVarRange-{tyTypeDesc}).kind notin {tyFloat..tyFloat128, tyString, tyCstring} or n[^1].kind == nkElse analyse(c, b, n[0]) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index ae6d638e4..df767630d 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -684,7 +684,7 @@ proc trackCase(tracked: PEffects, n: PNode) = let oldState = tracked.init.len let oldFacts = tracked.guards.s.len let stringCase = n[0].typ != nil and skipTypes(n[0].typ, - abstractVarRange-{tyTypeDesc}).kind in {tyFloat..tyFloat128, tyString} + abstractVarRange-{tyTypeDesc}).kind in {tyFloat..tyFloat128, tyString, tyCstring} let interesting = not stringCase and interestingCaseExpr(n[0]) and tracked.config.hasWarn(warnProveField) var inter: TIntersection = @[] diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 43687cd2e..6ced487ce 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1067,7 +1067,7 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil of tyRange: if skipTypes(caseTyp[0], abstractInst).kind in shouldChckCovered: chckCovered = true - of tyFloat..tyFloat128, tyString, tyError: + of tyFloat..tyFloat128, tyString, tyCstring, tyError: discard else: popCaseContext(c) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 8ddc2196a..e807e0870 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -603,7 +603,9 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, checkMinSonsLen(t, 1, c.config) var tmp = fitNode(c, t[0].typ, r, r.info) # the call to fitNode may introduce a call to a converter - if tmp.kind in {nkHiddenCallConv}: tmp = semConstExpr(c, tmp) + if tmp.kind == nkHiddenCallConv or + (tmp.kind == nkHiddenStdConv and t[0].typ.kind == tyCstring): + tmp = semConstExpr(c, tmp) branch[i] = skipConv(tmp) inc(covered) else: |