5
5
6
6
import basilisp ._pyast as ast
7
7
import basilisp .lang .keyword as kw
8
+ import basilisp .lang .map as lmap
8
9
from basilisp .lang .compiler .nodes import Node
9
- from basilisp .lang .interfaces import ISeq
10
+ from basilisp .lang .interfaces import IExceptionInfo , IMeta , IPersistentMap , ISeq
11
+ from basilisp .lang .obj import lrepr
12
+ from basilisp .lang .reader import READER_COL_KW , READER_LINE_KW
10
13
from basilisp .lang .typing import LispForm
11
14
15
+ _PHASE = kw .keyword ("phase" )
16
+ _FORM = kw .keyword ("form" )
17
+ _LISP_AST = kw .keyword ("lisp_ast" )
18
+ _PY_AST = kw .keyword ("py_ast" )
19
+ _LINE = kw .keyword ("line" )
20
+ _COL = kw .keyword ("col" )
21
+
12
22
13
23
class CompilerPhase (Enum ):
14
24
ANALYZING = kw .keyword ("analyzing" )
@@ -17,10 +27,47 @@ class CompilerPhase(Enum):
17
27
COMPILING_PYTHON = kw .keyword ("compiling-python" )
18
28
19
29
20
- @attr .s (auto_attribs = True , slots = True )
21
- class CompilerException (Exception ):
30
+ @attr .s (auto_attribs = True , frozen = True , slots = True )
31
+ class _loc :
32
+ line : Optional [int ] = None
33
+ col : Optional [int ] = None
34
+
35
+ def __bool__ (self ):
36
+ return self .line is not None and self .col is not None
37
+
38
+
39
+ @attr .s (auto_attribs = True , slots = True , str = False )
40
+ class CompilerException (IExceptionInfo ):
22
41
msg : str
23
42
phase : CompilerPhase
24
43
form : Union [LispForm , None , ISeq ] = None
25
44
lisp_ast : Optional [Node ] = None
26
45
py_ast : Optional [ast .AST ] = None
46
+
47
+ @property
48
+ def data (self ) -> IPersistentMap :
49
+ d = {_PHASE : self .phase .value }
50
+ loc = None
51
+ if self .form is not None :
52
+ d [_FORM ] = self .form
53
+ loc = (
54
+ _loc (
55
+ self .form .meta .val_at (READER_LINE_KW ),
56
+ self .form .meta .val_at (READER_COL_KW ),
57
+ )
58
+ if isinstance (self .form , IMeta ) and self .form .meta
59
+ else None
60
+ )
61
+ if self .lisp_ast is not None : # pragma: no cover
62
+ d [_LISP_AST ] = self .lisp_ast
63
+ loc = loc or _loc (self .lisp_ast .env .line , self .lisp_ast .env .col )
64
+ if self .py_ast is not None : # pragma: no cover
65
+ d [_PY_AST ] = self .py_ast
66
+ loc = loc or _loc (self .py_ast .lineno , self .py_ast .col_offset )
67
+ if loc : # pragma: no cover
68
+ d [_LINE ] = loc .line
69
+ d [_COL ] = loc .col
70
+ return lmap .map (d )
71
+
72
+ def __str__ (self ):
73
+ return f"{ self .msg } { lrepr (self .data )} "
0 commit comments