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