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

View file

@ -1585,12 +1585,21 @@ proc skipStmtList*(n: PNode): PNode =
result = n result = n
proc toRef*(typ: PType): PType = 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 result = typ
if typ.kind == tyObject: if typ.kind == tyObject:
# Convert to a `ref T`.
result = newType(tyRef, typ.owner) result = newType(tyRef, typ.owner)
rawAddSon(result, typ) 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: when false:
proc containsNil*(n: PNode): bool = proc containsNil*(n: PNode): bool =
# only for debugging # only for debugging

View file

@ -291,8 +291,16 @@ proc semTry(c: PContext, n: PNode): PNode =
symbolNode = a.sons[j].sons[2] symbolNode = a.sons[j].sons[2]
# Resolve the type ident into a PType. # Resolve the type ident into a PType.
var typ = semTypeNode(c, typeNode, nil) var typ = semTypeNode(c, typeNode, nil).toObject()
if not symbolNode.isNil: 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. # Add the exception ident to the symbol table.
let symbol = newSymG(skLet, symbolNode, c) let symbol = newSymG(skLet, symbolNode, c)
symbol.typ = typ.toRef() symbol.typ = typ.toRef()
@ -302,18 +310,6 @@ proc semTry(c: PContext, n: PNode): PNode =
symNode.sym = symbol symNode.sym = symbol
a.sons[j].sons[2] = symNode 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): if containsOrIncl(check, typ.id):
localError(a.sons[j].info, errExceptionAlreadyHandled) localError(a.sons[j].info, errExceptionAlreadyHandled)
elif a.kind != nkFinally: elif a.kind != nkFinally:

View file

@ -707,12 +707,14 @@ proc transformExceptBranch(c: PTransf, n: PNode): PTransNode =
let excTypeNode = n[0][1] let excTypeNode = n[0][1]
let actions = newTransNode(nkStmtList, n[1].info, 2) let actions = newTransNode(nkStmtList, n[1].info, 2)
# Generating `let exc = (excType)(getCurrentException())` # Generating `let exc = (excType)(getCurrentException())`
# -> getCurrentException()
let excCall = PTransNode(callCodegenProc("getCurrentException", ast.emptyNode)) let excCall = PTransNode(callCodegenProc("getCurrentException", ast.emptyNode))
# -> (excType)
let convNode = newTransNode(nkHiddenSubConv, n[1].info, 2) let convNode = newTransNode(nkHiddenSubConv, n[1].info, 2)
convNode[0] = PTransNode(ast.emptyNode) convNode[0] = PTransNode(ast.emptyNode)
convNode[1] = excCall convNode[1] = excCall
PNode(convNode).typ = excTypeNode.typ.toRef() PNode(convNode).typ = excTypeNode.typ.toRef()
# -> let exc = ...
let identDefs = newTransNode(nkIdentDefs, n[1].info, 3) let identDefs = newTransNode(nkIdentDefs, n[1].info, 3)
identDefs[0] = PTransNode(n[0][2]) identDefs[0] = PTransNode(n[0][2])
identDefs[1] = PTransNode(ast.emptyNode) identDefs[1] = PTransNode(ast.emptyNode)
@ -720,15 +722,14 @@ proc transformExceptBranch(c: PTransf, n: PNode): PTransNode =
let letSection = newTransNode(nkLetSection, n[1].info, 1) let letSection = newTransNode(nkLetSection, n[1].info, 1)
letSection[0] = identDefs letSection[0] = identDefs
# Place the let statement and body of the 'except' branch into new stmtList.
actions[0] = letSection actions[0] = letSection
actions[1] = transformSons(c, n[1]) actions[1] = transformSons(c, n[1])
# Overwrite 'except' branch body with our stmtList.
result[1] = actions result[1] = actions
# Replace the `Exception as foobar` with just `Exception`. # Replace the `Exception as foobar` with just `Exception`.
result[0] = result[0][1] result[0] = result[0][1]
#debug(PNode(result))
#echo(PNode(result))
proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} = proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} =
# symbols that expand to a complex constant (array, etc.) should not be # symbols that expand to a complex constant (array, etc.) should not be

View file

@ -25,3 +25,19 @@ Compiler Additions
Language 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.