diff options
-rw-r--r-- | compiler/ast.nim | 11 | ||||
-rw-r--r-- | compiler/semstmts.nim | 24 | ||||
-rw-r--r-- | compiler/transf.nim | 9 | ||||
-rw-r--r-- | 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 037de3dff..155113d8a 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 <typ>` 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 9d630d4bf..f428b4708 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -291,28 +291,24 @@ 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: - # 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] + 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 - a.sons[j].typ = typ else: a.sons[j].sons[1] = newTypeNode - a.sons[j].sons[1].typ = typ + # 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 containsOrIncl(check, typ.id): localError(a.sons[j].info, errExceptionAlreadyHandled) diff --git a/compiler/transf.nim b/compiler/transf.nim index 3ff2fc86a..3a4e25eb5 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 4d9d99d16..225324c3a 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. |