@@ -23,6 +23,127 @@ use crate::vm::types::{TraitIdentifier, TupleTypeSignature, TypeSignature, Value
23
23
24
24
pub type CheckResult < T > = Result < T , CheckError > ;
25
25
26
+ /// What kind of syntax binding was found to be in error?
27
+ #[ derive( Debug , PartialEq , Clone , Copy ) ]
28
+ pub enum SyntaxBindingErrorType {
29
+ Let ,
30
+ Eval ,
31
+ TupleCons ,
32
+ }
33
+
34
+ impl fmt:: Display for SyntaxBindingErrorType {
35
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
36
+ write ! ( f, "{}" , & self . message( ) )
37
+ }
38
+ }
39
+
40
+ impl DiagnosableError for SyntaxBindingErrorType {
41
+ fn message ( & self ) -> String {
42
+ match & self {
43
+ Self :: Let => "Let-binding" . to_string ( ) ,
44
+ Self :: Eval => "Function argument definition" . to_string ( ) ,
45
+ Self :: TupleCons => "Tuple constructor" . to_string ( ) ,
46
+ }
47
+ }
48
+
49
+ fn suggestion ( & self ) -> Option < String > {
50
+ None
51
+ }
52
+ }
53
+
54
+ /// Syntax binding error types
55
+ #[ derive( Debug , PartialEq ) ]
56
+ pub enum SyntaxBindingError {
57
+ /// binding list item is not a list
58
+ NotList ( SyntaxBindingErrorType , usize ) ,
59
+ /// binding list item has an invalid length (e.g. not 2)
60
+ InvalidLength ( SyntaxBindingErrorType , usize ) ,
61
+ /// binding name is not an atom
62
+ NotAtom ( SyntaxBindingErrorType , usize ) ,
63
+ }
64
+
65
+ impl fmt:: Display for SyntaxBindingError {
66
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
67
+ write ! ( f, "{self:?}" )
68
+ }
69
+ }
70
+
71
+ impl DiagnosableError for SyntaxBindingError {
72
+ fn message ( & self ) -> String {
73
+ match & self {
74
+ Self :: NotList ( err_type, item_index) => {
75
+ let item_no = item_index + 1 ;
76
+ format ! ( "{err_type} item #{item_no} is not a list" , )
77
+ }
78
+ Self :: InvalidLength ( err_type, item_index) => {
79
+ let item_no = item_index + 1 ;
80
+ format ! ( "{err_type} item #{item_no} is not a two-element list" , )
81
+ }
82
+ Self :: NotAtom ( err_type, item_index) => {
83
+ let item_no = item_index + 1 ;
84
+ format ! ( "{err_type} item #{item_no}'s name is not an atom" , )
85
+ }
86
+ }
87
+ }
88
+
89
+ fn suggestion ( & self ) -> Option < String > {
90
+ None
91
+ }
92
+ }
93
+
94
+ impl SyntaxBindingError {
95
+ /// Helper constructor for NotList(SyntaxBindingErrorType::Let, item_no)
96
+ pub fn let_binding_not_list ( item_no : usize ) -> Self {
97
+ Self :: NotList ( SyntaxBindingErrorType :: Let , item_no)
98
+ }
99
+
100
+ /// Helper constructor for InvalidLength(SyntaxBindingErrorType::Let, item_no)
101
+ pub fn let_binding_invalid_length ( item_no : usize ) -> Self {
102
+ Self :: InvalidLength ( SyntaxBindingErrorType :: Let , item_no)
103
+ }
104
+
105
+ /// Helper constructor for NotAtom(SyntaxBindingErrorType::Let, item_no)
106
+ pub fn let_binding_not_atom ( item_no : usize ) -> Self {
107
+ Self :: NotAtom ( SyntaxBindingErrorType :: Let , item_no)
108
+ }
109
+
110
+ /// Helper constructor for NotList(SyntaxBindingErrorType::Eval, item_no)
111
+ pub fn eval_binding_not_list ( item_no : usize ) -> Self {
112
+ Self :: NotList ( SyntaxBindingErrorType :: Eval , item_no)
113
+ }
114
+
115
+ /// Helper constructor for InvalidLength(SyntaxBindingErrorType::Eval, item_no)
116
+ pub fn eval_binding_invalid_length ( item_no : usize ) -> Self {
117
+ Self :: InvalidLength ( SyntaxBindingErrorType :: Eval , item_no)
118
+ }
119
+
120
+ /// Helper constructor for NotAtom(SyntaxBindingErrorType::Eval, item_no)
121
+ pub fn eval_binding_not_atom ( item_no : usize ) -> Self {
122
+ Self :: NotAtom ( SyntaxBindingErrorType :: Eval , item_no)
123
+ }
124
+
125
+ /// Helper constructor for NotList(SyntaxBindingErrorType::TupleCons, item_no)
126
+ pub fn tuple_cons_not_list ( item_no : usize ) -> Self {
127
+ Self :: NotList ( SyntaxBindingErrorType :: TupleCons , item_no)
128
+ }
129
+
130
+ /// Helper constructor for InvalidLength(SyntaxBindingErrorType::TupleCons, item_no)
131
+ pub fn tuple_cons_invalid_length ( item_no : usize ) -> Self {
132
+ Self :: InvalidLength ( SyntaxBindingErrorType :: TupleCons , item_no)
133
+ }
134
+
135
+ /// Helper constructor for NotAtom(SyntaxBindingErrorType::TupleCons, item_no)
136
+ pub fn tuple_cons_not_atom ( item_no : usize ) -> Self {
137
+ Self :: NotAtom ( SyntaxBindingErrorType :: TupleCons , item_no)
138
+ }
139
+ }
140
+
141
+ impl From < SyntaxBindingError > for CheckErrors {
142
+ fn from ( e : SyntaxBindingError ) -> Self {
143
+ Self :: BadSyntaxBinding ( e)
144
+ }
145
+ }
146
+
26
147
#[ derive( Debug , PartialEq ) ]
27
148
pub enum CheckErrors {
28
149
// cost checker errors
@@ -101,8 +222,7 @@ pub enum CheckErrors {
101
222
ExpectedTuple ( TypeSignature ) ,
102
223
NoSuchTupleField ( String , TupleTypeSignature ) ,
103
224
EmptyTuplesNotAllowed ,
104
- BadTupleConstruction ,
105
- TupleExpectsPairs ,
225
+ BadTupleConstruction ( String ) ,
106
226
107
227
// variables
108
228
NoSuchDataVariable ( String ) ,
@@ -152,8 +272,7 @@ pub enum CheckErrors {
152
272
BadLetSyntax ,
153
273
154
274
// generic binding syntax
155
- BadSyntaxBinding ,
156
- BadSyntaxExpectedListOfPairs ,
275
+ BadSyntaxBinding ( SyntaxBindingError ) ,
157
276
158
277
MaxContextDepthReached ,
159
278
UndefinedFunction ( String ) ,
@@ -240,6 +359,32 @@ impl CheckError {
240
359
self . diagnostic . spans = exprs. iter ( ) . map ( |e| e. span ( ) . clone ( ) ) . collect ( ) ;
241
360
self . expressions . replace ( exprs. to_vec ( ) ) ;
242
361
}
362
+
363
+ pub fn with_expression ( err : CheckErrors , expr : & SymbolicExpression ) -> Self {
364
+ let mut r = Self :: new ( err) ;
365
+ r. set_expression ( expr) ;
366
+ r
367
+ }
368
+ }
369
+
370
+ impl From < ( SyntaxBindingError , & SymbolicExpression ) > for CheckError {
371
+ fn from ( e : ( SyntaxBindingError , & SymbolicExpression ) ) -> Self {
372
+ Self :: with_expression ( CheckErrors :: BadSyntaxBinding ( e. 0 ) , e. 1 )
373
+ }
374
+ }
375
+
376
+ impl From < ( CheckErrors , & SymbolicExpression ) > for CheckError {
377
+ fn from ( e : ( CheckErrors , & SymbolicExpression ) ) -> Self {
378
+ let mut ce = Self :: new ( e. 0 ) ;
379
+ ce. set_expression ( e. 1 ) ;
380
+ ce
381
+ }
382
+ }
383
+
384
+ impl From < ( CheckErrors , & SymbolicExpression ) > for CheckErrors {
385
+ fn from ( e : ( CheckErrors , & SymbolicExpression ) ) -> Self {
386
+ e. 0
387
+ }
243
388
}
244
389
245
390
impl fmt:: Display for CheckErrors {
@@ -362,7 +507,6 @@ impl DiagnosableError for CheckErrors {
362
507
CheckErrors :: MemoryBalanceExceeded ( a, b) => format ! ( "contract execution cost exceeded memory budget: {a:?} > {b:?}" ) ,
363
508
CheckErrors :: InvalidTypeDescription => "supplied type description is invalid" . into ( ) ,
364
509
CheckErrors :: EmptyTuplesNotAllowed => "tuple types may not be empty" . into ( ) ,
365
- CheckErrors :: BadSyntaxExpectedListOfPairs => "bad syntax: function expects a list of pairs to bind names, e.g., ((name-0 a) (name-1 b) ...)" . into ( ) ,
366
510
CheckErrors :: UnknownTypeName ( name) => format ! ( "failed to parse type: '{name}'" ) ,
367
511
CheckErrors :: ValueTooLarge => "created a type which was greater than maximum allowed value size" . into ( ) ,
368
512
CheckErrors :: ValueOutOfBounds => "created a type which value size was out of defined bounds" . into ( ) ,
@@ -390,8 +534,7 @@ impl DiagnosableError for CheckErrors {
390
534
CheckErrors :: BadTupleFieldName => "invalid tuple field name" . into ( ) ,
391
535
CheckErrors :: ExpectedTuple ( type_signature) => format ! ( "expecting tuple, found '{type_signature}'" ) ,
392
536
CheckErrors :: NoSuchTupleField ( field_name, tuple_signature) => format ! ( "cannot find field '{field_name}' in tuple '{tuple_signature}'" ) ,
393
- CheckErrors :: BadTupleConstruction => "invalid tuple syntax, expecting list of pair" . into ( ) ,
394
- CheckErrors :: TupleExpectsPairs => "invalid tuple syntax, expecting pair" . into ( ) ,
537
+ CheckErrors :: BadTupleConstruction ( message) => format ! ( "invalid tuple syntax: {message}" ) ,
395
538
CheckErrors :: NoSuchDataVariable ( var_name) => format ! ( "use of unresolved persisted variable '{var_name}'" ) ,
396
539
CheckErrors :: BadTransferSTXArguments => "STX transfer expects an int amount, from principal, to principal" . into ( ) ,
397
540
CheckErrors :: BadTransferFTArguments => "transfer expects an int amount, from principal, to principal" . into ( ) ,
@@ -428,7 +571,7 @@ impl DiagnosableError for CheckErrors {
428
571
CheckErrors :: MaxLengthOverflow => format ! ( "expecting a value <= {}" , u32 :: MAX ) ,
429
572
CheckErrors :: BadLetSyntax => "invalid syntax of 'let'" . into ( ) ,
430
573
CheckErrors :: CircularReference ( references) => format ! ( "detected circular reference: ({})" , references. join( ", " ) ) ,
431
- CheckErrors :: BadSyntaxBinding => "invalid syntax binding" . into ( ) ,
574
+ CheckErrors :: BadSyntaxBinding ( binding_error ) => format ! ( "invalid syntax binding: {}" , & binding_error . message ( ) ) ,
432
575
CheckErrors :: MaxContextDepthReached => "reached depth limit" . into ( ) ,
433
576
CheckErrors :: UndefinedVariable ( var_name) => format ! ( "use of unresolved variable '{var_name}'" ) ,
434
577
CheckErrors :: UndefinedFunction ( var_name) => format ! ( "use of unresolved function '{var_name}'" ) ,
@@ -476,9 +619,6 @@ impl DiagnosableError for CheckErrors {
476
619
477
620
fn suggestion ( & self ) -> Option < String > {
478
621
match & self {
479
- CheckErrors :: BadSyntaxBinding => {
480
- Some ( "binding syntax example: ((supply int) (ttl int))" . into ( ) )
481
- }
482
622
CheckErrors :: BadLetSyntax => Some (
483
623
"'let' syntax example: (let ((supply 1000) (ttl 60)) <next-expression>)" . into ( ) ,
484
624
) ,
0 commit comments