123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147(* Claude Code
*
* Copyright (C) 2026 Yoann Padioleau
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* (LGPL) as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*)(* See Scheme.mli *)typet=|Intofint|Realoffloat|Boolofbool|Charofint|Strofstring|Symofstring|Nil|Pairoft*t|Vectoroftarray|Structofstring*tlist|ImageofScheme_image.t|Procofproc|Voidandproc=Primofstring|Closureoflambda*env|Contofkont|Makeofstring*int|Getofstring*int*string|Isofstringandloc=intandenv=(string*loc)listandexpr={desc:desc;span:Sexpr.span}anddesc=|Quoteoft|Varofstring|Lambdaoflambda|Ifofexpr*expr*expr|Setofstring*expr|Appofexpr*exprlist|Seqofexprlist|Defineofstring*expr|Define_structofstring*stringlist|Big_bangofexpr*(string*expr)listandlambda={params:stringlist;rest:stringoption;locals:stringlist;body:exprlist;name:string}andkont=|Halt|K_ifofexpr*expr*env*kont|K_appoftlist*exprlist*env*Sexpr.span*kont|K_setofloc*kont|K_seqofexprlist*env*kont|K_defineofstring*kont|K_big_bangoftlist*(string*expr)list*stringlist*env*Sexpr.span*konttypestyle=Write|Constructor(*****************************************************************************)(* Lists *)(*****************************************************************************)letlist(xs:tlist):t=List.fold_right(funxrest->Pair(x,rest))xsNilletto_list(v:t):tlistoption=letrecgovacc=matchvwithNil->Some(List.revacc)|Pair(a,d)->god(a::acc)|_->Noneingov[]lettruthy(v:t):bool=v<>Boolfalse(*****************************************************************************)(* Printing *)(*****************************************************************************)(* 1.5, and 2.0 rather than 2: a real prints as one *)letreal(f:float):string=lets=Printf.sprintf"%.15g"finifString.exists(func->c='.'||c='e'||c='n'||c='i')sthenselses^".0"letchar_name(c:int):string=matchcwith32->"space"|10->"newline"|9->"tab"|0->"nul"|_->String.make1(Char.chr(cland255))letproc_name(p:proc):string=matchpwith|Primname->name|Closure(l,_)->l.name|Cont_->"continuation"|Make(s,_)->"make-"^s|Get(s,_,f)->s^"-"^f|Iss->s^"?"letrecprint(style:style)(v:t):string=letp=printstyleinletallxs=String.concat" "(List.mappxs)inmatch(style,v)with|_,Intn->string_of_intn|_,Realf->realf|Write,Boolb->ifbthen"#t"else"#f"|Constructor,Boolb->ifbthen"true"else"false"|_,Charc->"#\\"^char_namec|_,Strs->Printf.sprintf"%S"s|Write,Syms->s|Constructor,Syms->"'"^s|Write,Nil->"()"|Constructor,Nil->"empty"|Write,Pair_->letrecgovacc=matchvwithPair(a,d)->god(pa::acc)|Nil->List.revacc|tail->List.rev(ptail::"."::acc)in"("^String.concat" "(gov[])^")"|Constructor,Pair(a,d)->(matchto_listvwithSomexs->"(list "^allxs^")"|None->"(cons "^pa^" "^pd^")")|Write,Vectorxs->"#("^all(Array.to_listxs)^")"|Constructor,Vectorxs->"(vector "^all(Array.to_listxs)^")"|Write,Struct(name,fields)->"#(struct:"^name^(iffields=[]then""else" "^allfields)^")"|Constructor,Struct(name,fields)->"(make-"^name^(iffields=[]then""else" "^allfields)^")"|Write,Image_->"#<image>"|Constructor,Imagei->Scheme_image.to_stringi|_,Proc(Cont_)->"#<continuation>"|_,Proc(Closure({name="";_},_))->"#<procedure>"|_,Procpr->"#<procedure:"^proc_namepr^">"|_,Void->"#<void>"letdisplay(v:t):string=matchvwithStrs->s|Charc->String.make1(Char.chr(cland255))|_->printWritev(*****************************************************************************)(* Equality, kinds *)(*****************************************************************************)letrecequal(a:t)(b:t):bool=match(a,b)with|Pair(a1,d1),Pair(a2,d2)->equala1a2&&equald1d2|Vectorxs,Vectorys->Array.lengthxs=Array.lengthys&&Array.for_all2equalxsys|Struct(n1,f1),Struct(n2,f2)->n1=n2&&List.lengthf1=List.lengthf2&&List.for_all2equalf1f2(* a procedure is only itself *)|Procp,Procq->p==q|_->a=bletkind(v:t):string=matchvwith|Int_|Real_->"number"|Bool_->"boolean"|Char_->"character"|Str_->"string"|Sym_->"symbol"|Nil|Pair_->"list"|Vector_->"vector"|Struct(name,_)->name|Image_->"image"|Proc_->"procedure"|Void->"void"