errorhandling.nim 2.3 KB

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