gdjn  Diff

Differences From Artifact [bd52030fd5]:

To Artifact [56067a22ef]:


     1         -(defn api-parse [src]
     2         -	{} #TODO parse json
     3         -	)
            1  +# [ʞ] tool/api-compile.janet
            2  +#  ~ lexi hale <lexi@hale.su>
            3  +#  🄯 AGPLv3
            4  +#  ? gathers the core modules and assembles
            5  +#    them into a unified image that can be
            6  +#    loaded into gdjn.
            7  +
            8  +(def- extern-table  @{})
            9  +(def  marshal-map   @{})
           10  +(def  unmarshal-map @{})
           11  +
           12  +(defn- safe-to-export? [x]
           13  +	# only ref types and explicit exportscan be safely replaced;
           14  +	# otherwise e.g. any use of the string "release" will be
           15  +	# replaced by the value of janet/build when loaded
           16  +	# yes this is lunacy i don't know why they did it like that
           17  +	(or (function?  x)
           18  +		(cfunction? x)
           19  +		(table?     x)
           20  +		(array?     x)
           21  +		(buffer?    x)
           22  +		(has-key? extern-table x)))
           23  +
           24  +(defn- register-env [env]
           25  +	(merge-into extern-table
           26  +		(tabseq [[sym data] :pairs env
           27  +				 :when (has-key?         data :value)
           28  +				 :when (safe-to-export? (data :value))]
           29  +						(data :value) sym)))
           30  +
           31  +
           32  +# provide symbol mapping for core values &
           33  +# external symbols provided by gdjn
           34  +(register-env root-env)
           35  +
           36  +(def modules '[
           37  +	core prim json
           38  +])
           39  +
           40  +# here we iterate over the core modules and load each
           41  +# in turn. the array *gd-api-map* is assembled at
           42  +# compile-time and then used by the init function at
           43  +# runtime to enumerate and install the core modules.
           44  +# when core modules use a primitive, they declare their
           45  +# own *gd-api-map* which maps gensyms to the name of
           46  +# the desired primitive.
           47  +(def *gd-api-map* @{})
           48  +(defn- install [name env]
           49  +	(put *gd-api-map* name env)
           50  +	(when (has-key? env '*gd-api-map*)
           51  +		(def gdmap (get-in env ['*gd-api-map* :value]))
           52  +		(loop [[val key] :pairs gdmap
           53  +			   :when (safe-to-export? val)]
           54  +			(def sym (symbol '-val- (bxor (hash name) (hash val))))
           55  +			(put   marshal-map val sym)
           56  +			(put unmarshal-map sym val))
           57  +		(merge-into extern-table gdmap)))
           58  +
           59  +(defn- log [fmt & r]
           60  +	(:write stderr "(api-compile) "
           61  +			(string/format fmt ;r)))
           62  +(defn- install-mod [name]
           63  +	(log "loading library %s\n" name)
           64  +	(def env (require (string "/lib/" name)))
           65  +	(install (string name) env))
           66  +
           67  +(each m modules (install-mod m))
     4     68   
     5         -(defn api-gen [api]
     6         -	@{} #TODO gen bindings
     7         -	)
           69  +# macro implementations can be provided directly in janet
           70  +# and incorporated into the API image without having to
           71  +# implement anything beyond the primitive API in C
     8     72   
     9         -(defn main [_ api-src api-dest & _]
    10         -	(def api
    11         -		(with [fd (file/open api-src :r)]
    12         -			(api-gen (api-parse (:read fd :all)))))
    13         -	(def api-bin (make-image api))
    14         -	(with [fd (file/open api-dest :w)]
    15         -		(:write fd api-bin))
    16         -	0)
           73  +# this function is exported as part of api.jimage.
           74  +# it will be called from vm.c after initializing
           75  +# the primitive bindings
           76  +(defn init []
           77  +	(print "beginning merge")
           78  +	(merge-into module/cache *gd-api-map*)
           79  +	(print "api loaded"))
    17     80   
           81  +# this is the build-time entry point, which does
           82  +# the work of assembling the modules and marshalling
           83  +# them out. it is not exported
           84  +(defn main [_ out-path]
           85  +	(def env @{})
           86  +	(each sym '[init marshal-map unmarshal-map]
           87  +		(put env sym ((curenv) sym)))
           88  +	(let [blob (marshal env extern-table)]
           89  +		(with [fd (file/open out-path :w)]
           90  +			(:write fd blob)))
           91  +	0)