1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
#
#
# The Nim Compiler
# (c) Copyright 2021 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module contains support code for new-styled error
## handling via an `nkError` node kind.
import ast, renderer, options, strutils, types
when defined(nimPreviewSlimSystem):
import std/assertions
type
ErrorKind* = enum ## expand as you need.
RawTypeMismatchError
ExpressionCannotBeCalled
CustomError
WrongNumberOfArguments
AmbiguousCall
proc errorSubNode*(n: PNode): PNode =
case n.kind
of nkEmpty..nkNilLit:
result = nil
of nkError:
result = n
else:
result = nil
for i in 0..<n.len:
result = errorSubNode(n[i])
if result != nil: break
proc newError*(wrongNode: PNode; k: ErrorKind; args: varargs[PNode]): PNode =
assert wrongNode.kind != nkError
let innerError = errorSubNode(wrongNode)
if innerError != nil:
return innerError
result = newNodeIT(nkError, wrongNode.info, newType(tyError, ItemId(module: -1, item: -1), nil))
result.add wrongNode
result.add newIntNode(nkIntLit, ord(k))
for a in args: result.add a
proc newError*(wrongNode: PNode; msg: string): PNode =
assert wrongNode.kind != nkError
let innerError = errorSubNode(wrongNode)
if innerError != nil:
return innerError
result = newNodeIT(nkError, wrongNode.info, newType(tyError, ItemId(module: -1, item: -1), nil))
result.add wrongNode
result.add newIntNode(nkIntLit, ord(CustomError))
result.add newStrNode(msg, wrongNode.info)
proc errorToString*(config: ConfigRef; n: PNode): string =
assert n.kind == nkError
assert n.len > 1
let wrongNode = n[0]
case ErrorKind(n[1].intVal)
of RawTypeMismatchError:
result = "type mismatch"
of ExpressionCannotBeCalled:
result = "expression '$1' cannot be called" % wrongNode[0].renderTree
of CustomError:
result = n[2].strVal
of WrongNumberOfArguments:
result = "wrong number of arguments"
of AmbiguousCall:
let a = n[2].sym
let b = n[3].sym
var args = "("
for i in 1..<wrongNode.len:
if i > 1: args.add(", ")
args.add(typeToString(wrongNode[i].typ))
args.add(")")
result = "ambiguous call; both $1 and $2 match for: $3" % [
getProcHeader(config, a),
getProcHeader(config, b),
args]
|