diff options
-rw-r--r-- | compiler/semexprs.nim | 10 | ||||
-rw-r--r-- | lib/system.nim | 80 |
2 files changed, 59 insertions, 31 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index ae0f42dd6..7135dcf34 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1818,7 +1818,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode = result = nil template setResult(e: expr) = - if semCheck: result = semStmt(c, e) # do not open a new scope! + if semCheck: result = semExpr(c, e) # do not open a new scope! else: result = e # Check if the node is "when nimvm" @@ -1827,6 +1827,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode = # else: # ... var whenNimvm = false + var typ = commonTypeBegin if n.sons.len == 2 and n.sons[0].kind == nkElifBranch and n.sons[1].kind == nkElse: let exprNode = n.sons[0].sons[0] @@ -1843,7 +1844,8 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode = checkSonsLen(it, 2) if whenNimvm: if semCheck: - it.sons[1] = semStmt(c, it.sons[1]) + it.sons[1] = semExpr(c, it.sons[1]) + typ = commonType(typ, it.sons[1].typ) result = n # when nimvm is not elimited until codegen else: var e = semConstExpr(c, it.sons[0]) @@ -1857,12 +1859,14 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode = checkSonsLen(it, 1) if result == nil or whenNimvm: if semCheck: - it.sons[0] = semStmt(c, it.sons[0]) + it.sons[0] = semExpr(c, it.sons[0]) + typ = commonType(typ, it.sons[0].typ) if result == nil: result = it.sons[0] else: illFormedAst(n) if result == nil: result = newNodeI(nkEmpty, n.info) + if whenNimvm: result.typ = typ # The ``when`` statement implements the mechanism for platform dependent # code. Thus we try to ensure here consistent ID allocation after the # ``when`` statement. diff --git a/lib/system.nim b/lib/system.nim index 604992969..c224535f0 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3042,34 +3042,6 @@ when not defined(JS): #and not defined(nimscript): {.pop.} # stacktrace when not defined(nimscript): - proc likely*(val: bool): bool {.importc: "likely", nodecl, nosideeffect.} - ## Hints the optimizer that `val` is likely going to be true. - ## - ## You can use this proc to decorate a branch condition. On certain - ## platforms this can help the processor predict better which branch is - ## going to be run. Example: - ## - ## .. code-block:: nim - ## for value in inputValues: - ## if likely(value <= 100): - ## process(value) - ## else: - ## echo "Value too big!" - - proc unlikely*(val: bool): bool {.importc: "unlikely", nodecl, nosideeffect.} - ## Hints the optimizer that `val` is likely going to be false. - ## - ## You can use this proc to decorate a branch condition. On certain - ## platforms this can help the processor predict better which branch is - ## going to be run. Example: - ## - ## .. code-block:: nim - ## for value in inputValues: - ## if unlikely(value > 100): - ## echo "Value too big!" - ## else: - ## process(value) - proc rawProc*[T: proc](x: T): pointer {.noSideEffect, inline.} = ## retrieves the raw proc pointer of the closure `x`. This is ## useful for interfacing closures with C. @@ -3137,6 +3109,58 @@ proc quit*(errormsg: string, errorcode = QuitFailure) {.noReturn.} = {.pop.} # checks {.pop.} # hints +when not defined(JS): + proc likely_proc(val: bool): bool {.importc: "likely", nodecl, nosideeffect.} + proc unlikely_proc(val: bool): bool {.importc: "unlikely", nodecl, nosideeffect.} + +template likely*(val: bool): bool = + ## Hints the optimizer that `val` is likely going to be true. + ## + ## You can use this template to decorate a branch condition. On certain + ## platforms this can help the processor predict better which branch is + ## going to be run. Example: + ## + ## .. code-block:: nim + ## for value in inputValues: + ## if likely(value <= 100): + ## process(value) + ## else: + ## echo "Value too big!" + ## + ## On backends without branch prediction (JS and the nimscript VM), this + ## template will not affect code execution. + when nimvm: + val + else: + when defined(JS): + val + else: + likely_proc(val) + +template unlikely*(val: bool): bool = + ## Hints the optimizer that `val` is likely going to be false. + ## + ## You can use this proc to decorate a branch condition. On certain + ## platforms this can help the processor predict better which branch is + ## going to be run. Example: + ## + ## .. code-block:: nim + ## for value in inputValues: + ## if unlikely(value > 100): + ## echo "Value too big!" + ## else: + ## process(value) + ## + ## On backends without branch prediction (JS and the nimscript VM), this + ## template will not affect code execution. + when nimvm: + val + else: + when defined(JS): + val + else: + unlikely_proc(val) + proc `/`*(x, y: int): float {.inline, noSideEffect.} = ## integer division that results in a float. result = toFloat(x) / toFloat(y) |