Fixes #3691.
This commit is contained in:
parent
e8c46d29cd
commit
3cbfd56e1d
4 changed files with 41 additions and 19 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue