This commit is contained in:
Dominik Picheta
2017-02-01 21:11:40 +01:00
parent e8c46d29cd
commit 3cbfd56e1d
4 changed files with 41 additions and 19 deletions

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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.