@@ -6,7 +6,8 @@ use crate::{
6
6
} ,
7
7
typechecker:: {
8
8
info:: TypeInfo ,
9
- types:: { Primitive , Type } ,
9
+ scope:: { ResolvedName , ScopeRef } ,
10
+ types:: { Type , TypeDefinition } ,
10
11
} ,
11
12
} ;
12
13
use std:: {
@@ -105,36 +106,43 @@ fn check_roto_type(
105
106
let mut roto_ty = type_info. resolve ( roto_ty) ;
106
107
107
108
if let Type :: IntVar ( _) = roto_ty {
108
- roto_ty = Type :: Primitive ( Primitive :: I32 ) ;
109
+ roto_ty = Type :: named ( "i32" , Vec :: new ( ) ) ;
109
110
}
110
111
111
112
match rust_ty. description {
112
113
TypeDescription :: Leaf => {
113
- let expected_roto = match rust_ty. type_id {
114
- x if x == BOOL => Type :: Primitive ( Primitive :: Bool ) ,
115
- x if x == U8 => Type :: Primitive ( Primitive :: U8 ) ,
116
- x if x == U16 => Type :: Primitive ( Primitive :: U16 ) ,
117
- x if x == U32 => Type :: Primitive ( Primitive :: U32 ) ,
118
- x if x == U64 => Type :: Primitive ( Primitive :: U64 ) ,
119
- x if x == I8 => Type :: Primitive ( Primitive :: I8 ) ,
120
- x if x == I16 => Type :: Primitive ( Primitive :: I16 ) ,
121
- x if x == I32 => Type :: Primitive ( Primitive :: I32 ) ,
122
- x if x == I64 => Type :: Primitive ( Primitive :: I64 ) ,
123
- x if x == UNIT => Type :: Primitive ( Primitive :: Unit ) ,
124
- x if x == ASN => Type :: Primitive ( Primitive :: Asn ) ,
125
- x if x == IPADDR => Type :: Primitive ( Primitive :: IpAddr ) ,
126
- x if x == PREFIX => Type :: Primitive ( Primitive :: Prefix ) ,
127
- x if x == STRING => Type :: Primitive ( Primitive :: String ) ,
114
+ let expected_name = match rust_ty. type_id {
115
+ x if x == BOOL => "bool" ,
116
+ x if x == U8 => "u8" ,
117
+ x if x == U16 => "u16" ,
118
+ x if x == U32 => "u32" ,
119
+ x if x == U64 => "u64" ,
120
+ x if x == I8 => "i8" ,
121
+ x if x == I16 => "i16" ,
122
+ x if x == I32 => "i32" ,
123
+ x if x == I64 => "i64" ,
124
+ x if x == UNIT => " Unit" ,
125
+ x if x == ASN => " Asn" ,
126
+ x if x == IPADDR => " IpAddr" ,
127
+ x if x == PREFIX => " Prefix" ,
128
+ x if x == STRING => " String" ,
128
129
_ => panic ! ( ) ,
129
130
} ;
131
+ let expected_roto = Type :: named ( expected_name, Vec :: new ( ) ) ;
130
132
if expected_roto == roto_ty {
131
133
Ok ( ( ) )
132
134
} else {
133
135
Err ( error_message)
134
136
}
135
137
}
136
138
TypeDescription :: Val ( ty) => {
137
- let Type :: BuiltIn ( _, id) = roto_ty else {
139
+ let Type :: Name ( type_name) = roto_ty else {
140
+ return Err ( error_message) ;
141
+ } ;
142
+
143
+ let TypeDefinition :: Runtime ( _, id) =
144
+ type_info. resolve_type_name ( & type_name)
145
+ else {
138
146
return Err ( error_message) ;
139
147
} ;
140
148
@@ -147,18 +155,48 @@ fn check_roto_type(
147
155
TypeDescription :: ConstPtr ( _) => Err ( error_message) ,
148
156
TypeDescription :: MutPtr ( _) => Err ( error_message) , // TODO: actually check this
149
157
TypeDescription :: Verdict ( rust_accept, rust_reject) => {
150
- let Type :: Verdict ( roto_accept , roto_reject ) = & roto_ty else {
158
+ let Type :: Name ( type_name ) = & roto_ty else {
151
159
return Err ( error_message) ;
152
160
} ;
161
+
162
+ if type_name. name
163
+ != ( ResolvedName {
164
+ scope : ScopeRef :: GLOBAL ,
165
+ ident : "Verdict" . into ( ) ,
166
+ } )
167
+ {
168
+ return Err ( error_message) ;
169
+ }
170
+
171
+ let [ roto_accept, roto_reject] = & type_name. arguments [ ..] else {
172
+ return Err ( error_message) ;
173
+ } ;
174
+
153
175
check_roto_type ( registry, type_info, rust_accept, roto_accept) ?;
154
176
check_roto_type ( registry, type_info, rust_reject, roto_reject) ?;
155
177
Ok ( ( ) )
156
178
}
157
- // We don't do options and results, we should hint towards verdict
158
- // when using them.
159
- TypeDescription :: Option ( _) | TypeDescription :: Result ( _, _) => {
160
- Err ( error_message)
179
+ TypeDescription :: Option ( rust_ty) => {
180
+ let Type :: Name ( type_name) = & roto_ty else {
181
+ return Err ( error_message) ;
182
+ } ;
183
+
184
+ if type_name. name
185
+ != ( ResolvedName {
186
+ scope : ScopeRef :: GLOBAL ,
187
+ ident : "Optional" . into ( ) ,
188
+ } )
189
+ {
190
+ return Err ( error_message) ;
191
+ }
192
+
193
+ let [ roto_ty] = & type_name. arguments [ ..] else {
194
+ return Err ( error_message) ;
195
+ } ;
196
+ check_roto_type ( registry, type_info, rust_ty, roto_ty)
161
197
}
198
+ // We don't do results, we should hint towards verdict when using them.
199
+ TypeDescription :: Result ( _, _) => Err ( error_message) ,
162
200
}
163
201
}
164
202
@@ -172,18 +210,20 @@ fn check_roto_type(
172
210
///
173
211
/// This trait is implemented on tuples of various sizes.
174
212
pub trait RotoParams {
213
+ type Transformed ;
175
214
/// This type but with [`Reflect::AsParam`] applied to each element.
176
215
type AsParams ;
177
216
217
+ fn transform ( self ) -> Self :: Transformed ;
218
+
178
219
/// Convert to `Self::AsParams`.
179
- fn as_params ( & mut self ) -> Self :: AsParams ;
220
+ fn as_params ( transformed : & mut Self :: Transformed ) -> Self :: AsParams ;
180
221
181
222
/// Check whether these parameters match a parameter list from Roto.
182
223
fn check (
183
224
type_info : & mut TypeInfo ,
184
225
ty : & [ Type ] ,
185
226
) -> Result < ( ) , FunctionRetrievalError > ;
186
-
187
227
/// Call a function pointer as if it were a function with these parameters.
188
228
///
189
229
/// This is _extremely_ unsafe, do not pass this arbitrary pointers and
@@ -214,14 +254,18 @@ macro_rules! params {
214
254
#[ allow( unused_variables) ]
215
255
#[ allow( unused_mut) ]
216
256
impl <$( $t, ) * > RotoParams for ( $( $t, ) * )
217
- where
218
- $( $t: Reflect , ) *
219
- {
257
+ where $( $t: Reflect , ) * {
258
+ type Transformed = ( $( $t:: Transformed , ) * ) ;
220
259
type AsParams = ( $( $t:: AsParam , ) * ) ;
221
260
222
- fn as_params ( & mut self ) -> Self :: AsParams {
261
+ fn transform ( self ) -> Self :: Transformed {
223
262
let ( $( $t, ) * ) = self ;
224
- return ( $( $t. as_param( ) , ) * ) ;
263
+ return ( $( $t. transform( ) , ) * ) ;
264
+ }
265
+
266
+ fn as_params( transformed: & mut Self :: Transformed ) -> Self :: AsParams {
267
+ let ( $( $t, ) * ) = transformed;
268
+ return ( $( $t:: as_param( $t) , ) * ) ;
225
269
}
226
270
227
271
fn check(
@@ -246,21 +290,24 @@ macro_rules! params {
246
290
Ok ( ( ) )
247
291
}
248
292
249
- unsafe fn invoke<Ctx : ' static , Return : Reflect >( mut self , ctx: & mut Ctx , func_ptr: * const u8 , return_by_ref: bool ) -> Return {
250
- let ( $( $t, ) * ) = self . as_params( ) ;
293
+ unsafe fn invoke<Ctx : ' static , Return : Reflect >( self , ctx: & mut Ctx , func_ptr: * const u8 , return_by_ref: bool ) -> Return {
294
+ let mut transformed = <Self as RotoParams >:: transform( self ) ;
295
+ let ( $( $t, ) * ) = <Self as RotoParams >:: as_params( & mut transformed) ;
251
296
252
297
// We forget values that we pass into Roto. The script is responsible
253
298
// for cleaning them op. Forgetting copy types does nothing, but that's
254
299
// fine.
255
300
#[ allow( forgetting_copy_types) ]
256
- std:: mem:: forget( self ) ;
301
+ std:: mem:: forget( transformed ) ;
257
302
if return_by_ref {
258
303
let func_ptr = unsafe {
259
- std:: mem:: transmute:: <* const u8 , fn ( * mut Return , * mut Ctx , $( $t:: AsParam ) ,* ) -> ( ) >( func_ptr)
304
+ std:: mem:: transmute:: <* const u8 , fn ( * mut Return :: Transformed , * mut Ctx , $( $t:: AsParam ) ,* ) -> ( ) >( func_ptr)
260
305
} ;
261
- let mut ret = MaybeUninit :: <Return >:: uninit( ) ;
306
+ let mut ret = MaybeUninit :: <Return :: Transformed >:: uninit( ) ;
262
307
func_ptr( ret. as_mut_ptr( ) , ctx as * mut Ctx , $( $t) ,* ) ;
263
- unsafe { ret. assume_init( ) }
308
+ let transformed_ret = unsafe { ret. assume_init( ) } ;
309
+ let ret: Return = Return :: untransform( transformed_ret) ;
310
+ ret
264
311
} else {
265
312
let func_ptr = unsafe {
266
313
std:: mem:: transmute:: <* const u8 , fn ( * mut Ctx , $( $t:: AsParam ) ,* ) -> Return >( func_ptr)
0 commit comments