Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file St_class.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273(* 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 St_class.mli *)moduleM=St_memorytypeoop=M.oopletf_superclass=0letf_method_dict=1letf_format=2letf_inst_vars=3letf_organization=4letf_name=5letf_category=6letf_class_pool=7letf_comment=8(*****************************************************************************)(* Formats *)(*****************************************************************************)typekind=Fixed|Indexable|Byte_indexable|Float_kind|Method_kindletkinds=[|Fixed;Indexable;Byte_indexable;Float_kind;Method_kind|]letformat(m:M.t)(cls:oop):int*kind=letf=M.int_of(M.fetchmclsf_format)in(flsr3,kinds.(fland7))letencode_format(n:int)(k:kind):int=letk=matchkwithFixed->0|Indexable->1|Byte_indexable->2|Float_kind->3|Method_kind->4in(nlsl3)lork(*****************************************************************************)(* Classes *)(*****************************************************************************)letsuperclass(m:M.t)(cls:oop):oop=M.fetchmclsf_superclassletis_meta(m:M.t)(cls:oop):bool=cls<>M.nil&&M.class_ofmcls=(M.knownm).metaclassletthis_class(m:M.t)(cls:oop):oop=ifis_metamclsthenM.fetchmclsf_nameelseclsletmetaclass(m:M.t)(cls:oop):oop=ifis_metamclsthenclselseM.class_ofmclsletname(m:M.t)(cls:oop):string=ifcls=M.nilthen"nil"elseifis_metamclsthenM.string_ofm(M.fetchm(this_classmcls)f_name)^" class"elseM.string_ofm(M.fetchmclsf_name)letstrings_of_array(m:M.t)(a:oop):stringlist=ifa=M.nilthen[]elseArray.to_list(Array.map(M.string_ofm)(M.fieldsma))letown_inst_var_names(m:M.t)(cls:oop):stringlist=strings_of_arraym(M.fetchmclsf_inst_vars)letrecinst_var_names(m:M.t)(cls:oop):stringlist=ifcls=M.nilthen[]elseinst_var_namesm(superclassmcls)@own_inst_var_namesmclsletcategory(m:M.t)(cls:oop):string=letcls=this_classmclsinletc=M.fetchmclsf_categoryinifc=M.nilthen""elseM.string_ofmcletcomment(m:M.t)(cls:oop):string=letc=M.fetchm(this_classmcls)f_commentinifc=M.nilthen""elseM.string_ofmc(*****************************************************************************)(* Globals *)(*****************************************************************************)letnew_association(m:M.t)(k:oop)(v:oop):oop=M.allocm~cls:(M.knownm).association(M.Pointers[|k;v|])(* the SystemDictionary's one field *)letassociations(m:M.t):ooparray=letsd=(M.knownm).smalltalkinifsd=M.nilthen[||]elseM.fieldsm(M.fetchmsd0)letfind_assoc(m:M.t)(assocs:ooparray)(name:string):oopoption=letsym=M.symbolmnameinArray.find_opt(funa->M.fetchma0=sym)assocsletglobal(m:M.t)(name:string):oopoption=find_assocm(associationsm)nameletdeclare_global(m:M.t)(name:string)(v:oop):oop=matchglobalmnamewith|Somea->M.storema1v;a|None->leta=new_associationm(M.symbolmname)vinletsd=(M.knownm).smalltalkinM.storemsd0(M.new_arraym(Array.append(associationsm)[|a|]));aletglobals(m:M.t):(string*oop)list=Array.to_list(associationsm)|>List.map(funa->(M.string_ofm(M.fetchma0),M.fetchma1))letclasses(m:M.t):ooplist=globalsm|>List.filter(fun(n,v)->(not(M.is_intv))&&v<>M.nil&&is_metam(M.class_ofmv)&&namemv=n)|>List.sort(fun(a,_)(b,_)->compareab)|>List.mapsndletclass_var_names(m:M.t)(cls:oop):stringlist=letpool=M.fetchm(this_classmcls)f_class_poolinifpool=M.nilthen[]elseArray.to_list(M.fieldsmpool)|>List.map(funa->M.string_ofm(M.fetchma0))letrecclass_var(m:M.t)(cls:oop)(name:string):oopoption=ifcls=M.nilthenNoneelseletc=this_classmclsinletpool=M.fetchmcf_class_poolinmatchifpool=M.nilthenNoneelsefind_assocm(M.fieldsmpool)namewith|Somea->Somea|None->class_varm(superclassmc)nameletdefinition(m:M.t)(cls:oop):string=letcls=this_classmclsinletsup=superclassmclsinletn,kind=formatmclsinignoren;letverb=matchkindwith|Indexable->"variableSubclass:"|Byte_indexable->"variableByteSubclass:"|Fixed|Float_kind|Method_kind->"subclass:"inPrintf.sprintf"%s %s #%s\n\tinstanceVariableNames: '%s'\n\tclassVariableNames: '%s'\n\tpoolDictionaries: ''\n\tcategory: '%s'"(ifsup=M.nilthen"nil"elsenamemsup)verb(namemcls)(String.concat" "(own_inst_var_namesmcls))(String.concat" "(class_var_namesmcls))(categorymcls)(*****************************************************************************)(* Methods *)(*****************************************************************************)letdict(m:M.t)(cls:oop):ooparray*ooparray=letd=M.fetchmclsf_method_dictin(M.fieldsm(M.fetchmd0),M.fieldsm(M.fetchmd1))letlocal_method(m:M.t)(cls:oop)(sel:oop):oopoption=letsels,meths=dictmclsinletrecfindi=ifi>=Array.lengthselsthenNoneelseifsels.(i)=selthenSomemeths.(i)elsefind(i+1)infind0letreclookup(m:M.t)(cls:oop)(sel:oop):oopoption=ifcls=M.nilthenNoneelsematchlocal_methodmclsselwithSomemeth->Somemeth|None->lookupm(superclassmcls)selletselectors(m:M.t)(cls:oop):stringlist=letsels,_=dictmclsinArray.to_listsels|>List.map(M.string_ofm)|>List.sortcompareletorganization(m:M.t)(cls:oop):(string*stringlist)list=leto=M.fetchmclsf_organizationinifo=M.nilthen[]elseArray.to_list(M.fieldsmo)|>List.map(funa->(M.string_ofm(M.fetchma0),Array.to_list(M.fieldsm(M.fetchma1))|>List.map(M.string_ofm)))letset_organization(m:M.t)(cls:oop)(org:(string*stringlist)list):unit=letorg=List.filter(fun(_,sels)->sels<>[])orginletassocs=List.map(fun(cat,sels)->new_associationm(M.new_stringmcat)(M.new_arraym(Array.of_list(List.map(M.symbolm)(List.sortcomparesels)))))orginM.storemclsf_organization(M.new_arraym(Array.of_listassocs))letcategories(m:M.t)(cls:oop):stringlist=List.mapfst(organizationmcls)letcategory_selectors(m:M.t)(cls:oop)(cat:string):stringlist=tryList.assoccat(organizationmcls)withNot_found->[]letcategory_of(m:M.t)(cls:oop)(sel:string):stringoption=List.find_map(fun(cat,sels)->ifList.memselselsthenSomecatelseNone)(organizationmcls)letinstall(m:M.t)(cls:oop)(sel:oop)(meth:oop)~(category:string):unit=letd=M.fetchmclsf_method_dictinletsels,meths=dictmclsinletrecfindi=ifi>=Array.lengthselsthenNoneelseifsels.(i)=selthenSomeielsefind(i+1)in(matchfind0with|Somei->meths.(i)<-meth|None->M.storemd0(M.new_arraym(Array.appendsels[|sel|]));M.storemd1(M.new_arraym(Array.appendmeths[|meth|])));lets=M.string_ofmselinletorg=organizationmcls|>List.map(fun(c,sels)->(c,List.filter((<>)s)sels))inletorg=ifList.mem_assoccategoryorgthenList.map(fun(c,sels)->ifc=categorythen(c,s::sels)else(c,sels))orgelseorg@[(category,[s])]inset_organizationmclsorg(*****************************************************************************)(* Defining a class *)(*****************************************************************************)letnew_method_dict(m:M.t):oop=M.allocm~cls:(M.knownm).method_dictionary(M.Pointers[|M.new_arraym[||];M.new_arraym[||]|])letsubclasses(m:M.t)(cls:oop):ooplist=List.filter(func->superclassmc=cls)(classesm)letis_class(m:M.t)(v:oop):bool=(not(M.is_intv))&&v<>M.nil&&is_metam(M.class_ofmv)(* the named fields of a class's instances, its superclass's first *)letrecrefresh_format(m:M.t)(cls:oop):unit=letsup=superclassmclsinletinherited=ifsup=M.nilthen0elsefst(formatmsup)inlet_,kind=formatmclsinM.storemclsf_format(M.of_int(encode_format(inherited+List.length(own_inst_var_namesmcls))kind));List.iter(refresh_formatm)(subclassesmcls)letdefine_class(m:M.t)~(superclass:oop)~(name:string)~(kind:kind)~(inst_vars:stringlist)~(class_vars:stringlist)~(category:string):oop*bool=letk=M.knownminletexisting=matchglobalmnamewithSomeawhenis_classm(M.fetchma1)->Some(M.fetchma1)|_->Noneinletcls,meta,changed=matchexistingwith|Somecls->letchanged=own_inst_var_namesmcls<>inst_vars||superclass<>M.fetchmclsf_superclass||snd(formatmcls)<>kindin(cls,M.class_ofmcls,changed)|None->letmeta=M.allocm~cls:k.metaclass(M.Pointers(Array.make6M.nil))inletcls=M.allocm~cls:meta(M.Pointers(Array.make9M.nil))inignore(declare_globalmnamecls);(cls,meta,false)inletf=M.fieldsmclsandmf=M.fieldsmmetainf.(f_superclass)<-superclass;iff.(f_method_dict)=M.nilthenf.(f_method_dict)<-new_method_dictm;f.(f_format)<-M.of_int(encode_format0kind);f.(f_inst_vars)<-M.new_arraym(Array.of_list(List.map(M.new_stringm)inst_vars));f.(f_name)<-M.symbolmname;f.(f_category)<-M.new_stringmcategory;(* the class variables: the old ones keep their values *)letold=iff.(f_class_pool)=M.nilthen[||]elseM.fieldsmf.(f_class_pool)inletpool=List.map(funv->matchArray.find_opt(funa->M.string_ofm(M.fetchma0)=v)oldwith|Somea->a|None->new_associationm(M.symbolmv)M.nil)class_varsinf.(f_class_pool)<-(ifpool=[]thenM.nilelseM.new_arraym(Array.of_listpool));(* the metaclass: its superclass is the superclass's metaclass, or
* Class at the top ("Object class superclass == Class") *)mf.(f_superclass)<-(ifsuperclass=M.nilthenmatchglobalm"Class"withSomea->M.fetchma1|None->M.nilelseM.class_ofmsuperclass);ifmf.(f_method_dict)=M.nilthenmf.(f_method_dict)<-new_method_dictm;mf.(f_format)<-M.of_int(encode_format9Fixed);mf.(f_inst_vars)<-M.new_arraym[||];mf.(f_name)<-cls;refresh_formatmcls;(cls,changed)letremove(m:M.t)(cls:oop)(sel:oop):unit=letd=M.fetchmclsf_method_dictinletsels,meths=dictmclsinletkeep=List.filter(fun(s,_)->s<>sel)(List.combine(Array.to_listsels)(Array.to_listmeths))inM.storemd0(M.new_arraym(Array.of_list(List.mapfstkeep)));M.storemd1(M.new_arraym(Array.of_list(List.mapsndkeep)));lets=M.string_ofmselinset_organizationmcls(organizationmcls|>List.map(fun(c,sels)->(c,List.filter((<>)s)sels)))