@@ -106,12 +106,31 @@ pub fn lisp2json(expression: &str) -> Result<Value, String> {
106106 // - @byte-vector: {"*type/byte-vector*: "deadbeef0000" }
107107 // - @float-vector: {"*type/float-vector*": [3.2, 8.6, 0.1]}
108108 // - @hash-table: {"*type/hash-table*": [["a", 6], [53, 199]]}
109+ // - @quoted: {"*type/quoted*": [["a", 6], [53, 199]]}
110+
111+ let mut owned_expr = None ;
112+ let expr = {
113+ let trimmed = expression. trim_start ( ) ;
114+ if let Some ( rest) = trimmed. strip_prefix ( '\'' ) {
115+ let rest = rest. trim_start ( ) ;
116+ if rest. is_empty ( ) {
117+ return Err ( "Empty quoted expression" . to_string ( ) ) ;
118+ }
119+ let mut wrapped = String :: from ( "(quote " ) ;
120+ wrapped. push_str ( rest) ;
121+ wrapped. push ( ')' ) ;
122+ owned_expr = Some ( wrapped) ;
123+ owned_expr. as_deref ( ) . expect ( "quote wrapper missing" )
124+ } else {
125+ expression
126+ }
127+ } ;
109128
110129 unsafe {
111130 let sc: * mut s7_scheme = s7_init ( ) ;
112131
113132 // Parse the expression without evaluating it
114- let c_expr = CString :: new ( expression ) . unwrap_or_else ( |_| CString :: new ( "()" ) . unwrap ( ) ) ;
133+ let c_expr = CString :: new ( expr ) . unwrap_or_else ( |_| CString :: new ( "()" ) . unwrap ( ) ) ;
115134 let input_port = s7_open_input_string ( sc, c_expr. as_ptr ( ) ) ;
116135 let s7_obj = s7_read ( sc, input_port) ;
117136 s7_close_input_port ( sc, input_port) ;
@@ -530,21 +549,37 @@ unsafe fn s7_obj_to_json(sc: *mut s7_scheme, obj: s7_pointer) -> Result<Value, S
530549 } else if s7_is_pair ( obj) {
531550 // Check if it's a quote form first
532551 let car = s7_car ( obj) ;
552+ if s7_is_syntax ( car) {
553+ let car_str = obj2str ( sc, car) ;
554+ if car_str == "#_quote" {
555+ let cdr = s7_cdr ( obj) ;
556+ if s7_is_pair ( cdr) && s7_is_null ( sc, s7_cdr ( cdr) ) {
557+ let quoted_expr = s7_car ( cdr) ;
558+ let mut special_type = Map :: new ( ) ;
559+ special_type. insert (
560+ "*type/quoted*" . to_string ( ) ,
561+ s7_obj_to_json ( sc, quoted_expr) ?,
562+ ) ;
563+ return Ok ( Value :: Object ( special_type) ) ;
564+ }
565+ }
566+ }
533567 if s7_is_symbol ( car) {
534568 let symbol_name_ptr = s7_symbol_name ( car) ;
535569 if !symbol_name_ptr. is_null ( ) {
536570 let symbol_name = CStr :: from_ptr ( symbol_name_ptr) . to_string_lossy ( ) ;
537571
538572 if symbol_name == "quote" {
539- // Handle quote form: convert (quote expr) to ["quote", expr]
573+ // Handle quote form: convert (quote expr) to {"*type/quoted*": < expr>}
540574 let cdr = s7_cdr ( obj) ;
541575 if s7_is_pair ( cdr) && s7_is_null ( sc, s7_cdr ( cdr) ) {
542- // It's a proper quote form: (quote expr)
543576 let quoted_expr = s7_car ( cdr) ;
544- let mut array = Vec :: new ( ) ;
545- array. push ( Value :: String ( "quote" . to_string ( ) ) ) ;
546- array. push ( s7_obj_to_json ( sc, quoted_expr) ?) ;
547- return Ok ( Value :: Array ( array) ) ;
577+ let mut special_type = Map :: new ( ) ;
578+ special_type. insert (
579+ "*type/quoted*" . to_string ( ) ,
580+ s7_obj_to_json ( sc, quoted_expr) ?,
581+ ) ;
582+ return Ok ( Value :: Object ( special_type) ) ;
548583 }
549584 }
550585 }
@@ -639,6 +674,31 @@ unsafe fn s7_obj_to_json(sc: *mut s7_scheme, obj: s7_pointer) -> Result<Value, S
639674 // This is a simplified approach - we'd need to iterate through the hash table
640675 special_type. insert ( "*type/hash-table*" . to_string ( ) , Value :: Array ( pairs) ) ;
641676 Ok ( Value :: Object ( special_type) )
677+ } else if s7_is_syntax ( obj) {
678+ // Fallback for syntax objects (e.g., nested quote shorthand).
679+ let expr = obj2str ( sc, obj) ;
680+ let trimmed = expr. trim_start ( ) ;
681+ let quoted_inner = if let Some ( rest) = trimmed. strip_prefix ( '\'' ) {
682+ let rest = rest. trim_start ( ) ;
683+ if rest. is_empty ( ) {
684+ return Err ( "Empty quoted expression" . to_string ( ) ) ;
685+ }
686+ rest
687+ } else if let Some ( rest) = trimmed. strip_prefix ( "(quote " ) {
688+ let rest = rest. trim_end ( ) ;
689+ if let Some ( rest) = rest. strip_suffix ( ')' ) {
690+ rest. trim ( )
691+ } else {
692+ return Err ( "Malformed quote syntax" . to_string ( ) ) ;
693+ }
694+ } else {
695+ return Err ( format ! ( "Unsupported syntax object: {}" , expr) ) ;
696+ } ;
697+
698+ let quoted_json = lisp2json ( quoted_inner) ?;
699+ let mut special_type = Map :: new ( ) ;
700+ special_type. insert ( "*type/quoted*" . to_string ( ) , quoted_json) ;
701+ Ok ( Value :: Object ( special_type) )
642702 } else {
643703 // For debugging: let's see what type this actually is
644704 let type_info = if s7_is_procedure ( obj) {
@@ -713,6 +773,12 @@ unsafe fn json_to_s7_obj(sc: *mut s7_scheme, json: &Value) -> Result<s7_pointer,
713773 }
714774 return Ok ( vector) ;
715775 }
776+ if let Some ( value) = obj. get ( "*type/quoted*" ) {
777+ let quoted = json_to_s7_obj ( sc, value) ?;
778+ let quote_sym = s7_make_symbol ( sc, c"quote" . as_ptr ( ) ) ;
779+ let quoted_list = s7_cons ( sc, quoted, s7_nil ( sc) ) ;
780+ return Ok ( s7_cons ( sc, quote_sym, quoted_list) ) ;
781+ }
716782 if let Some ( Value :: String ( hex) ) = obj. get ( "*type/byte-vector*" ) {
717783 let bytes: Result < Vec < u8 > , ParseIntError > = ( 0 ..hex. len ( ) )
718784 . step_by ( 2 )
0 commit comments