diff options
-rw-r--r-- | compiler/semexprs.nim | 3 | ||||
-rw-r--r-- | compiler/sempass2.nim | 2 | ||||
-rw-r--r-- | compiler/semstmts.nim | 13 | ||||
-rw-r--r-- | compiler/semtypes.nim | 26 | ||||
-rw-r--r-- | tests/template/t2do.nim | 22 |
5 files changed, 47 insertions, 19 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index ab1b75994..5761e9e88 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -2113,7 +2113,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = of nkCurly: result = semSetConstr(c, n) of nkBracket: result = semArrayConstr(c, n, flags) of nkObjConstr: result = semObjConstr(c, n, flags) - of nkLambdaKinds: result = semLambda(c, n, flags) + of nkLambda: result = semLambda(c, n, flags) + of nkDo: result = semDo(c, n, flags) of nkDerefExpr: result = semDeref(c, n) of nkAddr: result = n diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index dcebf86ac..ede556a70 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -230,7 +230,7 @@ proc getEbase(): PType = proc excType(n: PNode): PType = # reraise is like raising E_Base: - let t = if n.kind == nkEmpty: getEbase() else: n.typ + let t = if n.kind == nkEmpty or n.typ.isNil: getEbase() else: n.typ result = skipTypes(t, skipPtrs) proc createRaise(n: PNode): PNode = diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 3fe3e40f0..b4790e421 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -813,8 +813,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = # we have a list of implicit type parameters: n.sons[genericParamsPos] = gp else: - s.typ = newTypeS(tyProc, c) - rawAddSon(s.typ, nil) + s.typ = newProcType(c, n.info) if n.sons[pragmasPos].kind != nkEmpty: pragma(c, s, n.sons[pragmasPos], lambdaPragmas) s.options = gOptions @@ -839,6 +838,13 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = popOwner() result.typ = s.typ +proc semDo(c: PContext, n: PNode, flags: TExprFlags): PNode = + # 'do' without params produces a stmt: + if n[genericParamsPos].kind == nkEmpty and n[paramsPos].kind == nkEmpty: + result = semStmt(c, n[bodyPos]) + else: + result = semLambda(c, n, flags) + proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode = var n = n @@ -988,8 +994,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, # check for semantics again: # semParamList(c, n.sons[ParamsPos], nil, s) else: - s.typ = newTypeS(tyProc, c) - rawAddSon(s.typ, nil) + s.typ = newProcType(c, n.info) if n.sons[patternPos].kind != nkEmpty: n.sons[patternPos] = semPattern(c, n.sons[patternPos]) if s.kind in skIterators: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 8d1655593..7908742db 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -856,25 +856,25 @@ proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType = else: result = semTypeNode(c, n, nil) +proc newProcType(c: PContext; info: TLineInfo; prev: PType = nil): PType = + result = newOrPrevType(tyProc, prev, c) + result.callConv = lastOptionEntry(c).defaultCC + result.n = newNodeI(nkFormalParams, info) + rawAddSon(result, nil) # return type + # result.n[0] used to be `nkType`, but now it's `nkEffectList` because + # the effects are now stored in there too ... this is a bit hacky, but as + # usual we desperately try to save memory: + addSon(result.n, newNodeI(nkEffectList, info)) + proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType, kind: TSymKind; isType=false): PType = # for historical reasons (code grows) this is invoked for parameter # lists too and then 'isType' is false. - var - res: PNode - cl: IntSet + var cl: IntSet checkMinSonsLen(n, 1) - result = newOrPrevType(tyProc, prev, c) - result.callConv = lastOptionEntry(c).defaultCC - result.n = newNodeI(nkFormalParams, n.info) + result = newProcType(c, n.info, prev) if genericParams != nil and sonsLen(genericParams) == 0: cl = initIntSet() - rawAddSon(result, nil) # return type - # result.n[0] used to be `nkType`, but now it's `nkEffectList` because - # the effects are now stored in there too ... this is a bit hacky, but as - # usual we desperately try to save memory: - res = newNodeI(nkEffectList, n.info) - addSon(result.n, res) var check = initIntSet() var counter = 0 for i in countup(1, n.len - 1): @@ -956,7 +956,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, # we don't need to change the return type to iter[T] if not r.isInlineIterator: r = newTypeWithSons(c, tyIter, @[r]) result.sons[0] = r - res.typ = r + result.n.typ = r if genericParams != nil: for n in genericParams: diff --git a/tests/template/t2do.nim b/tests/template/t2do.nim new file mode 100644 index 000000000..b87e3328c --- /dev/null +++ b/tests/template/t2do.nim @@ -0,0 +1,22 @@ +discard """ + output: "8.0" +""" + +# bug #2057 + +proc mpf_get_d(x: int): float = float(x) +proc mpf_cmp_d(a: int; b: float): int = 0 + +template toFloatHelper(result: expr; tooSmall, tooLarge: stmt) {.immediate.} = + result = mpf_get_d(a) + if result == 0.0 and mpf_cmp_d(a,0.0) != 0: + tooSmall + if result == Inf: + tooLarge + +proc toFloat*(a: int): float = + toFloatHelper(result) + do: raise newException(ValueError, "number too small"): + raise newException(ValueError, "number too large") + +echo toFloat(8) |