@@ -472,6 +472,10 @@ pub fn eval_function_call(
472472 Ok ( Computation :: Continue ( _) ) => Err ( "Function did not return a value" . to_string ( ) ) ,
473473 Ok ( Computation :: Return ( value, _final_env) ) => Ok ( ExpressionResult :: Value ( value) ) ,
474474 Ok ( Computation :: PropagateError ( value, _) ) => Ok ( ExpressionResult :: Propagate ( value) ) ,
475+ Ok ( Computation :: BreakLoop ( _) ) => Err ( "'break' used outside of a loop" . to_string ( ) ) ,
476+ Ok ( Computation :: ContinueLoop ( _) ) => {
477+ Err ( "'continue' used outside of a loop" . to_string ( ) )
478+ }
475479 Err ( e) => Err ( e) ,
476480 }
477481 }
@@ -524,6 +528,256 @@ pub fn eval_function_call(
524528 Ok ( ExpressionResult :: Value ( Expression :: CVoid ) )
525529 }
526530
531+ // input_int([prompt]) -> Integer or error string
532+ "input_int" => {
533+ if let Some ( prompt_expr) = args. get ( 0 ) {
534+ let prompt_val = match eval ( prompt_expr. clone ( ) , env) ? {
535+ ExpressionResult :: Value ( Expression :: CString ( s) ) => {
536+ Expression :: CString ( s)
537+ }
538+ ExpressionResult :: Value ( v) => {
539+ Expression :: CString ( format ! ( "{:?}" , v) )
540+ }
541+ ExpressionResult :: Propagate ( e) => {
542+ return Ok ( ExpressionResult :: Propagate ( e) )
543+ }
544+ } ;
545+ meta_env. map_variable ( "prompt" . to_string ( ) , false , prompt_val) ;
546+ }
547+
548+ let stmt = meta_fn ( & mut meta_env) ;
549+ if let Statement :: Return ( expr) = stmt {
550+ Ok ( ExpressionResult :: Value ( * expr) )
551+ } else {
552+ Err ( "[Runtime Error] input_int builtin did not return a value" . into ( ) )
553+ }
554+ }
555+
556+ // input_real([prompt]) -> Real or error string
557+ "input_real" => {
558+ if let Some ( prompt_expr) = args. get ( 0 ) {
559+ let prompt_val = match eval ( prompt_expr. clone ( ) , env) ? {
560+ ExpressionResult :: Value ( Expression :: CString ( s) ) => {
561+ Expression :: CString ( s)
562+ }
563+ ExpressionResult :: Value ( v) => {
564+ Expression :: CString ( format ! ( "{:?}" , v) )
565+ }
566+ ExpressionResult :: Propagate ( e) => {
567+ return Ok ( ExpressionResult :: Propagate ( e) )
568+ }
569+ } ;
570+ meta_env. map_variable ( "prompt" . to_string ( ) , false , prompt_val) ;
571+ }
572+
573+ let stmt = meta_fn ( & mut meta_env) ;
574+ if let Statement :: Return ( expr) = stmt {
575+ Ok ( ExpressionResult :: Value ( * expr) )
576+ } else {
577+ Err ( "[Runtime Error] input_real builtin did not return a value" . into ( ) )
578+ }
579+ }
580+
581+ // to_string(value) -> String
582+ "to_string" => {
583+ if args. len ( ) != 1 {
584+ return Err (
585+ "[Runtime Error] to_string expects exactly 1 argument" . into ( )
586+ ) ;
587+ }
588+
589+ let val = match eval ( args[ 0 ] . clone ( ) , env) ? {
590+ ExpressionResult :: Value ( v) => v,
591+ ExpressionResult :: Propagate ( e) => {
592+ return Ok ( ExpressionResult :: Propagate ( e) )
593+ }
594+ } ;
595+ meta_env. map_variable ( "value" . to_string ( ) , false , val) ;
596+ let stmt = meta_fn ( & mut meta_env) ;
597+ if let Statement :: Return ( expr) = stmt {
598+ Ok ( ExpressionResult :: Value ( * expr) )
599+ } else {
600+ Err ( "[Runtime Error] to_string builtin did not return a value" . into ( ) )
601+ }
602+ }
603+
604+ // len(value) -> Int or error string
605+ "len" => {
606+ if args. len ( ) != 1 {
607+ return Err ( "[Runtime Error] len expects exactly 1 argument" . into ( ) ) ;
608+ }
609+
610+ let val = match eval ( args[ 0 ] . clone ( ) , env) ? {
611+ ExpressionResult :: Value ( v) => v,
612+ ExpressionResult :: Propagate ( e) => {
613+ return Ok ( ExpressionResult :: Propagate ( e) )
614+ }
615+ } ;
616+
617+ meta_env. map_variable ( "value" . to_string ( ) , false , val) ;
618+ let stmt = meta_fn ( & mut meta_env) ;
619+ if let Statement :: Return ( expr) = stmt {
620+ Ok ( ExpressionResult :: Value ( * expr) )
621+ } else {
622+ Err ( "[Runtime Error] len builtin did not return a value" . into ( ) )
623+ }
624+ }
625+
626+ // print_line(value) -> Unit
627+ "print_line" => {
628+ if args. len ( ) != 1 {
629+ return Err (
630+ "[Runtime Error] print_line expects exactly 1 argument" . into ( )
631+ ) ;
632+ }
633+ let val = match eval ( args[ 0 ] . clone ( ) , env) ? {
634+ ExpressionResult :: Value ( v) => v,
635+ ExpressionResult :: Propagate ( e) => {
636+ return Ok ( ExpressionResult :: Propagate ( e) )
637+ }
638+ } ;
639+ meta_env. map_variable ( "value" . to_string ( ) , false , val) ;
640+ let _ = meta_fn ( & mut meta_env) ;
641+ Ok ( ExpressionResult :: Value ( Expression :: CVoid ) )
642+ }
643+
644+ // join(values, sep) -> String
645+ "join" => {
646+ if args. len ( ) != 2 {
647+ return Err ( "[Runtime Error] join expects exactly 2 arguments" . into ( ) ) ;
648+ }
649+
650+ let values_val = match eval ( args[ 0 ] . clone ( ) , env) ? {
651+ ExpressionResult :: Value ( v) => v,
652+ ExpressionResult :: Propagate ( e) => {
653+ return Ok ( ExpressionResult :: Propagate ( e) )
654+ }
655+ } ;
656+ let sep_val = match eval ( args[ 1 ] . clone ( ) , env) ? {
657+ ExpressionResult :: Value ( v) => v,
658+ ExpressionResult :: Propagate ( e) => {
659+ return Ok ( ExpressionResult :: Propagate ( e) )
660+ }
661+ } ;
662+
663+ meta_env. map_variable ( "values" . to_string ( ) , false , values_val) ;
664+ meta_env. map_variable ( "sep" . to_string ( ) , false , sep_val) ;
665+ let stmt = meta_fn ( & mut meta_env) ;
666+ if let Statement :: Return ( expr) = stmt {
667+ Ok ( ExpressionResult :: Value ( * expr) )
668+ } else {
669+ Err ( "[Runtime Error] join builtin did not return a value" . into ( ) )
670+ }
671+ }
672+
673+ // to_int(value) -> Int or error string
674+ "to_int" => {
675+ if args. len ( ) != 1 {
676+ return Err ( "[Runtime Error] to_int expects exactly 1 argument" . into ( ) ) ;
677+ }
678+
679+ let val = match eval ( args[ 0 ] . clone ( ) , env) ? {
680+ ExpressionResult :: Value ( v) => v,
681+ ExpressionResult :: Propagate ( e) => {
682+ return Ok ( ExpressionResult :: Propagate ( e) )
683+ }
684+ } ;
685+ meta_env. map_variable ( "value" . to_string ( ) , false , val) ;
686+ let stmt = meta_fn ( & mut meta_env) ;
687+ if let Statement :: Return ( expr) = stmt {
688+ Ok ( ExpressionResult :: Value ( * expr) )
689+ } else {
690+ Err ( "[Runtime Error] to_int builtin did not return a value" . into ( ) )
691+ }
692+ }
693+
694+ // to_real(value) -> Real or error string
695+ "to_real" => {
696+ if args. len ( ) != 1 {
697+ return Err ( "[Runtime Error] to_real expects exactly 1 argument" . into ( ) ) ;
698+ }
699+
700+ let val = match eval ( args[ 0 ] . clone ( ) , env) ? {
701+ ExpressionResult :: Value ( v) => v,
702+ ExpressionResult :: Propagate ( e) => {
703+ return Ok ( ExpressionResult :: Propagate ( e) )
704+ }
705+ } ;
706+ meta_env. map_variable ( "value" . to_string ( ) , false , val) ;
707+ let stmt = meta_fn ( & mut meta_env) ;
708+ if let Statement :: Return ( expr) = stmt {
709+ Ok ( ExpressionResult :: Value ( * expr) )
710+ } else {
711+ Err ( "[Runtime Error] to_real builtin did not return a value" . into ( ) )
712+ }
713+ }
714+
715+ // to_string_fixed(value, places) -> String
716+ "to_string_fixed" => {
717+ if args. len ( ) != 2 {
718+ return Err (
719+ "[Runtime Error] to_string_fixed expects exactly 2 arguments"
720+ . into ( ) ,
721+ ) ;
722+ }
723+
724+ let val = match eval ( args[ 0 ] . clone ( ) , env) ? {
725+ ExpressionResult :: Value ( v) => v,
726+ ExpressionResult :: Propagate ( e) => {
727+ return Ok ( ExpressionResult :: Propagate ( e) )
728+ }
729+ } ;
730+ let places = match eval ( args[ 1 ] . clone ( ) , env) ? {
731+ ExpressionResult :: Value ( v) => v,
732+ ExpressionResult :: Propagate ( e) => {
733+ return Ok ( ExpressionResult :: Propagate ( e) )
734+ }
735+ } ;
736+
737+ meta_env. map_variable ( "value" . to_string ( ) , false , val) ;
738+ meta_env. map_variable ( "places" . to_string ( ) , false , places) ;
739+ let stmt = meta_fn ( & mut meta_env) ;
740+ if let Statement :: Return ( expr) = stmt {
741+ Ok ( ExpressionResult :: Value ( * expr) )
742+ } else {
743+ Err (
744+ "[Runtime Error] to_string_fixed builtin did not return a value"
745+ . into ( ) ,
746+ )
747+ }
748+ }
749+
750+ // str_concat(left, right) -> String
751+ "str_concat" => {
752+ if args. len ( ) != 2 {
753+ return Err (
754+ "[Runtime Error] str_concat expects exactly 2 arguments" . into ( )
755+ ) ;
756+ }
757+
758+ let left_val = match eval ( args[ 0 ] . clone ( ) , env) ? {
759+ ExpressionResult :: Value ( v) => v,
760+ ExpressionResult :: Propagate ( e) => {
761+ return Ok ( ExpressionResult :: Propagate ( e) )
762+ }
763+ } ;
764+ let right_val = match eval ( args[ 1 ] . clone ( ) , env) ? {
765+ ExpressionResult :: Value ( v) => v,
766+ ExpressionResult :: Propagate ( e) => {
767+ return Ok ( ExpressionResult :: Propagate ( e) )
768+ }
769+ } ;
770+
771+ meta_env. map_variable ( "left" . to_string ( ) , false , left_val) ;
772+ meta_env. map_variable ( "right" . to_string ( ) , false , right_val) ;
773+ let stmt = meta_fn ( & mut meta_env) ;
774+ if let Statement :: Return ( expr) = stmt {
775+ Ok ( ExpressionResult :: Value ( * expr) )
776+ } else {
777+ Err ( "[Runtime Error] str_concat builtin did not return a value" . into ( ) )
778+ }
779+ }
780+
527781 // open(path, [mode], [content]) -> String ou Unit
528782 "open" => {
529783 if args. is_empty ( ) {
0 commit comments