environments.c 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350
  1. /* Copyright (C) 1999,2000,2001, 2003, 2006, 2008 Free Software Foundation, Inc.
  2. *
  3. * This library is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU Lesser General Public
  5. * License as published by the Free Software Foundation; either
  6. * version 2.1 of the License, or (at your option) any later version.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public
  14. * License along with this library; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. # include <config.h>
  19. #endif
  20. #include "libguile/_scm.h"
  21. #include "libguile/alist.h"
  22. #include "libguile/eval.h"
  23. #include "libguile/gh.h"
  24. #include "libguile/hash.h"
  25. #include "libguile/list.h"
  26. #include "libguile/ports.h"
  27. #include "libguile/smob.h"
  28. #include "libguile/symbols.h"
  29. #include "libguile/vectors.h"
  30. #include "libguile/weaks.h"
  31. #include "libguile/environments.h"
  32. scm_t_bits scm_tc16_environment;
  33. scm_t_bits scm_tc16_observer;
  34. #define DEFAULT_OBARRAY_SIZE 31
  35. SCM scm_system_environment;
  36. /* error conditions */
  37. /*
  38. * Throw an error if symbol is not bound in environment func
  39. */
  40. void
  41. scm_error_environment_unbound (const char *func, SCM env, SCM symbol)
  42. {
  43. /* Dirk:FIXME:: Should throw an environment:unbound type error */
  44. char error[] = "Symbol `~A' not bound in environment `~A'.";
  45. SCM arguments = scm_cons2 (symbol, env, SCM_EOL);
  46. scm_misc_error (func, error, arguments);
  47. }
  48. /*
  49. * Throw an error if func tried to create (define) or remove
  50. * (undefine) a new binding for symbol in env
  51. */
  52. void
  53. scm_error_environment_immutable_binding (const char *func, SCM env, SCM symbol)
  54. {
  55. /* Dirk:FIXME:: Should throw an environment:immutable-binding type error */
  56. char error[] = "Immutable binding in environment ~A (symbol: `~A').";
  57. SCM arguments = scm_cons2 (env, symbol, SCM_EOL);
  58. scm_misc_error (func, error, arguments);
  59. }
  60. /*
  61. * Throw an error if func tried to change an immutable location.
  62. */
  63. void
  64. scm_error_environment_immutable_location (const char *func, SCM env, SCM symbol)
  65. {
  66. /* Dirk:FIXME:: Should throw an environment:immutable-location type error */
  67. char error[] = "Immutable location in environment `~A' (symbol: `~A').";
  68. SCM arguments = scm_cons2 (env, symbol, SCM_EOL);
  69. scm_misc_error (func, error, arguments);
  70. }
  71. /* generic environments */
  72. /* Create an environment for the given type. Dereferencing type twice must
  73. * deliver the initialized set of environment functions. Thus, type will
  74. * also determine the signature of the underlying environment implementation.
  75. * Dereferencing type once will typically deliver the data fields used by the
  76. * underlying environment implementation.
  77. */
  78. SCM
  79. scm_make_environment (void *type)
  80. {
  81. return scm_cell (scm_tc16_environment, (scm_t_bits) type);
  82. }
  83. SCM_DEFINE (scm_environment_p, "environment?", 1, 0, 0,
  84. (SCM obj),
  85. "Return @code{#t} if @var{obj} is an environment, or @code{#f}\n"
  86. "otherwise.")
  87. #define FUNC_NAME s_scm_environment_p
  88. {
  89. return scm_from_bool (SCM_ENVIRONMENT_P (obj));
  90. }
  91. #undef FUNC_NAME
  92. SCM_DEFINE (scm_environment_bound_p, "environment-bound?", 2, 0, 0,
  93. (SCM env, SCM sym),
  94. "Return @code{#t} if @var{sym} is bound in @var{env}, or\n"
  95. "@code{#f} otherwise.")
  96. #define FUNC_NAME s_scm_environment_bound_p
  97. {
  98. SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  99. SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, FUNC_NAME);
  100. return scm_from_bool (SCM_ENVIRONMENT_BOUND_P (env, sym));
  101. }
  102. #undef FUNC_NAME
  103. SCM_DEFINE (scm_environment_ref, "environment-ref", 2, 0, 0,
  104. (SCM env, SCM sym),
  105. "Return the value of the location bound to @var{sym} in\n"
  106. "@var{env}. If @var{sym} is unbound in @var{env}, signal an\n"
  107. "@code{environment:unbound} error.")
  108. #define FUNC_NAME s_scm_environment_ref
  109. {
  110. SCM val;
  111. SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  112. SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, FUNC_NAME);
  113. val = SCM_ENVIRONMENT_REF (env, sym);
  114. if (!SCM_UNBNDP (val))
  115. return val;
  116. else
  117. scm_error_environment_unbound (FUNC_NAME, env, sym);
  118. }
  119. #undef FUNC_NAME
  120. /* This C function is identical to environment-ref, except that if symbol is
  121. * unbound in env, it returns the value SCM_UNDEFINED, instead of signalling
  122. * an error.
  123. */
  124. SCM
  125. scm_c_environment_ref (SCM env, SCM sym)
  126. {
  127. SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, "scm_c_environment_ref");
  128. SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, "scm_c_environment_ref");
  129. return SCM_ENVIRONMENT_REF (env, sym);
  130. }
  131. static SCM
  132. environment_default_folder (SCM proc, SCM symbol, SCM value, SCM tail)
  133. {
  134. return scm_call_3 (proc, symbol, value, tail);
  135. }
  136. SCM_DEFINE (scm_environment_fold, "environment-fold", 3, 0, 0,
  137. (SCM env, SCM proc, SCM init),
  138. "Iterate over all the bindings in @var{env}, accumulating some\n"
  139. "value.\n"
  140. "For each binding in @var{env}, apply @var{proc} to the symbol\n"
  141. "bound, its value, and the result from the previous application\n"
  142. "of @var{proc}.\n"
  143. "Use @var{init} as @var{proc}'s third argument the first time\n"
  144. "@var{proc} is applied.\n"
  145. "If @var{env} contains no bindings, this function simply returns\n"
  146. "@var{init}.\n"
  147. "If @var{env} binds the symbol sym1 to the value val1, sym2 to\n"
  148. "val2, and so on, then this procedure computes:\n"
  149. "@lisp\n"
  150. " (proc sym1 val1\n"
  151. " (proc sym2 val2\n"
  152. " ...\n"
  153. " (proc symn valn\n"
  154. " init)))\n"
  155. "@end lisp\n"
  156. "Each binding in @var{env} will be processed exactly once.\n"
  157. "@code{environment-fold} makes no guarantees about the order in\n"
  158. "which the bindings are processed.\n"
  159. "Here is a function which, given an environment, constructs an\n"
  160. "association list representing that environment's bindings,\n"
  161. "using environment-fold:\n"
  162. "@lisp\n"
  163. " (define (environment->alist env)\n"
  164. " (environment-fold env\n"
  165. " (lambda (sym val tail)\n"
  166. " (cons (cons sym val) tail))\n"
  167. " '()))\n"
  168. "@end lisp")
  169. #define FUNC_NAME s_scm_environment_fold
  170. {
  171. SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  172. SCM_ASSERT (scm_is_true (scm_procedure_p (proc)),
  173. proc, SCM_ARG2, FUNC_NAME);
  174. return SCM_ENVIRONMENT_FOLD (env, environment_default_folder, proc, init);
  175. }
  176. #undef FUNC_NAME
  177. /* This is the C-level analog of environment-fold. For each binding in ENV,
  178. * make the call:
  179. * (*proc) (data, symbol, value, previous)
  180. * where previous is the value returned from the last call to *PROC, or INIT
  181. * for the first call. If ENV contains no bindings, return INIT.
  182. */
  183. SCM
  184. scm_c_environment_fold (SCM env, scm_environment_folder proc, SCM data, SCM init)
  185. {
  186. SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, "scm_c_environment_fold");
  187. return SCM_ENVIRONMENT_FOLD (env, proc, data, init);
  188. }
  189. SCM_DEFINE (scm_environment_define, "environment-define", 3, 0, 0,
  190. (SCM env, SCM sym, SCM val),
  191. "Bind @var{sym} to a new location containing @var{val} in\n"
  192. "@var{env}. If @var{sym} is already bound to another location\n"
  193. "in @var{env} and the binding is mutable, that binding is\n"
  194. "replaced. The new binding and location are both mutable. The\n"
  195. "return value is unspecified.\n"
  196. "If @var{sym} is already bound in @var{env}, and the binding is\n"
  197. "immutable, signal an @code{environment:immutable-binding} error.")
  198. #define FUNC_NAME s_scm_environment_define
  199. {
  200. SCM status;
  201. SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  202. SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, FUNC_NAME);
  203. status = SCM_ENVIRONMENT_DEFINE (env, sym, val);
  204. if (scm_is_eq (status, SCM_ENVIRONMENT_SUCCESS))
  205. return SCM_UNSPECIFIED;
  206. else if (scm_is_eq (status, SCM_ENVIRONMENT_BINDING_IMMUTABLE))
  207. scm_error_environment_immutable_binding (FUNC_NAME, env, sym);
  208. else
  209. abort();
  210. }
  211. #undef FUNC_NAME
  212. SCM_DEFINE (scm_environment_undefine, "environment-undefine", 2, 0, 0,
  213. (SCM env, SCM sym),
  214. "Remove any binding for @var{sym} from @var{env}. If @var{sym}\n"
  215. "is unbound in @var{env}, do nothing. The return value is\n"
  216. "unspecified.\n"
  217. "If @var{sym} is already bound in @var{env}, and the binding is\n"
  218. "immutable, signal an @code{environment:immutable-binding} error.")
  219. #define FUNC_NAME s_scm_environment_undefine
  220. {
  221. SCM status;
  222. SCM_ASSERT(SCM_ENVIRONMENT_P(env), env, SCM_ARG1, FUNC_NAME);
  223. SCM_ASSERT(scm_is_symbol(sym), sym, SCM_ARG2, FUNC_NAME);
  224. status = SCM_ENVIRONMENT_UNDEFINE (env, sym);
  225. if (scm_is_eq (status, SCM_ENVIRONMENT_SUCCESS))
  226. return SCM_UNSPECIFIED;
  227. else if (scm_is_eq (status, SCM_ENVIRONMENT_BINDING_IMMUTABLE))
  228. scm_error_environment_immutable_binding (FUNC_NAME, env, sym);
  229. else
  230. abort();
  231. }
  232. #undef FUNC_NAME
  233. SCM_DEFINE (scm_environment_set_x, "environment-set!", 3, 0, 0,
  234. (SCM env, SCM sym, SCM val),
  235. "If @var{env} binds @var{sym} to some location, change that\n"
  236. "location's value to @var{val}. The return value is\n"
  237. "unspecified.\n"
  238. "If @var{sym} is not bound in @var{env}, signal an\n"
  239. "@code{environment:unbound} error. If @var{env} binds @var{sym}\n"
  240. "to an immutable location, signal an\n"
  241. "@code{environment:immutable-location} error.")
  242. #define FUNC_NAME s_scm_environment_set_x
  243. {
  244. SCM status;
  245. SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  246. SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, FUNC_NAME);
  247. status = SCM_ENVIRONMENT_SET (env, sym, val);
  248. if (scm_is_eq (status, SCM_ENVIRONMENT_SUCCESS))
  249. return SCM_UNSPECIFIED;
  250. else if (SCM_UNBNDP (status))
  251. scm_error_environment_unbound (FUNC_NAME, env, sym);
  252. else if (scm_is_eq (status, SCM_ENVIRONMENT_LOCATION_IMMUTABLE))
  253. scm_error_environment_immutable_binding (FUNC_NAME, env, sym);
  254. else
  255. abort();
  256. }
  257. #undef FUNC_NAME
  258. SCM_DEFINE (scm_environment_cell, "environment-cell", 3, 0, 0,
  259. (SCM env, SCM sym, SCM for_write),
  260. "Return the value cell which @var{env} binds to @var{sym}, or\n"
  261. "@code{#f} if the binding does not live in a value cell.\n"
  262. "The argument @var{for-write} indicates whether the caller\n"
  263. "intends to modify the variable's value by mutating the value\n"
  264. "cell. If the variable is immutable, then\n"
  265. "@code{environment-cell} signals an\n"
  266. "@code{environment:immutable-location} error.\n"
  267. "If @var{sym} is unbound in @var{env}, signal an\n"
  268. "@code{environment:unbound} error.\n"
  269. "If you use this function, you should consider using\n"
  270. "@code{environment-observe}, to be notified when @var{sym} gets\n"
  271. "re-bound to a new value cell, or becomes undefined.")
  272. #define FUNC_NAME s_scm_environment_cell
  273. {
  274. SCM location;
  275. SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  276. SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, FUNC_NAME);
  277. SCM_ASSERT (scm_is_bool (for_write), for_write, SCM_ARG3, FUNC_NAME);
  278. location = SCM_ENVIRONMENT_CELL (env, sym, scm_is_true (for_write));
  279. if (!SCM_IMP (location))
  280. return location;
  281. else if (SCM_UNBNDP (location))
  282. scm_error_environment_unbound (FUNC_NAME, env, sym);
  283. else if (scm_is_eq (location, SCM_ENVIRONMENT_LOCATION_IMMUTABLE))
  284. scm_error_environment_immutable_location (FUNC_NAME, env, sym);
  285. else /* no cell */
  286. return location;
  287. }
  288. #undef FUNC_NAME
  289. /* This C function is identical to environment-cell, with the following
  290. * exceptions: If symbol is unbound in env, it returns the value
  291. * SCM_UNDEFINED, instead of signalling an error. If symbol is bound to an
  292. * immutable location but the cell is requested for write, the value
  293. * SCM_ENVIRONMENT_LOCATION_IMMUTABLE is returned.
  294. */
  295. SCM
  296. scm_c_environment_cell(SCM env, SCM sym, int for_write)
  297. {
  298. SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, "scm_c_environment_cell");
  299. SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, "scm_c_environment_cell");
  300. return SCM_ENVIRONMENT_CELL (env, sym, for_write);
  301. }
  302. static void
  303. environment_default_observer (SCM env, SCM proc)
  304. {
  305. scm_call_1 (proc, env);
  306. }
  307. SCM_DEFINE (scm_environment_observe, "environment-observe", 2, 0, 0,
  308. (SCM env, SCM proc),
  309. "Whenever @var{env}'s bindings change, apply @var{proc} to\n"
  310. "@var{env}.\n"
  311. "This function returns an object, token, which you can pass to\n"
  312. "@code{environment-unobserve} to remove @var{proc} from the set\n"
  313. "of procedures observing @var{env}. The type and value of\n"
  314. "token is unspecified.")
  315. #define FUNC_NAME s_scm_environment_observe
  316. {
  317. SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  318. return SCM_ENVIRONMENT_OBSERVE (env, environment_default_observer, proc, 0);
  319. }
  320. #undef FUNC_NAME
  321. SCM_DEFINE (scm_environment_observe_weak, "environment-observe-weak", 2, 0, 0,
  322. (SCM env, SCM proc),
  323. "This function is the same as environment-observe, except that\n"
  324. "the reference @var{env} retains to @var{proc} is a weak\n"
  325. "reference. This means that, if there are no other live,\n"
  326. "non-weak references to @var{proc}, it will be\n"
  327. "garbage-collected, and dropped from @var{env}'s\n"
  328. "list of observing procedures.")
  329. #define FUNC_NAME s_scm_environment_observe_weak
  330. {
  331. SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  332. return SCM_ENVIRONMENT_OBSERVE (env, environment_default_observer, proc, 1);
  333. }
  334. #undef FUNC_NAME
  335. /* This is the C-level analog of the Scheme functions environment-observe and
  336. * environment-observe-weak. Whenever env's bindings change, call the
  337. * function proc, passing it env and data. If weak_p is non-zero, env will
  338. * retain only a weak reference to data, and if data is garbage collected, the
  339. * entire observation will be dropped. This function returns a token, with
  340. * the same meaning as those returned by environment-observe and
  341. * environment-observe-weak.
  342. */
  343. SCM
  344. scm_c_environment_observe (SCM env, scm_environment_observer proc, SCM data, int weak_p)
  345. #define FUNC_NAME "scm_c_environment_observe"
  346. {
  347. SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  348. return SCM_ENVIRONMENT_OBSERVE (env, proc, data, weak_p);
  349. }
  350. #undef FUNC_NAME
  351. SCM_DEFINE (scm_environment_unobserve, "environment-unobserve", 1, 0, 0,
  352. (SCM token),
  353. "Cancel the observation request which returned the value\n"
  354. "@var{token}. The return value is unspecified.\n"
  355. "If a call @code{(environment-observe env proc)} returns\n"
  356. "@var{token}, then the call @code{(environment-unobserve token)}\n"
  357. "will cause @var{proc} to no longer be called when @var{env}'s\n"
  358. "bindings change.")
  359. #define FUNC_NAME s_scm_environment_unobserve
  360. {
  361. SCM env;
  362. SCM_ASSERT (SCM_OBSERVER_P (token), token, SCM_ARG1, FUNC_NAME);
  363. env = SCM_OBSERVER_ENVIRONMENT (token);
  364. SCM_ENVIRONMENT_UNOBSERVE (env, token);
  365. return SCM_UNSPECIFIED;
  366. }
  367. #undef FUNC_NAME
  368. static SCM
  369. environment_mark (SCM env)
  370. {
  371. return (*(SCM_ENVIRONMENT_FUNCS (env)->mark)) (env);
  372. }
  373. static size_t
  374. environment_free (SCM env)
  375. {
  376. (*(SCM_ENVIRONMENT_FUNCS (env)->free)) (env);
  377. return 0;
  378. }
  379. static int
  380. environment_print (SCM env, SCM port, scm_print_state *pstate)
  381. {
  382. return (*(SCM_ENVIRONMENT_FUNCS (env)->print)) (env, port, pstate);
  383. }
  384. /* observers */
  385. static SCM
  386. observer_mark (SCM observer)
  387. {
  388. scm_gc_mark (SCM_OBSERVER_ENVIRONMENT (observer));
  389. scm_gc_mark (SCM_OBSERVER_DATA (observer));
  390. return SCM_BOOL_F;
  391. }
  392. static int
  393. observer_print (SCM type, SCM port, scm_print_state *pstate SCM_UNUSED)
  394. {
  395. SCM address = scm_from_size_t (SCM_UNPACK (type));
  396. SCM base16 = scm_number_to_string (address, scm_from_int (16));
  397. scm_puts ("#<observer ", port);
  398. scm_display (base16, port);
  399. scm_puts (">", port);
  400. return 1;
  401. }
  402. /* obarrays
  403. *
  404. * Obarrays form the basic lookup tables used to implement most of guile's
  405. * built-in environment types. An obarray is implemented as a hash table with
  406. * symbols as keys. The content of the data depends on the environment type.
  407. */
  408. /*
  409. * Enter symbol into obarray. The symbol must not already exist in obarray.
  410. * The freshly generated (symbol . data) cell is returned.
  411. */
  412. static SCM
  413. obarray_enter (SCM obarray, SCM symbol, SCM data)
  414. {
  415. size_t hash = scm_i_symbol_hash (symbol) % SCM_HASHTABLE_N_BUCKETS (obarray);
  416. SCM entry = scm_cons (symbol, data);
  417. SCM slot = scm_cons (entry, SCM_HASHTABLE_BUCKET (obarray, hash));
  418. SCM_SET_HASHTABLE_BUCKET (obarray, hash, slot);
  419. SCM_HASHTABLE_INCREMENT (obarray);
  420. if (SCM_HASHTABLE_N_ITEMS (obarray) > SCM_HASHTABLE_UPPER (obarray))
  421. scm_i_rehash (obarray, scm_i_hash_symbol, 0, "obarray_enter", NULL);
  422. return entry;
  423. }
  424. /*
  425. * Enter symbol into obarray. An existing entry for symbol is replaced. If
  426. * an entry existed, the old (symbol . data) cell is returned, #f otherwise.
  427. */
  428. static SCM
  429. obarray_replace (SCM obarray, SCM symbol, SCM data)
  430. {
  431. size_t hash = scm_i_symbol_hash (symbol) % SCM_HASHTABLE_N_BUCKETS (obarray);
  432. SCM new_entry = scm_cons (symbol, data);
  433. SCM lsym;
  434. SCM slot;
  435. for (lsym = SCM_HASHTABLE_BUCKET (obarray, hash);
  436. !scm_is_null (lsym);
  437. lsym = SCM_CDR (lsym))
  438. {
  439. SCM old_entry = SCM_CAR (lsym);
  440. if (scm_is_eq (SCM_CAR (old_entry), symbol))
  441. {
  442. SCM_SETCAR (lsym, new_entry);
  443. return old_entry;
  444. }
  445. }
  446. slot = scm_cons (new_entry, SCM_HASHTABLE_BUCKET (obarray, hash));
  447. SCM_SET_HASHTABLE_BUCKET (obarray, hash, slot);
  448. SCM_HASHTABLE_INCREMENT (obarray);
  449. if (SCM_HASHTABLE_N_ITEMS (obarray) > SCM_HASHTABLE_UPPER (obarray))
  450. scm_i_rehash (obarray, scm_i_hash_symbol, 0, "obarray_replace", NULL);
  451. return SCM_BOOL_F;
  452. }
  453. /*
  454. * Look up symbol in obarray
  455. */
  456. static SCM
  457. obarray_retrieve (SCM obarray, SCM sym)
  458. {
  459. size_t hash = scm_i_symbol_hash (sym) % SCM_HASHTABLE_N_BUCKETS (obarray);
  460. SCM lsym;
  461. for (lsym = SCM_HASHTABLE_BUCKET (obarray, hash);
  462. !scm_is_null (lsym);
  463. lsym = SCM_CDR (lsym))
  464. {
  465. SCM entry = SCM_CAR (lsym);
  466. if (scm_is_eq (SCM_CAR (entry), sym))
  467. return entry;
  468. }
  469. return SCM_UNDEFINED;
  470. }
  471. /*
  472. * Remove entry from obarray. If the symbol was found and removed, the old
  473. * (symbol . data) cell is returned, #f otherwise.
  474. */
  475. static SCM
  476. obarray_remove (SCM obarray, SCM sym)
  477. {
  478. size_t hash = scm_i_symbol_hash (sym) % SCM_HASHTABLE_N_BUCKETS (obarray);
  479. SCM table_entry = SCM_HASHTABLE_BUCKET (obarray, hash);
  480. SCM handle = scm_sloppy_assq (sym, table_entry);
  481. if (scm_is_pair (handle))
  482. {
  483. SCM new_table_entry = scm_delq1_x (handle, table_entry);
  484. SCM_SET_HASHTABLE_BUCKET (obarray, hash, new_table_entry);
  485. SCM_HASHTABLE_DECREMENT (obarray);
  486. }
  487. return handle;
  488. }
  489. static void
  490. obarray_remove_all (SCM obarray)
  491. {
  492. size_t size = SCM_HASHTABLE_N_BUCKETS (obarray);
  493. size_t i;
  494. for (i = 0; i < size; i++)
  495. {
  496. SCM_SET_HASHTABLE_BUCKET (obarray, i, SCM_EOL);
  497. }
  498. SCM_SET_HASHTABLE_N_ITEMS (obarray, 0);
  499. }
  500. /* core environments base
  501. *
  502. * This struct and the corresponding functions form a base class for guile's
  503. * built-in environment types.
  504. */
  505. struct core_environments_base {
  506. struct scm_environment_funcs *funcs;
  507. SCM observers;
  508. SCM weak_observers;
  509. };
  510. #define CORE_ENVIRONMENTS_BASE(env) \
  511. ((struct core_environments_base *) SCM_CELL_WORD_1 (env))
  512. #define CORE_ENVIRONMENT_OBSERVERS(env) \
  513. (CORE_ENVIRONMENTS_BASE (env)->observers)
  514. #define SCM_SET_CORE_ENVIRONMENT_OBSERVERS(env, v) \
  515. (CORE_ENVIRONMENT_OBSERVERS (env) = (v))
  516. #define CORE_ENVIRONMENT_WEAK_OBSERVER_VECTOR(env) \
  517. (CORE_ENVIRONMENTS_BASE (env)->weak_observers)
  518. #define CORE_ENVIRONMENT_WEAK_OBSERVERS(env) \
  519. (scm_c_vector_ref (CORE_ENVIRONMENT_WEAK_OBSERVER_VECTOR (env), 0))
  520. #define SCM_SET_CORE_ENVIRONMENT_WEAK_OBSERVERS(env, v) \
  521. (scm_c_vector_set_x (CORE_ENVIRONMENT_WEAK_OBSERVER_VECTOR (env), 0, (v)))
  522. static SCM
  523. core_environments_observe (SCM env, scm_environment_observer proc, SCM data, int weak_p)
  524. {
  525. SCM observer = scm_double_cell (scm_tc16_observer,
  526. SCM_UNPACK (env),
  527. SCM_UNPACK (data),
  528. (scm_t_bits) proc);
  529. if (!weak_p)
  530. {
  531. SCM observers = CORE_ENVIRONMENT_OBSERVERS (env);
  532. SCM new_observers = scm_cons (observer, observers);
  533. SCM_SET_CORE_ENVIRONMENT_OBSERVERS (env, new_observers);
  534. }
  535. else
  536. {
  537. SCM observers = CORE_ENVIRONMENT_WEAK_OBSERVERS (env);
  538. SCM new_observers = scm_acons (SCM_BOOL_F, observer, observers);
  539. SCM_SET_CORE_ENVIRONMENT_WEAK_OBSERVERS (env, new_observers);
  540. }
  541. return observer;
  542. }
  543. static void
  544. core_environments_unobserve (SCM env, SCM observer)
  545. {
  546. unsigned int handling_weaks;
  547. for (handling_weaks = 0; handling_weaks <= 1; ++handling_weaks)
  548. {
  549. SCM l = handling_weaks
  550. ? CORE_ENVIRONMENT_WEAK_OBSERVERS (env)
  551. : CORE_ENVIRONMENT_OBSERVERS (env);
  552. if (!scm_is_null (l))
  553. {
  554. SCM rest = SCM_CDR (l);
  555. SCM first = handling_weaks
  556. ? SCM_CDAR (l)
  557. : SCM_CAR (l);
  558. if (scm_is_eq (first, observer))
  559. {
  560. /* Remove the first observer */
  561. if (handling_weaks)
  562. SCM_SET_CORE_ENVIRONMENT_WEAK_OBSERVERS (env, rest);
  563. else
  564. SCM_SET_CORE_ENVIRONMENT_OBSERVERS (env, rest);
  565. return;
  566. }
  567. do {
  568. SCM rest = SCM_CDR (l);
  569. if (!scm_is_null (rest))
  570. {
  571. SCM next = handling_weaks
  572. ? SCM_CDAR (l)
  573. : SCM_CAR (l);
  574. if (scm_is_eq (next, observer))
  575. {
  576. SCM_SETCDR (l, SCM_CDR (rest));
  577. return;
  578. }
  579. }
  580. l = rest;
  581. } while (!scm_is_null (l));
  582. }
  583. }
  584. /* Dirk:FIXME:: What to do now, since the observer is not found? */
  585. }
  586. static SCM
  587. core_environments_mark (SCM env)
  588. {
  589. scm_gc_mark (CORE_ENVIRONMENT_OBSERVERS (env));
  590. return CORE_ENVIRONMENT_WEAK_OBSERVER_VECTOR (env);
  591. }
  592. static void
  593. core_environments_finalize (SCM env SCM_UNUSED)
  594. {
  595. }
  596. static void
  597. core_environments_preinit (struct core_environments_base *body)
  598. {
  599. body->funcs = NULL;
  600. body->observers = SCM_BOOL_F;
  601. body->weak_observers = SCM_BOOL_F;
  602. }
  603. static void
  604. core_environments_init (struct core_environments_base *body,
  605. struct scm_environment_funcs *funcs)
  606. {
  607. body->funcs = funcs;
  608. body->observers = SCM_EOL;
  609. body->weak_observers = scm_make_weak_value_alist_vector (scm_from_int (1));
  610. }
  611. /* Tell all observers to clear their caches.
  612. *
  613. * Environments have to be informed about changes in the following cases:
  614. * - The observed env has a new binding. This must be always reported.
  615. * - The observed env has dropped a binding. This must be always reported.
  616. * - A binding in the observed environment has changed. This must only be
  617. * reported, if there is a chance that the binding is being cached outside.
  618. * However, this potential optimization is not performed currently.
  619. *
  620. * Errors that occur while the observers are called are accumulated and
  621. * signalled as one single error message to the caller.
  622. */
  623. struct update_data
  624. {
  625. SCM observer;
  626. SCM environment;
  627. };
  628. static SCM
  629. update_catch_body (void *ptr)
  630. {
  631. struct update_data *data = (struct update_data *) ptr;
  632. SCM observer = data->observer;
  633. (*SCM_OBSERVER_PROC (observer))
  634. (data->environment, SCM_OBSERVER_DATA (observer));
  635. return SCM_UNDEFINED;
  636. }
  637. static SCM
  638. update_catch_handler (void *ptr, SCM tag, SCM args)
  639. {
  640. struct update_data *data = (struct update_data *) ptr;
  641. SCM observer = data->observer;
  642. SCM message =
  643. scm_from_locale_string ("Observer `~A' signals `~A' error: ~S");
  644. return scm_cons (message, scm_list_3 (observer, tag, args));
  645. }
  646. static void
  647. core_environments_broadcast (SCM env)
  648. #define FUNC_NAME "core_environments_broadcast"
  649. {
  650. unsigned int handling_weaks;
  651. SCM errors = SCM_EOL;
  652. for (handling_weaks = 0; handling_weaks <= 1; ++handling_weaks)
  653. {
  654. SCM observers = handling_weaks
  655. ? CORE_ENVIRONMENT_WEAK_OBSERVERS (env)
  656. : CORE_ENVIRONMENT_OBSERVERS (env);
  657. for (; !scm_is_null (observers); observers = SCM_CDR (observers))
  658. {
  659. struct update_data data;
  660. SCM observer = handling_weaks
  661. ? SCM_CDAR (observers)
  662. : SCM_CAR (observers);
  663. SCM error;
  664. data.observer = observer;
  665. data.environment = env;
  666. error = scm_internal_catch (SCM_BOOL_T,
  667. update_catch_body, &data,
  668. update_catch_handler, &data);
  669. if (!SCM_UNBNDP (error))
  670. errors = scm_cons (error, errors);
  671. }
  672. }
  673. if (!scm_is_null (errors))
  674. {
  675. /* Dirk:FIXME:: As soon as scm_misc_error is fixed to handle the name
  676. * parameter correctly it should not be necessary any more to also pass
  677. * namestr in order to get the desired information from the error
  678. * message.
  679. */
  680. SCM ordered_errors = scm_reverse (errors);
  681. scm_misc_error
  682. (FUNC_NAME,
  683. "Observers of `~A' have signalled the following errors: ~S",
  684. scm_cons2 (env, ordered_errors, SCM_EOL));
  685. }
  686. }
  687. #undef FUNC_NAME
  688. /* leaf environments
  689. *
  690. * A leaf environment is simply a mutable set of definitions. A leaf
  691. * environment supports no operations beyond the common set.
  692. *
  693. * Implementation: The obarray of the leaf environment holds (symbol . value)
  694. * pairs. No further information is necessary, since all bindings and
  695. * locations in a leaf environment are mutable.
  696. */
  697. struct leaf_environment {
  698. struct core_environments_base base;
  699. SCM obarray;
  700. };
  701. #define LEAF_ENVIRONMENT(env) \
  702. ((struct leaf_environment *) SCM_CELL_WORD_1 (env))
  703. static SCM
  704. leaf_environment_ref (SCM env, SCM sym)
  705. {
  706. SCM obarray = LEAF_ENVIRONMENT (env)->obarray;
  707. SCM binding = obarray_retrieve (obarray, sym);
  708. return SCM_UNBNDP (binding) ? binding : SCM_CDR (binding);
  709. }
  710. static SCM
  711. leaf_environment_fold (SCM env, scm_environment_folder proc, SCM data, SCM init)
  712. {
  713. size_t i;
  714. SCM result = init;
  715. SCM obarray = LEAF_ENVIRONMENT (env)->obarray;
  716. for (i = 0; i < SCM_HASHTABLE_N_BUCKETS (obarray); i++)
  717. {
  718. SCM l;
  719. for (l = SCM_HASHTABLE_BUCKET (obarray, i);
  720. !scm_is_null (l);
  721. l = SCM_CDR (l))
  722. {
  723. SCM binding = SCM_CAR (l);
  724. SCM symbol = SCM_CAR (binding);
  725. SCM value = SCM_CDR (binding);
  726. result = (*proc) (data, symbol, value, result);
  727. }
  728. }
  729. return result;
  730. }
  731. static SCM
  732. leaf_environment_define (SCM env, SCM sym, SCM val)
  733. #define FUNC_NAME "leaf_environment_define"
  734. {
  735. SCM obarray = LEAF_ENVIRONMENT (env)->obarray;
  736. obarray_replace (obarray, sym, val);
  737. core_environments_broadcast (env);
  738. return SCM_ENVIRONMENT_SUCCESS;
  739. }
  740. #undef FUNC_NAME
  741. static SCM
  742. leaf_environment_undefine (SCM env, SCM sym)
  743. #define FUNC_NAME "leaf_environment_undefine"
  744. {
  745. SCM obarray = LEAF_ENVIRONMENT (env)->obarray;
  746. SCM removed = obarray_remove (obarray, sym);
  747. if (scm_is_true (removed))
  748. core_environments_broadcast (env);
  749. return SCM_ENVIRONMENT_SUCCESS;
  750. }
  751. #undef FUNC_NAME
  752. static SCM
  753. leaf_environment_set_x (SCM env, SCM sym, SCM val)
  754. #define FUNC_NAME "leaf_environment_set_x"
  755. {
  756. SCM obarray = LEAF_ENVIRONMENT (env)->obarray;
  757. SCM binding = obarray_retrieve (obarray, sym);
  758. if (!SCM_UNBNDP (binding))
  759. {
  760. SCM_SETCDR (binding, val);
  761. return SCM_ENVIRONMENT_SUCCESS;
  762. }
  763. else
  764. {
  765. return SCM_UNDEFINED;
  766. }
  767. }
  768. #undef FUNC_NAME
  769. static SCM
  770. leaf_environment_cell (SCM env, SCM sym, int for_write SCM_UNUSED)
  771. {
  772. SCM obarray = LEAF_ENVIRONMENT (env)->obarray;
  773. SCM binding = obarray_retrieve (obarray, sym);
  774. return binding;
  775. }
  776. static SCM
  777. leaf_environment_mark (SCM env)
  778. {
  779. scm_gc_mark (LEAF_ENVIRONMENT (env)->obarray);
  780. return core_environments_mark (env);
  781. }
  782. static void
  783. leaf_environment_free (SCM env)
  784. {
  785. core_environments_finalize (env);
  786. scm_gc_free (LEAF_ENVIRONMENT (env), sizeof (struct leaf_environment),
  787. "leaf environment");
  788. }
  789. static int
  790. leaf_environment_print (SCM type, SCM port, scm_print_state *pstate SCM_UNUSED)
  791. {
  792. SCM address = scm_from_size_t (SCM_UNPACK (type));
  793. SCM base16 = scm_number_to_string (address, scm_from_int (16));
  794. scm_puts ("#<leaf environment ", port);
  795. scm_display (base16, port);
  796. scm_puts (">", port);
  797. return 1;
  798. }
  799. static struct scm_environment_funcs leaf_environment_funcs = {
  800. leaf_environment_ref,
  801. leaf_environment_fold,
  802. leaf_environment_define,
  803. leaf_environment_undefine,
  804. leaf_environment_set_x,
  805. leaf_environment_cell,
  806. core_environments_observe,
  807. core_environments_unobserve,
  808. leaf_environment_mark,
  809. leaf_environment_free,
  810. leaf_environment_print
  811. };
  812. void *scm_type_leaf_environment = &leaf_environment_funcs;
  813. SCM_DEFINE (scm_make_leaf_environment, "make-leaf-environment", 0, 0, 0,
  814. (),
  815. "Create a new leaf environment, containing no bindings.\n"
  816. "All bindings and locations created in the new environment\n"
  817. "will be mutable.")
  818. #define FUNC_NAME s_scm_make_leaf_environment
  819. {
  820. size_t size = sizeof (struct leaf_environment);
  821. struct leaf_environment *body = scm_gc_malloc (size, "leaf environment");
  822. SCM env;
  823. core_environments_preinit (&body->base);
  824. body->obarray = SCM_BOOL_F;
  825. env = scm_make_environment (body);
  826. core_environments_init (&body->base, &leaf_environment_funcs);
  827. body->obarray = scm_c_make_hash_table (DEFAULT_OBARRAY_SIZE);
  828. return env;
  829. }
  830. #undef FUNC_NAME
  831. SCM_DEFINE (scm_leaf_environment_p, "leaf-environment?", 1, 0, 0,
  832. (SCM object),
  833. "Return @code{#t} if object is a leaf environment, or @code{#f}\n"
  834. "otherwise.")
  835. #define FUNC_NAME s_scm_leaf_environment_p
  836. {
  837. return scm_from_bool (SCM_LEAF_ENVIRONMENT_P (object));
  838. }
  839. #undef FUNC_NAME
  840. /* eval environments
  841. *
  842. * A module's source code refers to definitions imported from other modules,
  843. * and definitions made within itself. An eval environment combines two
  844. * environments -- a local environment and an imported environment -- to
  845. * produce a new environment in which both sorts of references can be
  846. * resolved.
  847. *
  848. * Implementation: The obarray of the eval environment is used to cache
  849. * entries from the local and imported environments such that in most of the
  850. * cases only a single lookup is necessary. Since for neither the local nor
  851. * the imported environment it is known, what kind of environment they form,
  852. * the most general case is assumed. Therefore, entries in the obarray take
  853. * one of the following forms:
  854. *
  855. * 1) (<symbol> location mutability . source-env), where mutability indicates
  856. * one of the following states: IMMUTABLE if the location is known to be
  857. * immutable, MUTABLE if the location is known to be mutable, UNKNOWN if
  858. * the location has only been requested for non modifying accesses.
  859. *
  860. * 2) (symbol . source-env) if the symbol has a binding in the source-env, but
  861. * if the source-env can't provide a cell for the binding. Thus, for every
  862. * access, the source-env has to be contacted directly.
  863. */
  864. struct eval_environment {
  865. struct core_environments_base base;
  866. SCM obarray;
  867. SCM imported;
  868. SCM imported_observer;
  869. SCM local;
  870. SCM local_observer;
  871. };
  872. #define EVAL_ENVIRONMENT(env) \
  873. ((struct eval_environment *) SCM_CELL_WORD_1 (env))
  874. #define IMMUTABLE SCM_I_MAKINUM (0)
  875. #define MUTABLE SCM_I_MAKINUM (1)
  876. #define UNKNOWN SCM_I_MAKINUM (2)
  877. #define CACHED_LOCATION(x) SCM_CAR (x)
  878. #define CACHED_MUTABILITY(x) SCM_CADR (x)
  879. #define SET_CACHED_MUTABILITY(x, v) SCM_SETCAR (SCM_CDR (x), (v))
  880. #define CACHED_SOURCE_ENVIRONMENT(x) SCM_CDDR (x)
  881. /* eval_environment_lookup will report one of the following distinct results:
  882. * a) (<object> . value) if a cell could be obtained.
  883. * b) <environment> if the environment has to be contacted directly.
  884. * c) IMMUTABLE if an immutable cell was requested for write.
  885. * d) SCM_UNDEFINED if there is no binding for the symbol.
  886. */
  887. static SCM
  888. eval_environment_lookup (SCM env, SCM sym, int for_write)
  889. {
  890. SCM obarray = EVAL_ENVIRONMENT (env)->obarray;
  891. SCM binding = obarray_retrieve (obarray, sym);
  892. if (!SCM_UNBNDP (binding))
  893. {
  894. /* The obarray holds an entry for the symbol. */
  895. SCM entry = SCM_CDR (binding);
  896. if (scm_is_pair (entry))
  897. {
  898. /* The entry in the obarray is a cached location. */
  899. SCM location = CACHED_LOCATION (entry);
  900. SCM mutability;
  901. if (!for_write)
  902. return location;
  903. mutability = CACHED_MUTABILITY (entry);
  904. if (scm_is_eq (mutability, MUTABLE))
  905. return location;
  906. if (scm_is_eq (mutability, UNKNOWN))
  907. {
  908. SCM source_env = CACHED_SOURCE_ENVIRONMENT (entry);
  909. SCM location = SCM_ENVIRONMENT_CELL (source_env, sym, 1);
  910. if (scm_is_pair (location))
  911. {
  912. SET_CACHED_MUTABILITY (entry, MUTABLE);
  913. return location;
  914. }
  915. else /* IMMUTABLE */
  916. {
  917. SET_CACHED_MUTABILITY (entry, IMMUTABLE);
  918. return IMMUTABLE;
  919. }
  920. }
  921. return IMMUTABLE;
  922. }
  923. else
  924. {
  925. /* The obarray entry is an environment */
  926. return entry;
  927. }
  928. }
  929. else
  930. {
  931. /* There is no entry for the symbol in the obarray. This can either
  932. * mean that there has not been a request for the symbol yet, or that
  933. * the symbol is really undefined. We are looking for the symbol in
  934. * both the local and the imported environment. If we find a binding, a
  935. * cached entry is created.
  936. */
  937. struct eval_environment *body = EVAL_ENVIRONMENT (env);
  938. unsigned int handling_import;
  939. for (handling_import = 0; handling_import <= 1; ++handling_import)
  940. {
  941. SCM source_env = handling_import ? body->imported : body->local;
  942. SCM location = SCM_ENVIRONMENT_CELL (source_env, sym, for_write);
  943. if (!SCM_UNBNDP (location))
  944. {
  945. if (scm_is_pair (location))
  946. {
  947. SCM mutability = for_write ? MUTABLE : UNKNOWN;
  948. SCM entry = scm_cons2 (location, mutability, source_env);
  949. obarray_enter (obarray, sym, entry);
  950. return location;
  951. }
  952. else if (scm_is_eq (location, SCM_ENVIRONMENT_LOCATION_NO_CELL))
  953. {
  954. obarray_enter (obarray, sym, source_env);
  955. return source_env;
  956. }
  957. else
  958. {
  959. return IMMUTABLE;
  960. }
  961. }
  962. }
  963. return SCM_UNDEFINED;
  964. }
  965. }
  966. static SCM
  967. eval_environment_ref (SCM env, SCM sym)
  968. #define FUNC_NAME "eval_environment_ref"
  969. {
  970. SCM location = eval_environment_lookup (env, sym, 0);
  971. if (scm_is_pair (location))
  972. return SCM_CDR (location);
  973. else if (!SCM_UNBNDP (location))
  974. return SCM_ENVIRONMENT_REF (location, sym);
  975. else
  976. return SCM_UNDEFINED;
  977. }
  978. #undef FUNC_NAME
  979. static SCM
  980. eval_environment_folder (SCM extended_data, SCM symbol, SCM value, SCM tail)
  981. {
  982. SCM local = SCM_CAR (extended_data);
  983. if (!SCM_ENVIRONMENT_BOUND_P (local, symbol))
  984. {
  985. SCM proc_as_nr = SCM_CADR (extended_data);
  986. unsigned long int proc_as_ul = scm_to_ulong (proc_as_nr);
  987. scm_environment_folder proc = (scm_environment_folder) proc_as_ul;
  988. SCM data = SCM_CDDR (extended_data);
  989. return (*proc) (data, symbol, value, tail);
  990. }
  991. else
  992. {
  993. return tail;
  994. }
  995. }
  996. static SCM
  997. eval_environment_fold (SCM env, scm_environment_folder proc, SCM data, SCM init)
  998. {
  999. SCM local = EVAL_ENVIRONMENT (env)->local;
  1000. SCM imported = EVAL_ENVIRONMENT (env)->imported;
  1001. SCM proc_as_nr = scm_from_ulong ((unsigned long) proc);
  1002. SCM extended_data = scm_cons2 (local, proc_as_nr, data);
  1003. SCM tmp_result = scm_c_environment_fold (imported, eval_environment_folder, extended_data, init);
  1004. return scm_c_environment_fold (local, proc, data, tmp_result);
  1005. }
  1006. static SCM
  1007. eval_environment_define (SCM env, SCM sym, SCM val)
  1008. #define FUNC_NAME "eval_environment_define"
  1009. {
  1010. SCM local = EVAL_ENVIRONMENT (env)->local;
  1011. return SCM_ENVIRONMENT_DEFINE (local, sym, val);
  1012. }
  1013. #undef FUNC_NAME
  1014. static SCM
  1015. eval_environment_undefine (SCM env, SCM sym)
  1016. #define FUNC_NAME "eval_environment_undefine"
  1017. {
  1018. SCM local = EVAL_ENVIRONMENT (env)->local;
  1019. return SCM_ENVIRONMENT_UNDEFINE (local, sym);
  1020. }
  1021. #undef FUNC_NAME
  1022. static SCM
  1023. eval_environment_set_x (SCM env, SCM sym, SCM val)
  1024. #define FUNC_NAME "eval_environment_set_x"
  1025. {
  1026. SCM location = eval_environment_lookup (env, sym, 1);
  1027. if (scm_is_pair (location))
  1028. {
  1029. SCM_SETCDR (location, val);
  1030. return SCM_ENVIRONMENT_SUCCESS;
  1031. }
  1032. else if (SCM_ENVIRONMENT_P (location))
  1033. {
  1034. return SCM_ENVIRONMENT_SET (location, sym, val);
  1035. }
  1036. else if (scm_is_eq (location, IMMUTABLE))
  1037. {
  1038. return SCM_ENVIRONMENT_LOCATION_IMMUTABLE;
  1039. }
  1040. else
  1041. {
  1042. return SCM_UNDEFINED;
  1043. }
  1044. }
  1045. #undef FUNC_NAME
  1046. static SCM
  1047. eval_environment_cell (SCM env, SCM sym, int for_write)
  1048. #define FUNC_NAME "eval_environment_cell"
  1049. {
  1050. SCM location = eval_environment_lookup (env, sym, for_write);
  1051. if (scm_is_pair (location))
  1052. return location;
  1053. else if (SCM_ENVIRONMENT_P (location))
  1054. return SCM_ENVIRONMENT_LOCATION_NO_CELL;
  1055. else if (scm_is_eq (location, IMMUTABLE))
  1056. return SCM_ENVIRONMENT_LOCATION_IMMUTABLE;
  1057. else
  1058. return SCM_UNDEFINED;
  1059. }
  1060. #undef FUNC_NAME
  1061. static SCM
  1062. eval_environment_mark (SCM env)
  1063. {
  1064. struct eval_environment *body = EVAL_ENVIRONMENT (env);
  1065. scm_gc_mark (body->obarray);
  1066. scm_gc_mark (body->imported);
  1067. scm_gc_mark (body->imported_observer);
  1068. scm_gc_mark (body->local);
  1069. scm_gc_mark (body->local_observer);
  1070. return core_environments_mark (env);
  1071. }
  1072. static void
  1073. eval_environment_free (SCM env)
  1074. {
  1075. core_environments_finalize (env);
  1076. scm_gc_free (EVAL_ENVIRONMENT (env), sizeof (struct eval_environment),
  1077. "eval environment");
  1078. }
  1079. static int
  1080. eval_environment_print (SCM type, SCM port, scm_print_state *pstate SCM_UNUSED)
  1081. {
  1082. SCM address = scm_from_size_t (SCM_UNPACK (type));
  1083. SCM base16 = scm_number_to_string (address, scm_from_int (16));
  1084. scm_puts ("#<eval environment ", port);
  1085. scm_display (base16, port);
  1086. scm_puts (">", port);
  1087. return 1;
  1088. }
  1089. static struct scm_environment_funcs eval_environment_funcs = {
  1090. eval_environment_ref,
  1091. eval_environment_fold,
  1092. eval_environment_define,
  1093. eval_environment_undefine,
  1094. eval_environment_set_x,
  1095. eval_environment_cell,
  1096. core_environments_observe,
  1097. core_environments_unobserve,
  1098. eval_environment_mark,
  1099. eval_environment_free,
  1100. eval_environment_print
  1101. };
  1102. void *scm_type_eval_environment = &eval_environment_funcs;
  1103. static void
  1104. eval_environment_observer (SCM caller SCM_UNUSED, SCM eval_env)
  1105. {
  1106. SCM obarray = EVAL_ENVIRONMENT (eval_env)->obarray;
  1107. obarray_remove_all (obarray);
  1108. core_environments_broadcast (eval_env);
  1109. }
  1110. SCM_DEFINE (scm_make_eval_environment, "make-eval-environment", 2, 0, 0,
  1111. (SCM local, SCM imported),
  1112. "Return a new environment object eval whose bindings are the\n"
  1113. "union of the bindings in the environments @var{local} and\n"
  1114. "@var{imported}, with bindings from @var{local} taking\n"
  1115. "precedence. Definitions made in eval are placed in @var{local}.\n"
  1116. "Applying @code{environment-define} or\n"
  1117. "@code{environment-undefine} to eval has the same effect as\n"
  1118. "applying the procedure to @var{local}.\n"
  1119. "Note that eval incorporates @var{local} and @var{imported} by\n"
  1120. "reference:\n"
  1121. "If, after creating eval, the program changes the bindings of\n"
  1122. "@var{local} or @var{imported}, those changes will be visible\n"
  1123. "in eval.\n"
  1124. "Since most Scheme evaluation takes place in eval environments,\n"
  1125. "they transparently cache the bindings received from @var{local}\n"
  1126. "and @var{imported}. Thus, the first time the program looks up\n"
  1127. "a symbol in eval, eval may make calls to @var{local} or\n"
  1128. "@var{imported} to find their bindings, but subsequent\n"
  1129. "references to that symbol will be as fast as references to\n"
  1130. "bindings in finite environments.\n"
  1131. "In typical use, @var{local} will be a finite environment, and\n"
  1132. "@var{imported} will be an import environment")
  1133. #define FUNC_NAME s_scm_make_eval_environment
  1134. {
  1135. SCM env;
  1136. struct eval_environment *body;
  1137. SCM_ASSERT (SCM_ENVIRONMENT_P (local), local, SCM_ARG1, FUNC_NAME);
  1138. SCM_ASSERT (SCM_ENVIRONMENT_P (imported), imported, SCM_ARG2, FUNC_NAME);
  1139. body = scm_gc_malloc (sizeof (struct eval_environment), "eval environment");
  1140. core_environments_preinit (&body->base);
  1141. body->obarray = SCM_BOOL_F;
  1142. body->imported = SCM_BOOL_F;
  1143. body->imported_observer = SCM_BOOL_F;
  1144. body->local = SCM_BOOL_F;
  1145. body->local_observer = SCM_BOOL_F;
  1146. env = scm_make_environment (body);
  1147. core_environments_init (&body->base, &eval_environment_funcs);
  1148. body->obarray = scm_c_make_hash_table (DEFAULT_OBARRAY_SIZE);
  1149. body->imported = imported;
  1150. body->imported_observer
  1151. = SCM_ENVIRONMENT_OBSERVE (imported, eval_environment_observer, env, 1);
  1152. body->local = local;
  1153. body->local_observer
  1154. = SCM_ENVIRONMENT_OBSERVE (local, eval_environment_observer, env, 1);
  1155. return env;
  1156. }
  1157. #undef FUNC_NAME
  1158. SCM_DEFINE (scm_eval_environment_p, "eval-environment?", 1, 0, 0,
  1159. (SCM object),
  1160. "Return @code{#t} if object is an eval environment, or @code{#f}\n"
  1161. "otherwise.")
  1162. #define FUNC_NAME s_scm_eval_environment_p
  1163. {
  1164. return scm_from_bool (SCM_EVAL_ENVIRONMENT_P (object));
  1165. }
  1166. #undef FUNC_NAME
  1167. SCM_DEFINE (scm_eval_environment_local, "eval-environment-local", 1, 0, 0,
  1168. (SCM env),
  1169. "Return the local environment of eval environment @var{env}.")
  1170. #define FUNC_NAME s_scm_eval_environment_local
  1171. {
  1172. SCM_ASSERT (SCM_EVAL_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  1173. return EVAL_ENVIRONMENT (env)->local;
  1174. }
  1175. #undef FUNC_NAME
  1176. SCM_DEFINE (scm_eval_environment_set_local_x, "eval-environment-set-local!", 2, 0, 0,
  1177. (SCM env, SCM local),
  1178. "Change @var{env}'s local environment to @var{local}.")
  1179. #define FUNC_NAME s_scm_eval_environment_set_local_x
  1180. {
  1181. struct eval_environment *body;
  1182. SCM_ASSERT (SCM_EVAL_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  1183. SCM_ASSERT (SCM_ENVIRONMENT_P (local), local, SCM_ARG2, FUNC_NAME);
  1184. body = EVAL_ENVIRONMENT (env);
  1185. obarray_remove_all (body->obarray);
  1186. SCM_ENVIRONMENT_UNOBSERVE (body->local, body->local_observer);
  1187. body->local = local;
  1188. body->local_observer
  1189. = SCM_ENVIRONMENT_OBSERVE (local, eval_environment_observer, env, 1);
  1190. core_environments_broadcast (env);
  1191. return SCM_UNSPECIFIED;
  1192. }
  1193. #undef FUNC_NAME
  1194. SCM_DEFINE (scm_eval_environment_imported, "eval-environment-imported", 1, 0, 0,
  1195. (SCM env),
  1196. "Return the imported environment of eval environment @var{env}.")
  1197. #define FUNC_NAME s_scm_eval_environment_imported
  1198. {
  1199. SCM_ASSERT (SCM_EVAL_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  1200. return EVAL_ENVIRONMENT (env)->imported;
  1201. }
  1202. #undef FUNC_NAME
  1203. SCM_DEFINE (scm_eval_environment_set_imported_x, "eval-environment-set-imported!", 2, 0, 0,
  1204. (SCM env, SCM imported),
  1205. "Change @var{env}'s imported environment to @var{imported}.")
  1206. #define FUNC_NAME s_scm_eval_environment_set_imported_x
  1207. {
  1208. struct eval_environment *body;
  1209. SCM_ASSERT (SCM_EVAL_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  1210. SCM_ASSERT (SCM_ENVIRONMENT_P (imported), imported, SCM_ARG2, FUNC_NAME);
  1211. body = EVAL_ENVIRONMENT (env);
  1212. obarray_remove_all (body->obarray);
  1213. SCM_ENVIRONMENT_UNOBSERVE (body->imported, body->imported_observer);
  1214. body->imported = imported;
  1215. body->imported_observer
  1216. = SCM_ENVIRONMENT_OBSERVE (imported, eval_environment_observer, env, 1);
  1217. core_environments_broadcast (env);
  1218. return SCM_UNSPECIFIED;
  1219. }
  1220. #undef FUNC_NAME
  1221. /* import environments
  1222. *
  1223. * An import environment combines the bindings of a set of argument
  1224. * environments, and checks for naming clashes.
  1225. *
  1226. * Implementation: The import environment does no caching at all. For every
  1227. * access, the list of imported environments is scanned.
  1228. */
  1229. struct import_environment {
  1230. struct core_environments_base base;
  1231. SCM imports;
  1232. SCM import_observers;
  1233. SCM conflict_proc;
  1234. };
  1235. #define IMPORT_ENVIRONMENT(env) \
  1236. ((struct import_environment *) SCM_CELL_WORD_1 (env))
  1237. /* Lookup will report one of the following distinct results:
  1238. * a) <environment> if only environment binds the symbol.
  1239. * b) (env-1 env-2 ...) for conflicting bindings in env-1, ...
  1240. * c) SCM_UNDEFINED if there is no binding for the symbol.
  1241. */
  1242. static SCM
  1243. import_environment_lookup (SCM env, SCM sym)
  1244. {
  1245. SCM imports = IMPORT_ENVIRONMENT (env)->imports;
  1246. SCM result = SCM_UNDEFINED;
  1247. SCM l;
  1248. for (l = imports; !scm_is_null (l); l = SCM_CDR (l))
  1249. {
  1250. SCM imported = SCM_CAR (l);
  1251. if (SCM_ENVIRONMENT_BOUND_P (imported, sym))
  1252. {
  1253. if (SCM_UNBNDP (result))
  1254. result = imported;
  1255. else if (scm_is_pair (result))
  1256. result = scm_cons (imported, result);
  1257. else
  1258. result = scm_cons2 (imported, result, SCM_EOL);
  1259. }
  1260. }
  1261. if (scm_is_pair (result))
  1262. return scm_reverse (result);
  1263. else
  1264. return result;
  1265. }
  1266. static SCM
  1267. import_environment_conflict (SCM env, SCM sym, SCM imports)
  1268. {
  1269. SCM conflict_proc = IMPORT_ENVIRONMENT (env)->conflict_proc;
  1270. SCM args = scm_cons2 (env, sym, scm_cons (imports, SCM_EOL));
  1271. return scm_apply_0 (conflict_proc, args);
  1272. }
  1273. static SCM
  1274. import_environment_ref (SCM env, SCM sym)
  1275. #define FUNC_NAME "import_environment_ref"
  1276. {
  1277. SCM owner = import_environment_lookup (env, sym);
  1278. if (SCM_UNBNDP (owner))
  1279. {
  1280. return SCM_UNDEFINED;
  1281. }
  1282. else if (scm_is_pair (owner))
  1283. {
  1284. SCM resolve = import_environment_conflict (env, sym, owner);
  1285. if (SCM_ENVIRONMENT_P (resolve))
  1286. return SCM_ENVIRONMENT_REF (resolve, sym);
  1287. else
  1288. return SCM_UNSPECIFIED;
  1289. }
  1290. else
  1291. {
  1292. return SCM_ENVIRONMENT_REF (owner, sym);
  1293. }
  1294. }
  1295. #undef FUNC_NAME
  1296. static SCM
  1297. import_environment_folder (SCM extended_data, SCM symbol, SCM value, SCM tail)
  1298. #define FUNC_NAME "import_environment_fold"
  1299. {
  1300. SCM import_env = SCM_CAR (extended_data);
  1301. SCM imported_env = SCM_CADR (extended_data);
  1302. SCM owner = import_environment_lookup (import_env, symbol);
  1303. SCM proc_as_nr = SCM_CADDR (extended_data);
  1304. unsigned long int proc_as_ul = scm_to_ulong (proc_as_nr);
  1305. scm_environment_folder proc = (scm_environment_folder) proc_as_ul;
  1306. SCM data = SCM_CDDDR (extended_data);
  1307. if (scm_is_pair (owner) && scm_is_eq (SCM_CAR (owner), imported_env))
  1308. owner = import_environment_conflict (import_env, symbol, owner);
  1309. if (SCM_ENVIRONMENT_P (owner))
  1310. return (*proc) (data, symbol, value, tail);
  1311. else /* unresolved conflict */
  1312. return (*proc) (data, symbol, SCM_UNSPECIFIED, tail);
  1313. }
  1314. #undef FUNC_NAME
  1315. static SCM
  1316. import_environment_fold (SCM env, scm_environment_folder proc, SCM data, SCM init)
  1317. {
  1318. SCM proc_as_nr = scm_from_ulong ((unsigned long) proc);
  1319. SCM result = init;
  1320. SCM l;
  1321. for (l = IMPORT_ENVIRONMENT (env)->imports; !scm_is_null (l); l = SCM_CDR (l))
  1322. {
  1323. SCM imported_env = SCM_CAR (l);
  1324. SCM extended_data = scm_cons (env, scm_cons2 (imported_env, proc_as_nr, data));
  1325. result = scm_c_environment_fold (imported_env, import_environment_folder, extended_data, result);
  1326. }
  1327. return result;
  1328. }
  1329. static SCM
  1330. import_environment_define (SCM env SCM_UNUSED,
  1331. SCM sym SCM_UNUSED,
  1332. SCM val SCM_UNUSED)
  1333. #define FUNC_NAME "import_environment_define"
  1334. {
  1335. return SCM_ENVIRONMENT_BINDING_IMMUTABLE;
  1336. }
  1337. #undef FUNC_NAME
  1338. static SCM
  1339. import_environment_undefine (SCM env SCM_UNUSED,
  1340. SCM sym SCM_UNUSED)
  1341. #define FUNC_NAME "import_environment_undefine"
  1342. {
  1343. return SCM_ENVIRONMENT_BINDING_IMMUTABLE;
  1344. }
  1345. #undef FUNC_NAME
  1346. static SCM
  1347. import_environment_set_x (SCM env, SCM sym, SCM val)
  1348. #define FUNC_NAME "import_environment_set_x"
  1349. {
  1350. SCM owner = import_environment_lookup (env, sym);
  1351. if (SCM_UNBNDP (owner))
  1352. {
  1353. return SCM_UNDEFINED;
  1354. }
  1355. else if (scm_is_pair (owner))
  1356. {
  1357. SCM resolve = import_environment_conflict (env, sym, owner);
  1358. if (SCM_ENVIRONMENT_P (resolve))
  1359. return SCM_ENVIRONMENT_SET (resolve, sym, val);
  1360. else
  1361. return SCM_ENVIRONMENT_LOCATION_IMMUTABLE;
  1362. }
  1363. else
  1364. {
  1365. return SCM_ENVIRONMENT_SET (owner, sym, val);
  1366. }
  1367. }
  1368. #undef FUNC_NAME
  1369. static SCM
  1370. import_environment_cell (SCM env, SCM sym, int for_write)
  1371. #define FUNC_NAME "import_environment_cell"
  1372. {
  1373. SCM owner = import_environment_lookup (env, sym);
  1374. if (SCM_UNBNDP (owner))
  1375. {
  1376. return SCM_UNDEFINED;
  1377. }
  1378. else if (scm_is_pair (owner))
  1379. {
  1380. SCM resolve = import_environment_conflict (env, sym, owner);
  1381. if (SCM_ENVIRONMENT_P (resolve))
  1382. return SCM_ENVIRONMENT_CELL (resolve, sym, for_write);
  1383. else
  1384. return SCM_ENVIRONMENT_LOCATION_NO_CELL;
  1385. }
  1386. else
  1387. {
  1388. return SCM_ENVIRONMENT_CELL (owner, sym, for_write);
  1389. }
  1390. }
  1391. #undef FUNC_NAME
  1392. static SCM
  1393. import_environment_mark (SCM env)
  1394. {
  1395. scm_gc_mark (IMPORT_ENVIRONMENT (env)->imports);
  1396. scm_gc_mark (IMPORT_ENVIRONMENT (env)->import_observers);
  1397. scm_gc_mark (IMPORT_ENVIRONMENT (env)->conflict_proc);
  1398. return core_environments_mark (env);
  1399. }
  1400. static void
  1401. import_environment_free (SCM env)
  1402. {
  1403. core_environments_finalize (env);
  1404. scm_gc_free (IMPORT_ENVIRONMENT (env), sizeof (struct import_environment),
  1405. "import environment");
  1406. }
  1407. static int
  1408. import_environment_print (SCM type, SCM port,
  1409. scm_print_state *pstate SCM_UNUSED)
  1410. {
  1411. SCM address = scm_from_size_t (SCM_UNPACK (type));
  1412. SCM base16 = scm_number_to_string (address, scm_from_int (16));
  1413. scm_puts ("#<import environment ", port);
  1414. scm_display (base16, port);
  1415. scm_puts (">", port);
  1416. return 1;
  1417. }
  1418. static struct scm_environment_funcs import_environment_funcs = {
  1419. import_environment_ref,
  1420. import_environment_fold,
  1421. import_environment_define,
  1422. import_environment_undefine,
  1423. import_environment_set_x,
  1424. import_environment_cell,
  1425. core_environments_observe,
  1426. core_environments_unobserve,
  1427. import_environment_mark,
  1428. import_environment_free,
  1429. import_environment_print
  1430. };
  1431. void *scm_type_import_environment = &import_environment_funcs;
  1432. static void
  1433. import_environment_observer (SCM caller SCM_UNUSED, SCM import_env)
  1434. {
  1435. core_environments_broadcast (import_env);
  1436. }
  1437. SCM_DEFINE (scm_make_import_environment, "make-import-environment", 2, 0, 0,
  1438. (SCM imports, SCM conflict_proc),
  1439. "Return a new environment @var{imp} whose bindings are the union\n"
  1440. "of the bindings from the environments in @var{imports};\n"
  1441. "@var{imports} must be a list of environments. That is,\n"
  1442. "@var{imp} binds a symbol to a location when some element of\n"
  1443. "@var{imports} does.\n"
  1444. "If two different elements of @var{imports} have a binding for\n"
  1445. "the same symbol, the @var{conflict-proc} is called with the\n"
  1446. "following parameters: the import environment, the symbol and\n"
  1447. "the list of the imported environments that bind the symbol.\n"
  1448. "If the @var{conflict-proc} returns an environment @var{env},\n"
  1449. "the conflict is considered as resolved and the binding from\n"
  1450. "@var{env} is used. If the @var{conflict-proc} returns some\n"
  1451. "non-environment object, the conflict is considered unresolved\n"
  1452. "and the symbol is treated as unspecified in the import\n"
  1453. "environment.\n"
  1454. "The checking for conflicts may be performed lazily, i. e. at\n"
  1455. "the moment when a value or binding for a certain symbol is\n"
  1456. "requested instead of the moment when the environment is\n"
  1457. "created or the bindings of the imports change.\n"
  1458. "All bindings in @var{imp} are immutable. If you apply\n"
  1459. "@code{environment-define} or @code{environment-undefine} to\n"
  1460. "@var{imp}, Guile will signal an\n"
  1461. " @code{environment:immutable-binding} error. However,\n"
  1462. "notice that the set of bindings in @var{imp} may still change,\n"
  1463. "if one of its imported environments changes.")
  1464. #define FUNC_NAME s_scm_make_import_environment
  1465. {
  1466. size_t size = sizeof (struct import_environment);
  1467. struct import_environment *body = scm_gc_malloc (size, "import environment");
  1468. SCM env;
  1469. core_environments_preinit (&body->base);
  1470. body->imports = SCM_BOOL_F;
  1471. body->import_observers = SCM_BOOL_F;
  1472. body->conflict_proc = SCM_BOOL_F;
  1473. env = scm_make_environment (body);
  1474. core_environments_init (&body->base, &import_environment_funcs);
  1475. body->imports = SCM_EOL;
  1476. body->import_observers = SCM_EOL;
  1477. body->conflict_proc = conflict_proc;
  1478. scm_import_environment_set_imports_x (env, imports);
  1479. return env;
  1480. }
  1481. #undef FUNC_NAME
  1482. SCM_DEFINE (scm_import_environment_p, "import-environment?", 1, 0, 0,
  1483. (SCM object),
  1484. "Return @code{#t} if object is an import environment, or\n"
  1485. "@code{#f} otherwise.")
  1486. #define FUNC_NAME s_scm_import_environment_p
  1487. {
  1488. return scm_from_bool (SCM_IMPORT_ENVIRONMENT_P (object));
  1489. }
  1490. #undef FUNC_NAME
  1491. SCM_DEFINE (scm_import_environment_imports, "import-environment-imports", 1, 0, 0,
  1492. (SCM env),
  1493. "Return the list of environments imported by the import\n"
  1494. "environment @var{env}.")
  1495. #define FUNC_NAME s_scm_import_environment_imports
  1496. {
  1497. SCM_ASSERT (SCM_IMPORT_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  1498. return IMPORT_ENVIRONMENT (env)->imports;
  1499. }
  1500. #undef FUNC_NAME
  1501. SCM_DEFINE (scm_import_environment_set_imports_x, "import-environment-set-imports!", 2, 0, 0,
  1502. (SCM env, SCM imports),
  1503. "Change @var{env}'s list of imported environments to\n"
  1504. "@var{imports}, and check for conflicts.")
  1505. #define FUNC_NAME s_scm_import_environment_set_imports_x
  1506. {
  1507. struct import_environment *body = IMPORT_ENVIRONMENT (env);
  1508. SCM import_observers = SCM_EOL;
  1509. SCM l;
  1510. SCM_ASSERT (SCM_IMPORT_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  1511. for (l = imports; scm_is_pair (l); l = SCM_CDR (l))
  1512. {
  1513. SCM obj = SCM_CAR (l);
  1514. SCM_ASSERT (SCM_ENVIRONMENT_P (obj), imports, SCM_ARG2, FUNC_NAME);
  1515. }
  1516. SCM_ASSERT (scm_is_null (l), imports, SCM_ARG2, FUNC_NAME);
  1517. for (l = body->import_observers; !scm_is_null (l); l = SCM_CDR (l))
  1518. {
  1519. SCM obs = SCM_CAR (l);
  1520. SCM_ENVIRONMENT_UNOBSERVE (env, obs);
  1521. }
  1522. for (l = imports; !scm_is_null (l); l = SCM_CDR (l))
  1523. {
  1524. SCM imp = SCM_CAR (l);
  1525. SCM obs = SCM_ENVIRONMENT_OBSERVE (imp, import_environment_observer, env, 1);
  1526. import_observers = scm_cons (obs, import_observers);
  1527. }
  1528. body->imports = imports;
  1529. body->import_observers = import_observers;
  1530. return SCM_UNSPECIFIED;
  1531. }
  1532. #undef FUNC_NAME
  1533. /* export environments
  1534. *
  1535. * An export environment restricts an environment to a specified set of
  1536. * bindings.
  1537. *
  1538. * Implementation: The export environment does no caching at all. For every
  1539. * access, the signature is scanned. The signature that is stored internally
  1540. * is an alist of pairs (symbol . (mutability)).
  1541. */
  1542. struct export_environment {
  1543. struct core_environments_base base;
  1544. SCM private;
  1545. SCM private_observer;
  1546. SCM signature;
  1547. };
  1548. #define EXPORT_ENVIRONMENT(env) \
  1549. ((struct export_environment *) SCM_CELL_WORD_1 (env))
  1550. SCM_SYMBOL (symbol_immutable_location, "immutable-location");
  1551. SCM_SYMBOL (symbol_mutable_location, "mutable-location");
  1552. static SCM
  1553. export_environment_ref (SCM env, SCM sym)
  1554. #define FUNC_NAME "export_environment_ref"
  1555. {
  1556. struct export_environment *body = EXPORT_ENVIRONMENT (env);
  1557. SCM entry = scm_assq (sym, body->signature);
  1558. if (scm_is_false (entry))
  1559. return SCM_UNDEFINED;
  1560. else
  1561. return SCM_ENVIRONMENT_REF (body->private, sym);
  1562. }
  1563. #undef FUNC_NAME
  1564. static SCM
  1565. export_environment_fold (SCM env, scm_environment_folder proc, SCM data, SCM init)
  1566. {
  1567. struct export_environment *body = EXPORT_ENVIRONMENT (env);
  1568. SCM result = init;
  1569. SCM l;
  1570. for (l = body->signature; !scm_is_null (l); l = SCM_CDR (l))
  1571. {
  1572. SCM symbol = SCM_CAR (l);
  1573. SCM value = SCM_ENVIRONMENT_REF (body->private, symbol);
  1574. if (!SCM_UNBNDP (value))
  1575. result = (*proc) (data, symbol, value, result);
  1576. }
  1577. return result;
  1578. }
  1579. static SCM
  1580. export_environment_define (SCM env SCM_UNUSED,
  1581. SCM sym SCM_UNUSED,
  1582. SCM val SCM_UNUSED)
  1583. #define FUNC_NAME "export_environment_define"
  1584. {
  1585. return SCM_ENVIRONMENT_BINDING_IMMUTABLE;
  1586. }
  1587. #undef FUNC_NAME
  1588. static SCM
  1589. export_environment_undefine (SCM env SCM_UNUSED, SCM sym SCM_UNUSED)
  1590. #define FUNC_NAME "export_environment_undefine"
  1591. {
  1592. return SCM_ENVIRONMENT_BINDING_IMMUTABLE;
  1593. }
  1594. #undef FUNC_NAME
  1595. static SCM
  1596. export_environment_set_x (SCM env, SCM sym, SCM val)
  1597. #define FUNC_NAME "export_environment_set_x"
  1598. {
  1599. struct export_environment *body = EXPORT_ENVIRONMENT (env);
  1600. SCM entry = scm_assq (sym, body->signature);
  1601. if (scm_is_false (entry))
  1602. {
  1603. return SCM_UNDEFINED;
  1604. }
  1605. else
  1606. {
  1607. if (scm_is_eq (SCM_CADR (entry), symbol_mutable_location))
  1608. return SCM_ENVIRONMENT_SET (body->private, sym, val);
  1609. else
  1610. return SCM_ENVIRONMENT_LOCATION_IMMUTABLE;
  1611. }
  1612. }
  1613. #undef FUNC_NAME
  1614. static SCM
  1615. export_environment_cell (SCM env, SCM sym, int for_write)
  1616. #define FUNC_NAME "export_environment_cell"
  1617. {
  1618. struct export_environment *body = EXPORT_ENVIRONMENT (env);
  1619. SCM entry = scm_assq (sym, body->signature);
  1620. if (scm_is_false (entry))
  1621. {
  1622. return SCM_UNDEFINED;
  1623. }
  1624. else
  1625. {
  1626. if (!for_write || scm_is_eq (SCM_CADR (entry), symbol_mutable_location))
  1627. return SCM_ENVIRONMENT_CELL (body->private, sym, for_write);
  1628. else
  1629. return SCM_ENVIRONMENT_LOCATION_IMMUTABLE;
  1630. }
  1631. }
  1632. #undef FUNC_NAME
  1633. static SCM
  1634. export_environment_mark (SCM env)
  1635. {
  1636. struct export_environment *body = EXPORT_ENVIRONMENT (env);
  1637. scm_gc_mark (body->private);
  1638. scm_gc_mark (body->private_observer);
  1639. scm_gc_mark (body->signature);
  1640. return core_environments_mark (env);
  1641. }
  1642. static void
  1643. export_environment_free (SCM env)
  1644. {
  1645. core_environments_finalize (env);
  1646. scm_gc_free (EXPORT_ENVIRONMENT (env), sizeof (struct export_environment),
  1647. "export environment");
  1648. }
  1649. static int
  1650. export_environment_print (SCM type, SCM port,
  1651. scm_print_state *pstate SCM_UNUSED)
  1652. {
  1653. SCM address = scm_from_size_t (SCM_UNPACK (type));
  1654. SCM base16 = scm_number_to_string (address, scm_from_int (16));
  1655. scm_puts ("#<export environment ", port);
  1656. scm_display (base16, port);
  1657. scm_puts (">", port);
  1658. return 1;
  1659. }
  1660. static struct scm_environment_funcs export_environment_funcs = {
  1661. export_environment_ref,
  1662. export_environment_fold,
  1663. export_environment_define,
  1664. export_environment_undefine,
  1665. export_environment_set_x,
  1666. export_environment_cell,
  1667. core_environments_observe,
  1668. core_environments_unobserve,
  1669. export_environment_mark,
  1670. export_environment_free,
  1671. export_environment_print
  1672. };
  1673. void *scm_type_export_environment = &export_environment_funcs;
  1674. static void
  1675. export_environment_observer (SCM caller SCM_UNUSED, SCM export_env)
  1676. {
  1677. core_environments_broadcast (export_env);
  1678. }
  1679. SCM_DEFINE (scm_make_export_environment, "make-export-environment", 2, 0, 0,
  1680. (SCM private, SCM signature),
  1681. "Return a new environment @var{exp} containing only those\n"
  1682. "bindings in private whose symbols are present in\n"
  1683. "@var{signature}. The @var{private} argument must be an\n"
  1684. "environment.\n\n"
  1685. "The environment @var{exp} binds symbol to location when\n"
  1686. "@var{env} does, and symbol is exported by @var{signature}.\n\n"
  1687. "@var{signature} is a list specifying which of the bindings in\n"
  1688. "@var{private} should be visible in @var{exp}. Each element of\n"
  1689. "@var{signature} should be a list of the form:\n"
  1690. " (symbol attribute ...)\n"
  1691. "where each attribute is one of the following:\n"
  1692. "@table @asis\n"
  1693. "@item the symbol @code{mutable-location}\n"
  1694. " @var{exp} should treat the\n"
  1695. " location bound to symbol as mutable. That is, @var{exp}\n"
  1696. " will pass calls to @code{environment-set!} or\n"
  1697. " @code{environment-cell} directly through to private.\n"
  1698. "@item the symbol @code{immutable-location}\n"
  1699. " @var{exp} should treat\n"
  1700. " the location bound to symbol as immutable. If the program\n"
  1701. " applies @code{environment-set!} to @var{exp} and symbol, or\n"
  1702. " calls @code{environment-cell} to obtain a writable value\n"
  1703. " cell, @code{environment-set!} will signal an\n"
  1704. " @code{environment:immutable-location} error. Note that, even\n"
  1705. " if an export environment treats a location as immutable, the\n"
  1706. " underlying environment may treat it as mutable, so its\n"
  1707. " value may change.\n"
  1708. "@end table\n"
  1709. "It is an error for an element of signature to specify both\n"
  1710. "@code{mutable-location} and @code{immutable-location}. If\n"
  1711. "neither is specified, @code{immutable-location} is assumed.\n\n"
  1712. "As a special case, if an element of signature is a lone\n"
  1713. "symbol @var{sym}, it is equivalent to an element of the form\n"
  1714. "@code{(sym)}.\n\n"
  1715. "All bindings in @var{exp} are immutable. If you apply\n"
  1716. "@code{environment-define} or @code{environment-undefine} to\n"
  1717. "@var{exp}, Guile will signal an\n"
  1718. "@code{environment:immutable-binding} error. However,\n"
  1719. "notice that the set of bindings in @var{exp} may still change,\n"
  1720. "if the bindings in private change.")
  1721. #define FUNC_NAME s_scm_make_export_environment
  1722. {
  1723. size_t size;
  1724. struct export_environment *body;
  1725. SCM env;
  1726. SCM_ASSERT (SCM_ENVIRONMENT_P (private), private, SCM_ARG1, FUNC_NAME);
  1727. size = sizeof (struct export_environment);
  1728. body = scm_gc_malloc (size, "export environment");
  1729. core_environments_preinit (&body->base);
  1730. body->private = SCM_BOOL_F;
  1731. body->private_observer = SCM_BOOL_F;
  1732. body->signature = SCM_BOOL_F;
  1733. env = scm_make_environment (body);
  1734. core_environments_init (&body->base, &export_environment_funcs);
  1735. body->private = private;
  1736. body->private_observer
  1737. = SCM_ENVIRONMENT_OBSERVE (private, export_environment_observer, env, 1);
  1738. body->signature = SCM_EOL;
  1739. scm_export_environment_set_signature_x (env, signature);
  1740. return env;
  1741. }
  1742. #undef FUNC_NAME
  1743. SCM_DEFINE (scm_export_environment_p, "export-environment?", 1, 0, 0,
  1744. (SCM object),
  1745. "Return @code{#t} if object is an export environment, or\n"
  1746. "@code{#f} otherwise.")
  1747. #define FUNC_NAME s_scm_export_environment_p
  1748. {
  1749. return scm_from_bool (SCM_EXPORT_ENVIRONMENT_P (object));
  1750. }
  1751. #undef FUNC_NAME
  1752. SCM_DEFINE (scm_export_environment_private, "export-environment-private", 1, 0, 0,
  1753. (SCM env),
  1754. "Return the private environment of export environment @var{env}.")
  1755. #define FUNC_NAME s_scm_export_environment_private
  1756. {
  1757. SCM_ASSERT (SCM_EXPORT_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  1758. return EXPORT_ENVIRONMENT (env)->private;
  1759. }
  1760. #undef FUNC_NAME
  1761. SCM_DEFINE (scm_export_environment_set_private_x, "export-environment-set-private!", 2, 0, 0,
  1762. (SCM env, SCM private),
  1763. "Change the private environment of export environment @var{env}.")
  1764. #define FUNC_NAME s_scm_export_environment_set_private_x
  1765. {
  1766. struct export_environment *body;
  1767. SCM_ASSERT (SCM_EXPORT_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  1768. SCM_ASSERT (SCM_ENVIRONMENT_P (private), private, SCM_ARG2, FUNC_NAME);
  1769. body = EXPORT_ENVIRONMENT (env);
  1770. SCM_ENVIRONMENT_UNOBSERVE (private, body->private_observer);
  1771. body->private = private;
  1772. body->private_observer
  1773. = SCM_ENVIRONMENT_OBSERVE (private, export_environment_observer, env, 1);
  1774. return SCM_UNSPECIFIED;
  1775. }
  1776. #undef FUNC_NAME
  1777. SCM_DEFINE (scm_export_environment_signature, "export-environment-signature", 1, 0, 0,
  1778. (SCM env),
  1779. "Return the signature of export environment @var{env}.")
  1780. #define FUNC_NAME s_scm_export_environment_signature
  1781. {
  1782. SCM_ASSERT (SCM_EXPORT_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  1783. return EXPORT_ENVIRONMENT (env)->signature;
  1784. }
  1785. #undef FUNC_NAME
  1786. static SCM
  1787. export_environment_parse_signature (SCM signature, const char* caller)
  1788. {
  1789. SCM result = SCM_EOL;
  1790. SCM l;
  1791. for (l = signature; scm_is_pair (l); l = SCM_CDR (l))
  1792. {
  1793. SCM entry = SCM_CAR (l);
  1794. if (scm_is_symbol (entry))
  1795. {
  1796. SCM new_entry = scm_cons2 (entry, symbol_immutable_location, SCM_EOL);
  1797. result = scm_cons (new_entry, result);
  1798. }
  1799. else
  1800. {
  1801. SCM sym;
  1802. SCM new_entry;
  1803. int immutable = 0;
  1804. int mutable = 0;
  1805. SCM mutability;
  1806. SCM l2;
  1807. SCM_ASSERT (scm_is_pair (entry), entry, SCM_ARGn, caller);
  1808. SCM_ASSERT (scm_is_symbol (SCM_CAR (entry)), entry, SCM_ARGn, caller);
  1809. sym = SCM_CAR (entry);
  1810. for (l2 = SCM_CDR (entry); scm_is_pair (l2); l2 = SCM_CDR (l2))
  1811. {
  1812. SCM attribute = SCM_CAR (l2);
  1813. if (scm_is_eq (attribute, symbol_immutable_location))
  1814. immutable = 1;
  1815. else if (scm_is_eq (attribute, symbol_mutable_location))
  1816. mutable = 1;
  1817. else
  1818. SCM_ASSERT (0, entry, SCM_ARGn, caller);
  1819. }
  1820. SCM_ASSERT (scm_is_null (l2), entry, SCM_ARGn, caller);
  1821. SCM_ASSERT (!mutable || !immutable, entry, SCM_ARGn, caller);
  1822. if (!mutable && !immutable)
  1823. immutable = 1;
  1824. mutability = mutable ? symbol_mutable_location : symbol_immutable_location;
  1825. new_entry = scm_cons2 (sym, mutability, SCM_EOL);
  1826. result = scm_cons (new_entry, result);
  1827. }
  1828. }
  1829. SCM_ASSERT (scm_is_null (l), signature, SCM_ARGn, caller);
  1830. /* Dirk:FIXME:: Now we know that signature is syntactically correct. There
  1831. * are, however, no checks for symbols entered twice with contradicting
  1832. * mutabilities. It would be nice, to implement this test, to be able to
  1833. * call the sort functions conveniently from C.
  1834. */
  1835. return scm_reverse (result);
  1836. }
  1837. SCM_DEFINE (scm_export_environment_set_signature_x, "export-environment-set-signature!", 2, 0, 0,
  1838. (SCM env, SCM signature),
  1839. "Change the signature of export environment @var{env}.")
  1840. #define FUNC_NAME s_scm_export_environment_set_signature_x
  1841. {
  1842. SCM parsed_sig;
  1843. SCM_ASSERT (SCM_EXPORT_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
  1844. parsed_sig = export_environment_parse_signature (signature, FUNC_NAME);
  1845. EXPORT_ENVIRONMENT (env)->signature = parsed_sig;
  1846. return SCM_UNSPECIFIED;
  1847. }
  1848. #undef FUNC_NAME
  1849. void
  1850. scm_environments_prehistory ()
  1851. {
  1852. /* create environment smob */
  1853. scm_tc16_environment = scm_make_smob_type ("environment", 0);
  1854. scm_set_smob_mark (scm_tc16_environment, environment_mark);
  1855. scm_set_smob_free (scm_tc16_environment, environment_free);
  1856. scm_set_smob_print (scm_tc16_environment, environment_print);
  1857. /* create observer smob */
  1858. scm_tc16_observer = scm_make_smob_type ("observer", 0);
  1859. scm_set_smob_mark (scm_tc16_observer, observer_mark);
  1860. scm_set_smob_print (scm_tc16_observer, observer_print);
  1861. /* create system environment */
  1862. scm_system_environment = scm_make_leaf_environment ();
  1863. scm_permanent_object (scm_system_environment);
  1864. }
  1865. void
  1866. scm_init_environments ()
  1867. {
  1868. #include "libguile/environments.x"
  1869. }
  1870. /*
  1871. Local Variables:
  1872. c-file-style: "gnu"
  1873. End:
  1874. */