From e8c46d29cdfa604bf13294bc3505938fc243754d Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Wed, 1 Feb 2017 00:32:56 +0100 Subject: [PATCH 1/9] WIP implementation of `except ExcType as ident` syntax. Refs #3691. --- compiler/ast.nim | 7 +++++++ compiler/semstmts.nim | 37 ++++++++++++++++++++++++++++++++++--- compiler/transf.nim | 31 +++++++++++++++++++++++++++++++ tests/exception/texcas.nim | 10 ++++++++++ 4 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 tests/exception/texcas.nim diff --git a/compiler/ast.nim b/compiler/ast.nim index d9c886d7f4..037de3dff6 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1584,6 +1584,13 @@ proc skipStmtList*(n: PNode): PNode = else: result = n +proc toRef*(typ: PType): PType = + result = typ + if typ.kind == tyObject: + # Convert to a `ref T`. + result = newType(tyRef, typ.owner) + rawAddSon(result, typ) + when false: proc containsNil*(n: PNode): bool = # only for debugging diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index bbc83eca46..9d630d4bfa 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -263,36 +263,67 @@ proc semTry(c: PContext, n: PNode): PNode = result = n inc c.p.inTryStmt checkMinSonsLen(n, 2) + var typ = commonTypeBegin n.sons[0] = semExprBranchScope(c, n.sons[0]) typ = commonType(typ, n.sons[0].typ) + var check = initIntSet() var last = sonsLen(n) - 1 for i in countup(1, last): var a = n.sons[i] checkMinSonsLen(a, 1) var length = sonsLen(a) + if a.kind == nkExceptBranch: # so that ``except [a, b, c]`` is supported: if length == 2 and a.sons[0].kind == nkBracket: a.sons[0..0] = a.sons[0].sons length = a.sonsLen + # Iterate through each exception type in the except branch. for j in countup(0, length-2): - var typ = semTypeNode(c, a.sons[j], nil) + var typeNode = a.sons[j] # e.g. `Exception` + var symbolNode: PNode = nil # e.g. `foobar` + # Handle the case where the `Exception as foobar` syntax is used. + if typeNode.kind == nkInfix: + typeNode = a.sons[j].sons[1] + symbolNode = a.sons[j].sons[2] + + # Resolve the type ident into a PType. + var typ = semTypeNode(c, typeNode, nil) + if not symbolNode.isNil: + # Add the exception ident to the symbol table. + let symbol = newSymG(skLet, symbolNode, c) + symbol.typ = typ.toRef() + addDecl(c, symbol) + # Overwrite symbol in AST with the symbol in the symbol table. + let symNode = newNodeI(nkSym, typeNode.info) + symNode.sym = symbol + a.sons[j].sons[2] = symNode + if typ.kind == tyRef: typ = typ.sons[0] if typ.kind != tyObject: localError(a.sons[j].info, errExprCannotBeRaised) - a.sons[j] = newNodeI(nkType, a.sons[j].info) - a.sons[j].typ = typ + + let newTypeNode = newNodeI(nkType, typeNode.info) + if symbolNode.isNil: + a.sons[j] = newTypeNode + a.sons[j].typ = typ + else: + a.sons[j].sons[1] = newTypeNode + a.sons[j].sons[1].typ = typ + if containsOrIncl(check, typ.id): localError(a.sons[j].info, errExceptionAlreadyHandled) elif a.kind != nkFinally: illFormedAst(n) + # last child of an nkExcept/nkFinally branch is a statement: a.sons[length-1] = semExprBranchScope(c, a.sons[length-1]) if a.kind != nkFinally: typ = commonType(typ, a.sons[length-1].typ) else: dec last + dec c.p.inTryStmt if isEmptyType(typ) or typ.kind == tyNil: discardCheck(c, n.sons[0]) diff --git a/compiler/transf.nim b/compiler/transf.nim index 6eed17b2a9..3ff2fc86a1 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -701,6 +701,35 @@ proc transformCall(c: PTransf, n: PNode): PTransNode = else: result = s.PTransNode +proc transformExceptBranch(c: PTransf, n: PNode): PTransNode = + result = transformSons(c, n) + if n[0].kind == nkInfix: + let excTypeNode = n[0][1] + let actions = newTransNode(nkStmtList, n[1].info, 2) + # Generating `let exc = (excType)(getCurrentException())` + let excCall = PTransNode(callCodegenProc("getCurrentException", ast.emptyNode)) + let convNode = newTransNode(nkHiddenSubConv, n[1].info, 2) + convNode[0] = PTransNode(ast.emptyNode) + convNode[1] = excCall + PNode(convNode).typ = excTypeNode.typ.toRef() + + let identDefs = newTransNode(nkIdentDefs, n[1].info, 3) + identDefs[0] = PTransNode(n[0][2]) + identDefs[1] = PTransNode(ast.emptyNode) + identDefs[2] = convNode + + let letSection = newTransNode(nkLetSection, n[1].info, 1) + letSection[0] = identDefs + + actions[0] = letSection + actions[1] = transformSons(c, n[1]) + result[1] = actions + + # Replace the `Exception as foobar` with just `Exception`. + result[0] = result[0][1] + #debug(PNode(result)) + #echo(PNode(result)) + proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} = # symbols that expand to a complex constant (array, etc.) should not be # inlined, unless it's the empty array: @@ -851,6 +880,8 @@ proc transform(c: PTransf, n: PNode): PTransNode = if a.kind == nkSym: n.sons[1] = transformSymAux(c, a) return PTransNode(n) + of nkExceptBranch: + result = transformExceptBranch(c, n) else: result = transformSons(c, n) when false: diff --git a/tests/exception/texcas.nim b/tests/exception/texcas.nim new file mode 100644 index 0000000000..ac6e5db627 --- /dev/null +++ b/tests/exception/texcas.nim @@ -0,0 +1,10 @@ +discard """ + output: '''Hello''' +""" + +try: + raise newException(Exception, "Hello") +except Exception as foobar: + echo(foobar.msg) + + From 3cbfd56e1d02f30124a15db6104ac5d7ffbbbea3 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Wed, 1 Feb 2017 21:11:40 +0100 Subject: [PATCH 2/9] Fixes #3691. --- compiler/ast.nim | 11 ++++++++++- compiler/semstmts.nim | 24 ++++++++++-------------- compiler/transf.nim | 9 +++++---- web/news/e031_version_0_16_2.rst | 16 ++++++++++++++++ 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 037de3dff6..155113d8a7 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1585,12 +1585,21 @@ proc skipStmtList*(n: PNode): PNode = result = n proc toRef*(typ: PType): PType = + ## If ``typ`` is a tyObject then it is converted into a `ref ` and + ## returned. Otherwise ``typ`` is simply returned as-is. result = typ if typ.kind == tyObject: - # Convert to a `ref T`. result = newType(tyRef, typ.owner) rawAddSon(result, typ) +proc toObject*(typ: PType): PType = + ## If ``typ`` is a tyRef then its immediate son is returned (which in many + ## cases should be a ``tyObject``). + ## Otherwise ``typ`` is simply returned as-is. + result = typ + if result.kind == tyRef: + result = result.sons[0] + when false: proc containsNil*(n: PNode): bool = # only for debugging diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 9d630d4bfa..f428b47080 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -291,8 +291,16 @@ proc semTry(c: PContext, n: PNode): PNode = symbolNode = a.sons[j].sons[2] # Resolve the type ident into a PType. - var typ = semTypeNode(c, typeNode, nil) - if not symbolNode.isNil: + var typ = semTypeNode(c, typeNode, nil).toObject() + if typ.kind != tyObject: + localError(a.sons[j].info, errExprCannotBeRaised) + + let newTypeNode = newNodeI(nkType, typeNode.info) + newTypeNode.typ = typ + if symbolNode.isNil: + a.sons[j] = newTypeNode + else: + a.sons[j].sons[1] = newTypeNode # Add the exception ident to the symbol table. let symbol = newSymG(skLet, symbolNode, c) symbol.typ = typ.toRef() @@ -302,18 +310,6 @@ proc semTry(c: PContext, n: PNode): PNode = symNode.sym = symbol a.sons[j].sons[2] = symNode - if typ.kind == tyRef: typ = typ.sons[0] - if typ.kind != tyObject: - localError(a.sons[j].info, errExprCannotBeRaised) - - let newTypeNode = newNodeI(nkType, typeNode.info) - if symbolNode.isNil: - a.sons[j] = newTypeNode - a.sons[j].typ = typ - else: - a.sons[j].sons[1] = newTypeNode - a.sons[j].sons[1].typ = typ - if containsOrIncl(check, typ.id): localError(a.sons[j].info, errExceptionAlreadyHandled) elif a.kind != nkFinally: diff --git a/compiler/transf.nim b/compiler/transf.nim index 3ff2fc86a1..3a4e25eb56 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -707,12 +707,14 @@ proc transformExceptBranch(c: PTransf, n: PNode): PTransNode = let excTypeNode = n[0][1] let actions = newTransNode(nkStmtList, n[1].info, 2) # Generating `let exc = (excType)(getCurrentException())` + # -> getCurrentException() let excCall = PTransNode(callCodegenProc("getCurrentException", ast.emptyNode)) + # -> (excType) let convNode = newTransNode(nkHiddenSubConv, n[1].info, 2) convNode[0] = PTransNode(ast.emptyNode) convNode[1] = excCall PNode(convNode).typ = excTypeNode.typ.toRef() - + # -> let exc = ... let identDefs = newTransNode(nkIdentDefs, n[1].info, 3) identDefs[0] = PTransNode(n[0][2]) identDefs[1] = PTransNode(ast.emptyNode) @@ -720,15 +722,14 @@ proc transformExceptBranch(c: PTransf, n: PNode): PTransNode = let letSection = newTransNode(nkLetSection, n[1].info, 1) letSection[0] = identDefs - + # Place the let statement and body of the 'except' branch into new stmtList. actions[0] = letSection actions[1] = transformSons(c, n[1]) + # Overwrite 'except' branch body with our stmtList. result[1] = actions # Replace the `Exception as foobar` with just `Exception`. result[0] = result[0][1] - #debug(PNode(result)) - #echo(PNode(result)) proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} = # symbols that expand to a complex constant (array, etc.) should not be diff --git a/web/news/e031_version_0_16_2.rst b/web/news/e031_version_0_16_2.rst index 4d9d99d165..225324c3aa 100644 --- a/web/news/e031_version_0_16_2.rst +++ b/web/news/e031_version_0_16_2.rst @@ -25,3 +25,19 @@ Compiler Additions Language Additions ------------------ +- The ``try`` statement's ``except`` branches now support the binding of a +caught exception to a variable: + +.. code-block:: nim + try: + raise newException(Exception, "Hello World") + except Exception as exc: + echo(exc.msg) + +This replaces the ``getCurrentException`` and ``getCurrentExceptionMsg()`` +procedures, although these procedures will remain in the stdlib for the +foreseeable future. This new language feature is actually implemented using +these procedures. + +In the near future we will be converting all exception types to refs to +remove the need for the ``newException`` template. From 814f527175c0141c8f023b100461e72a9e990e6c Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Wed, 1 Feb 2017 21:51:17 +0100 Subject: [PATCH 3/9] Fixes based on @Araq's feedback. --- compiler/ast.nim | 2 +- compiler/semstmts.nim | 3 ++- compiler/transf.nim | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 155113d8a7..4ea68dc996 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1598,7 +1598,7 @@ proc toObject*(typ: PType): PType = ## Otherwise ``typ`` is simply returned as-is. result = typ if result.kind == tyRef: - result = result.sons[0] + result = result.lastSon when false: proc containsNil*(n: PNode): bool = diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index f428b47080..35c686bcba 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -286,7 +286,8 @@ proc semTry(c: PContext, n: PNode): PNode = var typeNode = a.sons[j] # e.g. `Exception` var symbolNode: PNode = nil # e.g. `foobar` # Handle the case where the `Exception as foobar` syntax is used. - if typeNode.kind == nkInfix: + if typeNode.kind == nkInfix and + considerQuotedIdent(typeNode[0]).s == "as": typeNode = a.sons[j].sons[1] symbolNode = a.sons[j].sons[2] diff --git a/compiler/transf.nim b/compiler/transf.nim index 3a4e25eb56..8944ff43b2 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -21,7 +21,7 @@ import intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os, idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread, - lambdalifting, sempass2, lowerings + lambdalifting, sempass2, lowerings, lookups # implementation @@ -703,7 +703,7 @@ proc transformCall(c: PTransf, n: PNode): PTransNode = proc transformExceptBranch(c: PTransf, n: PNode): PTransNode = result = transformSons(c, n) - if n[0].kind == nkInfix: + if n[0].kind == nkInfix and considerQuotedIdent(n[0][0]).s == "as": let excTypeNode = n[0][1] let actions = newTransNode(nkStmtList, n[1].info, 2) # Generating `let exc = (excType)(getCurrentException())` From 656da1f6a99c504eb5bf7c51b01b8fe00e2afd71 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Thu, 2 Feb 2017 21:36:49 +0100 Subject: [PATCH 4/9] WIP: `as` with generics. --- compiler/lookups.nim | 3 +++ compiler/semgnrc.nim | 11 ++++++++++- compiler/semstmts.nim | 3 +-- compiler/transf.nim | 2 +- tests/exception/texcas.nim | 12 ++++++------ 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 61ecdb24b2..cb7985384a 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -434,3 +434,6 @@ proc pickSym*(c: PContext, n: PNode; kind: TSymKind; if a.kind == kind and flags <= a.flags: return a a = nextOverloadIter(o, c, n) + +proc isExceptAs*(n: PNode): bool = + return n.kind == nkInfix and considerQuotedIdent(n[0]).s == "as" \ No newline at end of file diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index ab0ce7c4c2..42f9bd4015 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -339,8 +339,17 @@ proc semGenericStmt(c: PContext, n: PNode, checkMinSonsLen(a, 1) var L = sonsLen(a) for j in countup(0, L-2): - a.sons[j] = semGenericStmt(c, a.sons[j], flags+{withinTypeDesc}, ctx) + debug(a.sons[j]) + if a.sons[j].isExceptAs(): + openScope(c) + addTempDecl(c, getIdentNode(a.sons[j][2]), skLet) + a.sons[j] = semGenericStmt(c, a.sons[j][1], flags+{withinTypeDesc}, ctx) + closeScope(c) + else: + a.sons[j] = semGenericStmt(c, a.sons[j], flags+{withinTypeDesc}, ctx) + debug(a) a.sons[L-1] = semGenericStmtScope(c, a.sons[L-1], flags, ctx) + of nkVarSection, nkLetSection: for i in countup(0, sonsLen(n) - 1): var a = n.sons[i] diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 35c686bcba..6745893065 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -286,8 +286,7 @@ proc semTry(c: PContext, n: PNode): PNode = var typeNode = a.sons[j] # e.g. `Exception` var symbolNode: PNode = nil # e.g. `foobar` # Handle the case where the `Exception as foobar` syntax is used. - if typeNode.kind == nkInfix and - considerQuotedIdent(typeNode[0]).s == "as": + if typeNode.isExceptAs(): typeNode = a.sons[j].sons[1] symbolNode = a.sons[j].sons[2] diff --git a/compiler/transf.nim b/compiler/transf.nim index 8944ff43b2..838b2d902d 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -703,7 +703,7 @@ proc transformCall(c: PTransf, n: PNode): PTransNode = proc transformExceptBranch(c: PTransf, n: PNode): PTransNode = result = transformSons(c, n) - if n[0].kind == nkInfix and considerQuotedIdent(n[0][0]).s == "as": + if n[0].isExceptAs(): let excTypeNode = n[0][1] let actions = newTransNode(nkStmtList, n[1].info, 2) # Generating `let exc = (excType)(getCurrentException())` diff --git a/tests/exception/texcas.nim b/tests/exception/texcas.nim index ac6e5db627..807f2c8029 100644 --- a/tests/exception/texcas.nim +++ b/tests/exception/texcas.nim @@ -1,10 +1,10 @@ discard """ output: '''Hello''' """ +proc test[T]() = + try: + raise newException(T, "Hello") + except T as foobar: + echo(foobar.msg) -try: - raise newException(Exception, "Hello") -except Exception as foobar: - echo(foobar.msg) - - +test[Exception]() From 1c233ba27a17830e325822fc27a12074eef49ccb Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Fri, 3 Feb 2017 19:50:22 +0100 Subject: [PATCH 5/9] More progress towards a working #3691. --- compiler/lookups.nim | 2 +- compiler/semgnrc.nim | 10 ++++------ compiler/semstmts.nim | 2 +- compiler/transf.nim | 2 +- tests/exception/texcas.nim | 17 ++++++++++++++++- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/compiler/lookups.nim b/compiler/lookups.nim index cb7985384a..19a4da07b7 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -435,5 +435,5 @@ proc pickSym*(c: PContext, n: PNode; kind: TSymKind; return a a = nextOverloadIter(o, c, n) -proc isExceptAs*(n: PNode): bool = +proc isInfixAs*(n: PNode): bool = return n.kind == nkInfix and considerQuotedIdent(n[0]).s == "as" \ No newline at end of file diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index 42f9bd4015..bc80c41ad1 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -338,17 +338,15 @@ proc semGenericStmt(c: PContext, n: PNode, var a = n.sons[i] checkMinSonsLen(a, 1) var L = sonsLen(a) + openScope(c) for j in countup(0, L-2): - debug(a.sons[j]) - if a.sons[j].isExceptAs(): - openScope(c) + if a.sons[j].isInfixAs(): addTempDecl(c, getIdentNode(a.sons[j][2]), skLet) - a.sons[j] = semGenericStmt(c, a.sons[j][1], flags+{withinTypeDesc}, ctx) - closeScope(c) + a.sons[j].sons[1] = semGenericStmt(c, a.sons[j][1], flags+{withinTypeDesc}, ctx) else: a.sons[j] = semGenericStmt(c, a.sons[j], flags+{withinTypeDesc}, ctx) - debug(a) a.sons[L-1] = semGenericStmtScope(c, a.sons[L-1], flags, ctx) + closeScope(c) of nkVarSection, nkLetSection: for i in countup(0, sonsLen(n) - 1): diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 6745893065..9752ccac16 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -286,7 +286,7 @@ proc semTry(c: PContext, n: PNode): PNode = var typeNode = a.sons[j] # e.g. `Exception` var symbolNode: PNode = nil # e.g. `foobar` # Handle the case where the `Exception as foobar` syntax is used. - if typeNode.isExceptAs(): + if typeNode.isInfixAs(): typeNode = a.sons[j].sons[1] symbolNode = a.sons[j].sons[2] diff --git a/compiler/transf.nim b/compiler/transf.nim index 838b2d902d..13c6dd8fe2 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -703,7 +703,7 @@ proc transformCall(c: PTransf, n: PNode): PTransNode = proc transformExceptBranch(c: PTransf, n: PNode): PTransNode = result = transformSons(c, n) - if n[0].isExceptAs(): + if n[0].isInfixAs(): let excTypeNode = n[0][1] let actions = newTransNode(nkStmtList, n[1].info, 2) # Generating `let exc = (excType)(getCurrentException())` diff --git a/tests/exception/texcas.nim b/tests/exception/texcas.nim index 807f2c8029..a00b09a8fc 100644 --- a/tests/exception/texcas.nim +++ b/tests/exception/texcas.nim @@ -1,10 +1,25 @@ discard """ - output: '''Hello''' + output: '''Hello + Hello + ''' """ proc test[T]() = try: raise newException(T, "Hello") except T as foobar: echo(foobar.msg) + echo(declared(foobar)) + doAssert(not declared(foobar)) + +template testTemplate() = + try: + raise newException(Exception, "Hello") + except Exception as foobar: + echo(foobar.msg) + doAssert(not declared(foobar)) + +proc test2() = + testTemplate() + doAssert(not declared(foobar)) test[Exception]() From 4661ae22dd87727900eb7e106957afce2047e284 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Mon, 6 Feb 2017 19:02:51 +0100 Subject: [PATCH 6/9] Fixes incorrect scoping in semstmts.semTry. --- compiler/semstmts.nim | 3 ++- tests/exception/texcas.nim | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 9752ccac16..25d4b3c745 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -274,7 +274,7 @@ proc semTry(c: PContext, n: PNode): PNode = var a = n.sons[i] checkMinSonsLen(a, 1) var length = sonsLen(a) - + openScope(c) if a.kind == nkExceptBranch: # so that ``except [a, b, c]`` is supported: if length == 2 and a.sons[0].kind == nkBracket: @@ -319,6 +319,7 @@ proc semTry(c: PContext, n: PNode): PNode = a.sons[length-1] = semExprBranchScope(c, a.sons[length-1]) if a.kind != nkFinally: typ = commonType(typ, a.sons[length-1].typ) else: dec last + closeScope(c) dec c.p.inTryStmt if isEmptyType(typ) or typ.kind == tyNil: diff --git a/tests/exception/texcas.nim b/tests/exception/texcas.nim index a00b09a8fc..dfbed8f467 100644 --- a/tests/exception/texcas.nim +++ b/tests/exception/texcas.nim @@ -8,7 +8,6 @@ proc test[T]() = raise newException(T, "Hello") except T as foobar: echo(foobar.msg) - echo(declared(foobar)) doAssert(not declared(foobar)) template testTemplate() = From e01c3561dc6ed08cd6c34a29d12c4c9951840f4b Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Mon, 6 Feb 2017 19:25:09 +0100 Subject: [PATCH 7/9] Add template tests for #3691. --- tests/exception/texcas.nim | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/exception/texcas.nim b/tests/exception/texcas.nim index dfbed8f467..627b36632d 100644 --- a/tests/exception/texcas.nim +++ b/tests/exception/texcas.nim @@ -10,15 +10,16 @@ proc test[T]() = echo(foobar.msg) doAssert(not declared(foobar)) -template testTemplate() = +template testTemplate(excType: typedesc) = try: - raise newException(Exception, "Hello") - except Exception as foobar: + raise newException(excType, "Hello") + except excType as foobar: echo(foobar.msg) doAssert(not declared(foobar)) proc test2() = - testTemplate() + testTemplate(Exception) doAssert(not declared(foobar)) test[Exception]() +test2() \ No newline at end of file From 3c8c5d081e50058569f6257d16a21ec928637aa0 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Mon, 6 Feb 2017 20:42:01 +0100 Subject: [PATCH 8/9] Adds `except T as ident` handling in semtempl. --- compiler/semtempl.nim | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index b639288079..c9a70e9bc9 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -391,9 +391,15 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode = var a = n.sons[i] checkMinSonsLen(a, 1) var L = sonsLen(a) + openScope(c) for j in countup(0, L-2): - a.sons[j] = semTemplBody(c, a.sons[j]) + if a.sons[j].isInfixAs(): + addLocalDecl(c, a.sons[j].sons[2], skLet) + a.sons[j].sons[1] = semTemplBody(c, a.sons[j][1]) + else: + a.sons[j] = semTemplBody(c, a.sons[j]) a.sons[L-1] = semTemplBodyScope(c, a.sons[L-1]) + closeScope(c) of nkVarSection: semTemplSomeDecl(c, n, skVar) of nkLetSection: semTemplSomeDecl(c, n, skLet) of nkFormalParams: From b7d7feffee9d02c60f80745606edf4ac00321aae Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Mon, 6 Feb 2017 22:01:27 +0100 Subject: [PATCH 9/9] Fixes test. --- tests/exception/texcas.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/exception/texcas.nim b/tests/exception/texcas.nim index 627b36632d..4b4ebe4488 100644 --- a/tests/exception/texcas.nim +++ b/tests/exception/texcas.nim @@ -1,6 +1,6 @@ discard """ output: '''Hello - Hello +Hello ''' """ proc test[T]() =