11use proc_macro:: TokenStream ;
22use quote:: quote;
33use std:: ops:: Neg ;
4- use syn:: { Expr , ExprLit , ExprUnary , Lit , parse_macro_input} ;
4+ use syn:: { Error , Expr , ExprLit , ExprUnary , Lit , Result , parse_macro_input} ;
55
66use lambdaworks_math:: {
77 field:: {
@@ -23,16 +23,17 @@ pub fn felt(input: TokenStream) -> TokenStream {
2323 let expr = parse_macro_input ! ( input as Expr ) ;
2424
2525 match handle_expr ( & expr) {
26- HandleExprOutput :: ComptimeFelt ( field_element) => {
26+ Ok ( HandleExprOutput :: ComptimeFelt ( field_element) ) => {
2727 generate_const_felt_token_stream_from_lambda_field_element ( field_element) . into ( )
2828 }
29- HandleExprOutput :: Runtime => quote ! {
29+ Ok ( HandleExprOutput :: Runtime ) => quote ! {
3030 match Felt :: try_from( #expr) {
3131 Ok ( f) => f,
32- Err ( _ ) => panic!( "Invalid Felt value" ) ,
32+ Err ( e ) => panic!( "Invalid Felt value: {}" , e ) ,
3333 }
3434 }
3535 . into ( ) ,
36+ Err ( error) => error. to_compile_error ( ) . into ( ) ,
3637 }
3738}
3839
@@ -54,19 +55,27 @@ fn generate_const_felt_token_stream_from_lambda_field_element(
5455 }
5556}
5657
57- fn handle_expr ( expr : & syn:: Expr ) -> HandleExprOutput {
58+ fn handle_expr ( expr : & syn:: Expr ) -> Result < HandleExprOutput > {
5859 match expr {
5960 Expr :: Lit ( expr_lit) => match & expr_lit. lit {
60- Lit :: Bool ( lit_bool) => HandleExprOutput :: ComptimeFelt ( match lit_bool. value ( ) {
61- false => LambdaFieldElement :: from_hex_unchecked ( "0x0" ) ,
62- true => LambdaFieldElement :: from_hex_unchecked ( "0x1" ) ,
63- } ) ,
61+ Lit :: Bool ( lit_bool) => Ok ( HandleExprOutput :: ComptimeFelt ( match lit_bool. value ( ) {
62+ false => LambdaFieldElement :: from ( & UnsignedInteger :: from_u64 ( 0 ) ) ,
63+ true => LambdaFieldElement :: from ( & UnsignedInteger :: from_u64 ( 1 ) ) ,
64+ } ) ) ,
6465
6566 Lit :: Int ( lit_int) => {
66- let value = lit_int. base10_parse :: < u128 > ( ) . unwrap ( ) ;
67+ let value = match lit_int. base10_parse :: < u128 > ( ) {
68+ Ok ( v) => v,
69+ Err ( _) => {
70+ return Err ( Error :: new_spanned (
71+ lit_int,
72+ "Invalid integer literal for Felt conversion" ,
73+ ) ) ;
74+ }
75+ } ;
6776
68- HandleExprOutput :: ComptimeFelt ( LambdaFieldElement :: from ( & UnsignedInteger :: from (
69- value,
77+ Ok ( HandleExprOutput :: ComptimeFelt ( LambdaFieldElement :: from (
78+ & UnsignedInteger :: from ( value) ,
7079 ) ) )
7180 }
7281
@@ -83,64 +92,103 @@ fn handle_expr(expr: &syn::Expr) -> HandleExprOutput {
8392 UnsignedInteger :: from_hex ( value) . map ( |x| LambdaFieldElement :: from ( & x) )
8493 } else {
8594 UnsignedInteger :: from_dec_str ( value) . map ( |x| LambdaFieldElement :: from ( & x) )
86- }
87- . unwrap ( ) ;
95+ } ;
96+
97+ let lfe = match lfe {
98+ Ok ( v) => v,
99+ Err ( _) => {
100+ return Err ( Error :: new_spanned (
101+ lit_str,
102+ "Invalid string literal for Felt conversion" ,
103+ ) ) ;
104+ }
105+ } ;
88106
89- HandleExprOutput :: ComptimeFelt ( if is_neg { lfe. neg ( ) } else { lfe } )
107+ Ok ( HandleExprOutput :: ComptimeFelt ( if is_neg {
108+ lfe. neg ( )
109+ } else {
110+ lfe
111+ } ) )
90112 }
91113
92114 Lit :: ByteStr ( lit_byte_str) => {
93115 let bytes = lit_byte_str. value ( ) ;
94116
95- assert ! (
96- bytes. len( ) <= 31 ,
97- "Short string must be at most 31 characters"
98- ) ;
99- assert ! (
100- bytes. is_ascii( ) ,
101- "Short string must contain only ASCII characters"
102- ) ;
117+ if bytes. len ( ) > 31 {
118+ return Err ( Error :: new_spanned (
119+ lit_byte_str,
120+ "Short string must be at most 31 characters" ,
121+ ) ) ;
122+ }
123+
124+ if !bytes. is_ascii ( ) {
125+ return Err ( Error :: new_spanned (
126+ lit_byte_str,
127+ "Short string must contain only ASCII characters" ,
128+ ) ) ;
129+ }
103130
104131 let mut buffer = [ 0u8 ; 32 ] ;
105132 buffer[ ( 32 - bytes. len ( ) ) ..] . copy_from_slice ( & bytes) ;
106133
107- HandleExprOutput :: ComptimeFelt ( LambdaFieldElement :: from_bytes_be ( & buffer) . unwrap ( ) )
134+ match LambdaFieldElement :: from_bytes_be ( & buffer) {
135+ Ok ( field_element) => Ok ( HandleExprOutput :: ComptimeFelt ( field_element) ) ,
136+ Err ( _) => Err ( Error :: new_spanned (
137+ lit_byte_str,
138+ "Failed to convert byte string to Felt" ,
139+ ) ) ,
140+ }
108141 }
142+
109143 Lit :: Char ( lit_char) => {
110144 let char = lit_char. value ( ) ;
111145
112- assert ! ( char . is_ascii( ) , "Only ASCII characters are handled" ) ;
146+ if !char. is_ascii ( ) {
147+ return Err ( Error :: new_spanned (
148+ lit_char,
149+ "Only ASCII characters are supported" ,
150+ ) ) ;
151+ }
113152
114153 let mut buffer = [ 0u8 ] ;
115154 char. encode_utf8 ( & mut buffer) ;
116155
117- HandleExprOutput :: ComptimeFelt ( LambdaFieldElement :: from ( & UnsignedInteger :: from (
118- u16:: from ( buffer[ 0 ] ) ,
156+ Ok ( HandleExprOutput :: ComptimeFelt ( LambdaFieldElement :: from (
157+ & UnsignedInteger :: from ( u16:: from ( buffer[ 0 ] ) ) ,
119158 ) ) )
120159 }
160+
121161 Lit :: Byte ( lit_byte) => {
122162 let char = lit_byte. value ( ) ;
123163
124- HandleExprOutput :: ComptimeFelt ( LambdaFieldElement :: from ( & UnsignedInteger :: from (
125- u16:: from ( char) ,
164+ Ok ( HandleExprOutput :: ComptimeFelt ( LambdaFieldElement :: from (
165+ & UnsignedInteger :: from ( u16:: from ( char) ) ,
126166 ) ) )
127167 }
128- Lit :: CStr ( _) | Lit :: Float ( _) | Lit :: Verbatim ( _) => panic ! ( "Literal type not handled" ) ,
168+
169+ Lit :: CStr ( _) | Lit :: Float ( _) | Lit :: Verbatim ( _) => {
170+ Err ( Error :: new_spanned ( expr_lit, "Unsupported literal type" ) )
171+ }
172+
129173 // `Lit` is a non-exhaustive enum
130- _ => panic ! ( "Unkown literal type. Not handled" ) ,
174+ _ => Err ( Error :: new_spanned ( expr_lit , "Unknown literal type" ) ) ,
131175 } ,
132176
133177 // Negative (`-`) prefixed values
178+ // Can be used before any other expression
134179 Expr :: Unary ( ExprUnary {
135180 attrs : _attrs,
136181 op : syn:: UnOp :: Neg ( _) ,
137182 expr,
138- } ) => match handle_expr ( expr) {
183+ } ) => match handle_expr ( expr) ? {
139184 HandleExprOutput :: ComptimeFelt ( field_element) => {
140- HandleExprOutput :: ComptimeFelt ( field_element. neg ( ) )
185+ Ok ( HandleExprOutput :: ComptimeFelt ( field_element. neg ( ) ) )
141186 }
142- HandleExprOutput :: Runtime => HandleExprOutput :: Runtime ,
187+ HandleExprOutput :: Runtime => Ok ( HandleExprOutput :: Runtime ) ,
143188 } ,
189+
190+ // Oposite (`!`) prefixed values
191+ // Can only be used before literal bool expression and any runtime expression where it is semanticaly valid
144192 Expr :: Unary ( ExprUnary {
145193 attrs : _attrs,
146194 op : syn:: UnOp :: Not ( _) ,
@@ -149,16 +197,17 @@ fn handle_expr(expr: &syn::Expr) -> HandleExprOutput {
149197 Expr :: Lit ( ExprLit {
150198 lit : Lit :: Bool ( lit_bool) ,
151199 ..
152- } ) => HandleExprOutput :: ComptimeFelt ( match lit_bool. value ( ) {
153- false => LambdaFieldElement :: from_hex_unchecked ( "0x1" ) ,
154- true => LambdaFieldElement :: from_hex_unchecked ( "0x0" ) ,
155- } ) ,
156- Expr :: Lit ( _) => panic ! (
157- "The `!` logical inversion operatior in only allowed before booleans in literal expressions."
158- ) ,
159- _ => HandleExprOutput :: Runtime ,
200+ } ) => Ok ( HandleExprOutput :: ComptimeFelt ( match lit_bool. value ( ) {
201+ false => LambdaFieldElement :: from ( & UnsignedInteger :: from_u64 ( 1 ) ) ,
202+ true => LambdaFieldElement :: from ( & UnsignedInteger :: from_u64 ( 0 ) ) ,
203+ } ) ) ,
204+ Expr :: Lit ( _) => Err ( Error :: new_spanned (
205+ expr,
206+ "The `!` logical inversion operator is only allowed before booleans in literal expressions" ,
207+ ) ) ,
208+ _ => Ok ( HandleExprOutput :: Runtime ) ,
160209 } ,
161210
162- _ => HandleExprOutput :: Runtime ,
211+ _ => Ok ( HandleExprOutput :: Runtime ) ,
163212 }
164213}
0 commit comments