@@ -264,3 +264,244 @@ impl NodeValue {
264264 }
265265 }
266266}
267+
268+ #[ cfg( test) ]
269+ mod test {
270+
271+ use crate :: {
272+ compiler:: compiled_prog:: PreResolvedCodePoint , types:: CelByteCode , ByteCode , CelValue ,
273+ ProgramDetails ,
274+ } ;
275+
276+ use super :: { CompiledProg , NodeValue } ;
277+
278+ mod helpers {
279+ use super :: CelValue ;
280+ use std:: ops:: Add as _;
281+
282+ pub fn add_values ( values : Vec < CelValue > ) -> CelValue {
283+ values. into_iter ( ) . reduce ( |v1, v2| v1 + v2) . unwrap ( )
284+ }
285+
286+ pub fn add_2 ( val1 : & CelValue , val2 : & CelValue ) -> Option < CelValue > {
287+ Some ( val1. clone ( ) . add ( val2. clone ( ) ) )
288+ }
289+ }
290+
291+ #[ test]
292+ fn node_basic ( ) {
293+ let a = NodeValue :: ConstExpr ( CelValue :: Int ( 32 ) ) ;
294+ let b = NodeValue :: Bytecode (
295+ [
296+ ByteCode :: Push ( 0 . into ( ) ) ,
297+ ByteCode :: Push ( 3 . into ( ) ) ,
298+ ByteCode :: Mul ,
299+ ]
300+ . into_iter ( )
301+ . collect ( ) ,
302+ ) ;
303+
304+ assert ! ( a. is_const( ) ) ;
305+ assert ! ( !b. is_const( ) ) ;
306+
307+ let a_bc = a. into_bytecode ( ) ;
308+ assert_eq ! ( a_bc. len( ) , 1 ) ;
309+ assert_eq ! (
310+ a_bc[ 0 ] ,
311+ PreResolvedCodePoint :: Bytecode ( ByteCode :: Push ( 32 . into( ) ) )
312+ ) ;
313+ }
314+
315+ #[ test]
316+ fn compprog_basic ( ) {
317+ let details = ProgramDetails :: new ( ) ;
318+ let node = NodeValue :: ConstExpr ( 0 . into ( ) ) ;
319+
320+ fn is_empty ( prog : CompiledProg ) -> bool {
321+ return prog. is_const ( ) || prog. bytecode_len ( ) == 0 ;
322+ }
323+
324+ // test the basic contructors
325+ assert ! ( is_empty( CompiledProg :: new( node. clone( ) , details. clone( ) ) ) ) ;
326+ assert ! ( is_empty( CompiledProg :: empty( ) ) ) ;
327+ assert ! ( is_empty( CompiledProg :: from_node( CompiledProg :: empty( ) ) ) ) ;
328+ assert ! ( is_empty( CompiledProg :: with_bytecode( CelByteCode :: new( ) ) ) ) ;
329+ assert ! ( is_empty( CompiledProg :: with_code_points( Vec :: new( ) ) ) ) ;
330+
331+ assert ! ( CompiledProg :: empty( ) . details( ) . params( ) . is_empty( ) ) ;
332+ let mut const_prog = CompiledProg :: with_const ( 42 . into ( ) ) ;
333+ assert ! ( const_prog. is_const( ) ) ;
334+ assert ! ( const_prog. bytecode_len( ) == 1 ) ;
335+
336+ const_prog. append_if_bytecode ( [ PreResolvedCodePoint :: Bytecode ( ByteCode :: Dup ) ] ) ;
337+ assert ! ( const_prog. is_const( ) ) ;
338+ assert ! ( const_prog. bytecode_len( ) == 1 ) ;
339+
340+ let ( node, details) = const_prog. into_parts ( ) ;
341+
342+ if let NodeValue :: ConstExpr ( inner) = node {
343+ assert_eq ! ( inner, 42 . into( ) ) ;
344+ } else {
345+ assert ! ( false ) ;
346+ }
347+
348+ assert ! ( details. params( ) . is_empty( ) ) ;
349+
350+ let mut bc_prog = CompiledProg :: empty ( ) ;
351+ assert ! ( !bc_prog. is_const( ) ) ;
352+ assert ! ( bc_prog. bytecode_len( ) == 0 ) ;
353+ bc_prog. append_if_bytecode ( [ PreResolvedCodePoint :: Bytecode ( ByteCode :: Dup ) ] ) ;
354+ assert ! ( bc_prog. bytecode_len( ) == 1 ) ;
355+ }
356+
357+ #[ test]
358+ fn from_child_2_nonconst ( ) {
359+ let c1 = CompiledProg :: with_bytecode ( [ ByteCode :: Push ( 2 . into ( ) ) ] . into_iter ( ) . collect ( ) ) ;
360+ let c2 = CompiledProg :: with_bytecode ( [ ByteCode :: Push ( 5 . into ( ) ) ] . into_iter ( ) . collect ( ) ) ;
361+
362+ let c3 = CompiledProg :: from_children2_w_bytecode_cannone (
363+ c1,
364+ c2,
365+ vec ! [ ByteCode :: Add ] ,
366+ helpers:: add_2,
367+ ) ;
368+
369+ assert ! ( !c3. is_const( ) ) ;
370+ assert_eq ! ( c3. bytecode_len( ) , 3 ) ;
371+
372+ assert_eq ! (
373+ c3. into_unresolved_bytecode( ) . resolve( ) ,
374+ [
375+ ByteCode :: Push ( 2 . into( ) ) ,
376+ ByteCode :: Push ( 5 . into( ) ) ,
377+ ByteCode :: Add
378+ ]
379+ . into_iter( )
380+ . collect( )
381+ )
382+ }
383+
384+ #[ test]
385+ fn from_child_2_const ( ) {
386+ let c1 = CompiledProg :: with_const ( 2 . into ( ) ) ;
387+ let c2 = CompiledProg :: with_const ( 5 . into ( ) ) ;
388+
389+ let c3 = CompiledProg :: from_children2_w_bytecode_cannone (
390+ c1. clone ( ) ,
391+ c2. clone ( ) ,
392+ vec ! [ ByteCode :: Add ] ,
393+ helpers:: add_2,
394+ ) ;
395+
396+ assert ! ( c3. is_const( ) ) ;
397+ assert_eq ! ( c3. clone( ) . const_val( ) , 7 . into( ) ) ;
398+ assert_eq ! (
399+ c3. into_unresolved_bytecode( ) . resolve( ) ,
400+ [ ByteCode :: Push ( 7 . into( ) ) , ] . into_iter( ) . collect( )
401+ ) ;
402+
403+ let c4 = CompiledProg :: from_children2_w_bytecode_cannone (
404+ c1. clone ( ) ,
405+ c2. clone ( ) ,
406+ vec ! [ ByteCode :: Add ] ,
407+ |_v1, _v2| None ,
408+ ) ;
409+
410+ assert ! ( !c4. is_const( ) ) ;
411+ assert_eq ! ( c4. bytecode_len( ) , 3 ) ;
412+ assert_eq ! (
413+ c4. into_unresolved_bytecode( ) . resolve( ) ,
414+ [
415+ ByteCode :: Push ( 2 . into( ) ) ,
416+ ByteCode :: Push ( 5 . into( ) ) ,
417+ ByteCode :: Add
418+ ]
419+ . into_iter( )
420+ . collect( )
421+ )
422+ }
423+
424+ #[ test]
425+ fn from_children_w_bytecode_nonconst ( ) {
426+ let c1 = CompiledProg :: with_bytecode ( [ ByteCode :: Push ( 2 . into ( ) ) ] . into_iter ( ) . collect ( ) ) ;
427+ let c2 = CompiledProg :: with_bytecode ( [ ByteCode :: Push ( 5 . into ( ) ) ] . into_iter ( ) . collect ( ) ) ;
428+
429+ let c3 = CompiledProg :: from_children_w_bytecode (
430+ vec ! [ c1, c2] ,
431+ vec ! [ ByteCode :: Add ] ,
432+ helpers:: add_values,
433+ ) ;
434+
435+ assert ! ( !c3. is_const( ) ) ;
436+ assert_eq ! ( c3. bytecode_len( ) , 3 ) ;
437+
438+ assert_eq ! (
439+ c3. into_unresolved_bytecode( ) . resolve( ) ,
440+ [
441+ ByteCode :: Push ( 2 . into( ) ) ,
442+ ByteCode :: Push ( 5 . into( ) ) ,
443+ ByteCode :: Add
444+ ]
445+ . into_iter( )
446+ . collect( )
447+ )
448+ }
449+
450+ #[ test]
451+ fn from_children_w_bytecode_const ( ) {
452+ let c1 = CompiledProg :: with_const ( 2 . into ( ) ) ;
453+ let c2 = CompiledProg :: with_const ( 5 . into ( ) ) ;
454+
455+ let c3 = CompiledProg :: from_children_w_bytecode (
456+ vec ! [ c1, c2] ,
457+ vec ! [ ByteCode :: Add ] ,
458+ helpers:: add_values,
459+ ) ;
460+
461+ assert ! ( c3. is_const( ) ) ;
462+ assert_eq ! ( c3. clone( ) . const_val( ) , 7 . into( ) ) ;
463+ assert_eq ! (
464+ c3. into_unresolved_bytecode( ) . resolve( ) ,
465+ [ ByteCode :: Push ( 7 . into( ) ) , ] . into_iter( ) . collect( )
466+ ) ;
467+ }
468+
469+ #[ test]
470+ fn consume_child ( ) {
471+ let c = CompiledProg :: with_const ( 5 . into ( ) ) ;
472+
473+ let p = CompiledProg :: empty ( ) ;
474+
475+ let r = p. consume_child ( c) ;
476+
477+ assert ! ( !r. is_const( ) ) ;
478+ assert_eq ! ( r. bytecode_len( ) , 1 )
479+ }
480+
481+ #[ test]
482+ fn program ( ) {
483+ let p = CompiledProg :: with_bytecode (
484+ [
485+ ByteCode :: Push ( CelValue :: from_ident ( "foo" ) ) ,
486+ ByteCode :: Push ( 4 . into ( ) ) ,
487+ ByteCode :: Mul ,
488+ ]
489+ . into_iter ( )
490+ . collect ( ) ,
491+ )
492+ . add_ident ( "foo" )
493+ . into_program ( "foo * 4" . to_owned ( ) ) ;
494+
495+ assert_eq ! ( p. params( ) , vec![ "foo" ] ) ;
496+ assert_eq ! (
497+ p. bytecode( ) ,
498+ & ( [
499+ ByteCode :: Push ( CelValue :: from_ident( "foo" ) ) ,
500+ ByteCode :: Push ( 4 . into( ) ) ,
501+ ByteCode :: Mul
502+ ]
503+ . into_iter( )
504+ . collect:: <CelByteCode >( ) )
505+ ) ;
506+ }
507+ }
0 commit comments