123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100open!Core_kernelopen!ImportmoduleQ=structleteval="eval"|>Symbol.internandinteractive="interactive"|>Symbol.internandlambda="lambda"|>Symbol.internandlet_="let"|>Symbol.internandprogn="progn"|>Symbol.internandquote="quote"|>Symbol.internandread_from_whole_string="read-from-whole-string"|>Symbol.internandthingatpt="thingatpt"|>Symbol.internmoduleA=structletoptional="&optional"|>Symbol.internletrest="&rest"|>Symbol.internendendincludeValue.Make_subtype(structletname="form"lethere=[%here]letis_in_subtype_=trueend)letstrings=s|>Value.of_utf8_bytes|>of_value_exnletsymbols=s|>Symbol.to_value|>of_value_exnletinti=i|>Value.of_int_exn|>of_value_exnletevalt=Symbol.funcall1Q.eval(t|>to_value)leteval_it=ignore(evalt:Value.t)letread=Feature.requireQ.thingatpt;funstring->Symbol.funcall1Q.read_from_whole_string(string|>Value.of_utf8_bytes)|>of_value_exn;;leteval_stringstring=eval(readstring)letlistts=Value.list(ts:tlist:>Value.tlist)|>of_value_exnletnil=list[]letqvalue=Value.list[Symbol.to_valueQ.quote;value]letquotevalue=qvalue|>of_value_exnletprognts=list(symbolQ.progn::ts)letlet_bindingsbody=Value.list[Q.let_|>Symbol.to_value;bindings|>List.map~f:(fun(v,e)->Value.list[v|>Symbol.to_value;e|>to_value])|>Value.list;body|>to_value]|>of_value_exn;;letlambda=letsome=Option.someinfun?docstring?interactive?optional_args?rest_arghere~args~body->(matchdocstringwith|None->()|Somedocstring->ifString.memdocstring'\000'thenraise_s[%message"docstring contains a NUL byte"(docstring:string)]);letargs=[args;(matchoptional_argswith|None|Some[]->[]|Someoptional_args->Q.A.optional::optional_args);rest_arg|>Option.value_map~default:[]~f:(funrest_arg->[Q.A.rest;rest_arg])]|>List.concat|>(funx->(x:Symbol.tlist:>Value.tlist))|>Value.listinlethere=concat["Implemented at [";here|>Source_code_position.to_string;"]."]inletdocstring=matchdocstringwith|None->here|Somes->lets=String.stripsinconcat[(ifString.is_emptysthen""elseconcat[s;"\n\n"]);here]in[Q.lambda|>Symbol.to_value|>some;args|>some;docstring|>Value.of_utf8_bytes|>some;interactive|>Option.map~f:(funinteractive->Value.list[Q.interactive|>Symbol.to_value;interactive|>Value.of_utf8_bytes]);body|>to_value|>some]|>List.filter_opt|>Value.list|>of_value_exn;;