@@ -5,12 +5,22 @@ use std::rc::Rc;
55
66use mruby_compiler2_sys:: MRubyCompiler2Context ;
77use mrubyedge:: yamrb:: value:: RObject ;
8+ use mrubyedge:: yamrb:: vm:: VM ;
89
910fn main ( ) { }
1011
1112/// Execute Ruby script and return the result as Rc<RObject>
1213/// Returns None if compilation or execution fails
1314fn eval_ruby_script ( text : & str ) -> Option < Rc < RObject > > {
15+ eval_ruby_script_with_setup ( text, |_| { } )
16+ }
17+
18+ /// Execute Ruby script with VM setup callback
19+ /// The callback can be used to set global variables before execution
20+ fn eval_ruby_script_with_setup < F > ( text : & str , setup : F ) -> Option < Rc < RObject > >
21+ where
22+ F : FnOnce ( & mut VM ) ,
23+ {
1424 let mut context = unsafe { MRubyCompiler2Context :: new ( ) } ;
1525
1626 // Compile the Ruby script
@@ -35,14 +45,18 @@ fn eval_ruby_script(text: &str) -> Option<Rc<RObject>> {
3545 let mut vm = mrubyedge:: yamrb:: vm:: VM :: open ( & mut rite) ;
3646 mrubyedge_math:: init_math ( & mut vm) ;
3747
48+ // Call setup callback to configure VM (e.g., set global variables)
49+ setup ( & mut vm) ;
50+
3851 // Execute the script and handle exceptions
39- match vm. run ( ) {
40- Ok ( r) => Some ( r) ,
41- Err ( e) => {
42- eprintln ! ( "Runtime error: {:?}" , e) ;
43- None
44- }
52+ let result = vm. run ( ) ;
53+ if let Err ( e) = result {
54+ eprintln ! ( "Runtime error: {:?}" , e) ;
55+ return None ;
4556 }
57+ mrubyedge_serde_json:: mrb_json_class_dump ( & mut vm, & [ result. unwrap ( ) ] )
58+ . unwrap_or_else ( |_| RObject :: string ( "null" . to_string ( ) ) . to_refcount_assigned ( ) )
59+ . into ( )
4660}
4761
4862/// Convert C string pointer to Rust &str
@@ -51,56 +65,46 @@ unsafe fn cstr_to_str<'a>(text_ptr: *const c_char) -> &'a str {
5165 c_str. to_str ( ) . unwrap_or ( "" )
5266}
5367
54- // Function called from JavaScript
55- // Receives Ruby script, executes it, and returns integer result
56- #[ unsafe( no_mangle) ]
57- pub extern "C" fn eval_ruby_script_int ( text_ptr : * const c_char ) -> i32 {
58- unsafe {
59- let text = cstr_to_str ( text_ptr) ;
60- match eval_ruby_script ( text) {
61- Some ( result) => ( & * result) . try_into ( ) . unwrap_or ( -1 ) ,
62- None => -1 ,
63- }
64- }
65- }
66-
67- // Receives Ruby script, executes it, and returns float result
68- #[ unsafe( no_mangle) ]
69- pub extern "C" fn eval_ruby_script_float ( text_ptr : * const c_char ) -> f64 {
70- unsafe {
71- let text = cstr_to_str ( text_ptr) ;
72- match eval_ruby_script ( text) {
73- Some ( result) => ( & * result) . try_into ( ) . unwrap_or ( f64:: NAN ) ,
74- None => f64:: NAN ,
75- }
76- }
77- }
68+ // Receives Ruby script, executes it, and returns string result
69+ // Returns a pointer to a null-terminated C string (caller should NOT free it)
70+ // The returned string is valid until the next call to this function
71+ static mut LAST_STRING_RESULT : Option < CString > = None ;
7872
79- // Receives Ruby script, executes it, and returns boolean result (0 or 1)
8073#[ unsafe( no_mangle) ]
81- pub extern "C" fn eval_ruby_script_bool ( text_ptr : * const c_char ) -> i32 {
74+ pub extern "C" fn eval_ruby_script_returning_json ( text_ptr : * const c_char ) -> * const c_char {
8275 unsafe {
8376 let text = cstr_to_str ( text_ptr) ;
8477 match eval_ruby_script ( text) {
8578 Some ( result) => {
86- let b: bool = ( & * result) . try_into ( ) . unwrap_or ( false ) ;
87- if b { 1 } else { 0 }
79+ let s: String = ( & * result) . try_into ( ) . unwrap_or_default ( ) ;
80+ match CString :: new ( s) {
81+ Ok ( cstring) => {
82+ let ptr = cstring. as_ptr ( ) ;
83+ LAST_STRING_RESULT = Some ( cstring) ;
84+ ptr
85+ }
86+ Err ( _) => std:: ptr:: null ( ) ,
87+ }
8888 }
89- None => 0 ,
89+ None => std :: ptr :: null ( ) ,
9090 }
9191 }
9292}
9393
94- // Receives Ruby script, executes it, and returns string result
95- // Returns a pointer to a null-terminated C string (caller should NOT free it)
96- // The returned string is valid until the next call to this function
97- static mut LAST_STRING_RESULT : Option < CString > = None ;
98-
9994#[ unsafe( no_mangle) ]
100- pub extern "C" fn eval_ruby_script_string ( text_ptr : * const c_char ) -> * const c_char {
95+ pub extern "C" fn eval_ruby_script_returning_json1 (
96+ text_ptr : * const c_char ,
97+ arg1_ptr : * const c_char ,
98+ ) -> * const c_char {
10199 unsafe {
102100 let text = cstr_to_str ( text_ptr) ;
103- match eval_ruby_script ( text) {
101+ let arg1 = cstr_to_str ( arg1_ptr) ;
102+ match eval_ruby_script_with_setup ( text, |vm| {
103+ let arg1_str = RObject :: string ( arg1. to_string ( ) ) . to_refcount_assigned ( ) ;
104+ let arg1_json = mrubyedge_serde_json:: mrb_json_class_load ( vm, & [ arg1_str] )
105+ . unwrap_or_else ( |_| RObject :: nil ( ) . to_refcount_assigned ( ) ) ;
106+ vm. globals . insert ( "$arg1" . to_string ( ) , arg1_json) ;
107+ } ) {
104108 Some ( result) => {
105109 let s: String = ( & * result) . try_into ( ) . unwrap_or_default ( ) ;
106110 match CString :: new ( s) {
0 commit comments