1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-03-26 00:34:17 -07:00

Write "advanced topics" chapter of the user guide.

Copied from Perforce
 Change: 180303
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2012-11-03 17:38:57 +00:00
parent f16a8b3629
commit d1bc2a6855
10 changed files with 507 additions and 308 deletions

View file

@ -1,12 +1,13 @@
;;; test-common.scm -- common definitions for the Scheme tests
(define (check exp result)
(write-string "test: ") (write exp) (newline)
(write-string "expect: ") (write result) (newline)
(define actually (eval exp))
(write-string "got: ") (write actually) (newline)
(if (not (equal? actually result))
(error "failed!")))
(let ((actually (eval exp)))
(if (not (equal? actually result))
(begin
(write-string "test: ") (write exp) (newline)
(write-string "expect: ") (write result) (newline)
(write-string "got: ") (write actually) (newline)
(error "failed!")))))
;; Return (f (f (f ... (f a) ... ))) with n invocations of f.
(define (church n f a)

View file

@ -0,0 +1,448 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="510"
height="390"
id="svg2"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="New document 1">
<defs
id="defs4">
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend"
style="overflow:visible">
<path
id="path3899"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="DotM"
orient="auto"
refY="0"
refX="0"
id="DotM"
style="overflow:visible">
<path
id="path3955"
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none"
transform="matrix(0.4,0,0,0.4,2.96,0.4)"
inkscape:connector-curvature="0" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="288.99598"
inkscape:cy="182.34538"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1276"
inkscape:window-height="756"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid2985"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-662.36218)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect2987"
width="90"
height="20"
x="80"
y="672.36218" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="90"
y="686.36218"
id="text3757"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3759"
x="90"
y="686.36218"
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Verdana;-inkscape-font-specification:Verdana">TABLE</tspan></text>
<rect
y="692.36218"
x="80"
height="20"
width="90"
id="rect3761"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<text
sodipodi:linespacing="125%"
id="text3763"
y="706.36218"
x="90"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Verdana;-inkscape-font-specification:Verdana"
y="706.36218"
x="90"
id="tspan3765"
sodipodi:role="line">keys</tspan></text>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3767"
width="90"
height="20"
x="80"
y="712.36218" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="90"
y="726.36218"
id="text3769"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3771"
x="90"
y="726.36218"
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Verdana;-inkscape-font-specification:Verdana">values</tspan></text>
<rect
y="892.36218"
x="140"
height="20"
width="90"
id="rect3773"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<text
sodipodi:linespacing="125%"
id="text3775"
y="906.36218"
x="150"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Verdana;-inkscape-font-specification:Verdana"
y="906.36218"
x="150"
id="tspan3777"
sodipodi:role="line">STRING</tspan></text>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3779"
width="90"
height="30"
x="140"
y="912.36218" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="150"
y="932.36218"
id="text3781"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3783"
x="150"
y="932.36218"
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Verdana;-inkscape-font-specification:Verdana">&quot;name&quot;</tspan></text>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3791"
width="90"
height="20"
x="270"
y="892.36218" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="280"
y="906.36218"
id="text3793"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3795"
x="280"
y="906.36218"
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Verdana;-inkscape-font-specification:Verdana">SYMBOL</tspan></text>
<rect
y="912.36218"
x="270"
height="20"
width="90"
id="rect3797"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<text
sodipodi:linespacing="125%"
id="text3799"
y="926.36218"
x="280"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Verdana;-inkscape-font-specification:Verdana"
y="926.36218"
x="280"
id="tspan3801"
sodipodi:role="line">name</tspan></text>
<rect
y="792.36218"
x="10"
height="20"
width="90"
id="rect3809"
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3815"
width="90"
height="20"
x="10"
y="812.36218" />
<rect
y="832.36218"
x="10"
height="20"
width="90"
id="rect3821"
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3827"
width="90"
height="20"
x="10"
y="852.36218" />
<rect
y="872.36218"
x="10"
height="20"
width="90"
id="rect3829"
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3831"
width="90"
height="20"
x="10"
y="892.36218" />
<rect
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3833"
width="90"
height="20"
x="10"
y="912.36218" />
<rect
y="932.36218"
x="10"
height="20"
width="90"
id="rect3835"
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3837"
width="90"
height="20"
x="10"
y="952.36218" />
<rect
y="972.36218"
x="10"
height="20"
width="90"
id="rect3839"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3841"
width="90"
height="20"
x="10"
y="992.36218" />
<rect
y="1012.3622"
x="10"
height="20"
width="90"
id="rect3843"
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3845"
width="90"
height="20"
x="390"
y="792.36218" />
<rect
y="812.36218"
x="390"
height="20"
width="90"
id="rect3847"
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3849"
width="90"
height="20"
x="390"
y="832.36218" />
<rect
y="852.36218"
x="390"
height="20"
width="90"
id="rect3851"
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3853"
width="90"
height="20"
x="390"
y="872.36218" />
<rect
y="892.36218"
x="390"
height="20"
width="90"
id="rect3855"
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="912.36218"
x="390"
height="20"
width="90"
id="rect3857"
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3859"
width="90"
height="20"
x="390"
y="932.36218" />
<rect
y="952.36218"
x="390"
height="20"
width="90"
id="rect3861"
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3863"
width="90"
height="20"
x="390"
y="972.36218" />
<rect
y="992.36218"
x="390"
height="20"
width="90"
id="rect3865"
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3867"
width="90"
height="20"
x="390"
y="1012.3622" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM);marker-end:url(#Arrow1Mend)"
d="m 150,722.36218 240,70"
id="path3871"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM);marker-end:url(#Arrow1Mend)"
d="m 150,702.36218 c 30,0 40,0 40,20 0,10 0.007,6.68771 0,30 0,20 -10,20 -40,20 -28.52438,0 -57.43061,0.005 -100,0 -30,0 -40,0 -40,20"
id="path3875"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccscc" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM);marker-end:url(#Arrow1Mend)"
d="m 460,982.36218 c 30,0 40,0 40,-30 l 0,-150 c 0,-20 -10,-30 -30,-30 -40,0 -70.83211,0 -170,0 -19.06193,0 -30,10 -30,30 0,17.94046 0,49.89376 0,90"
id="path3879"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccsssc" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM);marker-end:url(#Arrow1Mend)"
d="m 80,982.36218 c 30,0 40,0 40,-20 l 0,-50 c 0,-20 10,-20 20,-20"
id="path3883"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM);marker-end:url(#Arrow1Mend)"
d="m 340,922.36218 c 0,20 0,30 -20,30 l -40,0 c -20,0 -30,-10 -30,-39 0,-31 -10,-41 -30,-41 l -50,0 c -20,0 -30,0 -30,20"
id="path3885"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="20"
y="1046.3622"
id="text4699"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4701"
x="20"
y="1046.3622"
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Verdana;-inkscape-font-specification:Verdana">keys</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4703"
y="1046.3622"
x="400"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Verdana;-inkscape-font-specification:Verdana"
y="1046.3622"
x="400"
id="tspan4705"
sodipodi:role="line">values</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -170,11 +170,11 @@ implements the environment as a list of *frames*, each of which is a
list of *bindings*, each binding being a pair of a symbol and its
value, as shown here:
.. figure:: ../diagrams/scheme-env.svg
:align: center
:alt: Diagram: The environment data structure in the Scheme interpreter.
.. figure:: ../diagrams/scheme-env.svg
:align: center
:alt: Diagram: The environment data structure in the Scheme interpreter.
The environment data structure in the Scheme interpreter.
The environment data structure in the Scheme interpreter.
In this case, because the evaluation is taking place at top level,
there is only one frame in the environment (the global frame). And

View file

@ -11,3 +11,5 @@ Guide
lang
debug
perf
advanced

View file

@ -32,14 +32,14 @@ I'll be quoting the relevant sections of code as needed, but you may
find it helpful to experiment with this interpeter yourself, in either
of its versions:
:download:`scheme-malloc.c <../../../example/scheme/scheme-malloc.c>`
:download:`scheme-malloc.c <../../../example/scheme/scheme-malloc.c>`
The Scheme interpreter before integration with the MPS, using
:term:`malloc` and :term:`free (2)` for memory management.
The Scheme interpreter before integration with the MPS, using
:term:`malloc` and :term:`free (2)` for memory management.
:download:`scheme.c <../../../example/scheme/scheme.c>`
:download:`scheme.c <../../../example/scheme/scheme.c>`
The Scheme interpreter after integration with the MPS.
The Scheme interpreter after integration with the MPS.
This simple interpreter allocates two kinds of objects on the
:term:`heap`:
@ -476,11 +476,11 @@ The :term:`forward method` is a function of type
object, and its task is to replace the old object with a
:term:`forwarding object` pointing to the new location of the object.
.. figure:: ../diagrams/copying.svg
:align: center
:alt: Diagram: Copying garbage collection.
.. figure:: ../diagrams/copying.svg
:align: center
:alt: Diagram: Copying garbage collection.
Copying garbage collection.
Copying garbage collection.
The forwarding object must satisfy these properties:
@ -785,6 +785,8 @@ And finally the :term:`pool`::
single: root; creating
single: Scheme; root
.. _guide-lang-root:
Roots
-----

View file

@ -75,11 +75,11 @@ Technical introduction
The figure below gives a simplified picture of a program's memory from
the point of view of the Memory Pool System.
.. figure:: ../diagrams/overview.svg
:align: center
:alt: Diagram: Overview of the Memory Pool System.
.. figure:: ../diagrams/overview.svg
:align: center
:alt: Diagram: Overview of the Memory Pool System.
Overview of the Memory Pool System.
Overview of the Memory Pool System.
The **arena** is the top-level data structure in the MPS. An
:term:`arena` is responsible for requesting :term:`memory (3)` from

View file

@ -16,8 +16,8 @@ AWL (Automatic Weak Linked)
===========================
**AWL** is an :term:`automatically managed <automatic memory
management>` :term:`pool class` that may contain :term:`weak
references (1)`.
management>` :term:`non-moving <non-moving garbage collector>`
:term:`pool class` that may contain :term:`weak references (1)`.
The purpose of this pool class is to allow the client to implement
:term:`weak-key <weak-key hash table>`, :term:`weak-value <weak-value
@ -117,7 +117,8 @@ Dependent objects
In order to support prompt deletion of values in a :term:`weak-key
hash table` when the key is :term:`splatted <splat>` (and prompt
deletion of keys in a :term:`weak-value hash table`), an AWL pool
allows each object to have a :dfn:`dependent object`.
allows each object to have a :dfn:`dependent object`. (This is where
the "Linked" in the name of the pool class comes from.)
The dependent object is specified by the ``find_dependent`` argument
to :c:func:`mps_pool_create` when creating an AWL pool. This is a
@ -355,4 +356,4 @@ AWL interface
The dependent object need not be in memory managed by the MPS, but
if it is, then it must be in a :term:`non-moving <non-moving
garbage collection>` pool in the same arena as ``addr``.
garbage collector>` pool in the same arena as ``addr``.

View file

@ -107,108 +107,11 @@ program that registers the same block multiple times must cope with
either behaviour.
.. index::
single: finalization; example
single: Scheme; finalization
single: Scheme; ports
Example: ports in Scheme
------------------------
In Scheme, an open file is represented by a *port*. In the toy Scheme
example, a port is a wrapper around a Standard C file handle::
typedef struct port_s {
type_t type; /* TYPE_PORT */
obj_t name; /* name of stream */
FILE *stream;
} port_s;
The Scheme procedure ``open-input-file`` takes a filename and returns
a port:
.. code-block:: c
:emphasize-lines: 21
/* (open-input-file filename)
* Opens filename for input, with empty file options, and returns the
* obtained port.
* See R4RS 6.10.1
*/
static obj_t entry_open_input_file(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t filename;
FILE *stream;
obj_t port;
mps_addr_t port_ref;
eval_args(operator->operator.name, env, op_env, operands, 1, &filename);
unless(TYPE(filename) == TYPE_STRING)
error("%s: argument must be a string", operator->operator.name);
stream = fopen(filename->string.string, "r");
if(stream == NULL)
error("%s: cannot open input file", operator->operator.name);
port = make_port(filename, stream);
port_ref = port;
mps_finalize(arena, &port_ref);
return port;
}
Each time around the readevalprint loop, the interpreter polls the
message queue for finalization messages, and when it finds one it
closes the port's underlying file handle:
.. code-block:: c
:emphasize-lines: 9, 12
mps_message_type_t type;
while (mps_message_queue_type(&type, arena)) {
mps_message_t message;
mps_bool_t b;
b = mps_message_get(&message, arena, type);
assert(b); /* we just checked there was one */
if (type == mps_message_type_finalization()) {
mps_addr_t port_ref;
obj_t port;
mps_message_finalization_ref(&port_ref, arena, message);
port = port_ref;
assert(TYPE(port) == TYPE_PORT);
printf("Port to file \"%s\" is dying. Closing file.\n",
port->port.name->string.string);
(void)fclose(port->port.stream);
} else {
/* ... handle other message types ... */
}
mps_message_discard(arena, message);
}
Here's an example session showing finalization taking place:
.. code-block:: none
:emphasize-lines: 8
MPS Toy Scheme Example
9960, 0> (open-input-file "scheme.c")
#[port "scheme.c"]
10064, 0> (gc)
Collection started.
Why: Client requests: immediate full collection.
Clock: 3401
Port to file "scheme.c" is dying. Closing file.
Collection finished.
live 10040
condemned 10088
not_condemned 0
clock: 3807
.. index::
pair: finalization; cautions
.. _topic-finalization-cautions:
Cautions
--------
@ -233,7 +136,9 @@ Cautions
finalization messages are only processed at the end of the
readevalprint loop, so a program that opens many files may run
out of handles even though the associated objects are all
finalizable, as shown here::
finalizable, as shown here:
.. code-block:: none
MPS Toy Scheme Example
9960, 0> (define (repeat n f _) (if (eqv? n 0) '() (repeat (- n 1) f (f))))

View file

@ -291,6 +291,8 @@ For example::
.. index::
pair: object format; cautions
.. _topic-format-cautions:
Cautions
--------

View file

@ -20,6 +20,8 @@ client program needs to recognize and correctly deal with such cases).
The interface is intended to support (amongst other things)
address-based hash tables and that will be used as a running example.
See the section :ref:`guide-advanced-location` in the Guide for a more
detailed look at this example.
Terminology
@ -45,49 +47,6 @@ if any of the blocks whose location has been depended on might have
moved since the respective dependency was made.
.. index::
single: location dependency; example
single: hash table; address-based example
single: Scheme; address-based hash table
Example: ``eq?`` hash table
---------------------------
The toy Scheme interpreter contains a simple address-based (``eq?``)
hash table implementation. It hashes the addresses of its keys, and so
depends on their location.
If it fails to take account of this location dependency, the hash
tables become invalid after a garbage collection. In the interaction
shown below (with a naïve version of the code) you'll see that
although the keys remain present in the table after garbage
collection, they cannot be found. This is because their locations (and
hence their hashes) have changed, but their positions in the table
have not been updated to match.
.. code-block:: none
MPS Toy Scheme Example
10240, 0> (define ht (make-eq-hashtable))
ht
10584, 0> (hashtable-set! ht 'one 1)
10768, 0> (hashtable-set! ht 'two 2)
10952, 0> (hashtable-set! ht 'three 3)
11136, 0> ht
#[hashtable (two 2) (three 3) (one 1)]
11136, 0> (hashtable-ref ht 'two #f)
2
11280, 0> (gc)
11304, 1> (hashtable-ref ht 'one #f)
#f
11448, 1> (hashtable-ref ht 'two #f)
#f
11592, 1> (hashtable-ref ht 'three #f)
#f
11736, 1> ht
#[hashtable (two 2) (three 3) (one 1)]
.. index::
single: location dependency; creating
@ -99,49 +58,28 @@ The :term:`client program` must provide space for the
larger structure. This structure can be in memory managed by the MPS
or elsewhere; that doesn't matter.
For example, the Scheme interpreter inlines the location dependency in
its hash table structure:
For example, the toy Scheme interpreter inlines the location
dependency in its hash table structure:
.. code-block:: c
:emphasize-lines: 3
:emphasize-lines: 5
typedef struct table_s {
type_t type; /* TYPE_TABLE */
hash_t hash; /* hash function */
cmp_t cmp; /* comparison function */
mps_ld_s ld; /* location dependency */
obj_t buckets; /* hash buckets */
} table_s;
Before the first use, the location dependency must be reset by calling
function :c:func:`mps_ld_reset`.
the function :c:func:`mps_ld_reset`.
.. note::
This means that it is not possible to statically create a location
dependency that has been reset.
For example:
.. code-block:: c
:emphasize-lines: 15
static obj_t make_table(void)
{
obj_t obj;
mps_addr_t addr;
size_t size = ALIGN(sizeof(table_s));
do {
mps_res_t res = mps_reserve(&addr, obj_ap, size);
if (res != MPS_RES_OK) error("out of memory in make_table");
obj = addr;
obj->table.type = TYPE_TABLE;
obj->table.buckets = NULL;
} while (!mps_commit(obj_ap, addr, size));
total += size;
obj->table.buckets = make_buckets(8);
mps_ld_reset(&obj->table.ld, arena);
return obj;
}
You can call :c:func:`mps_ld_reset` at any later point to clear all
dependencies from the structure. For example, this is normally done
whenever :c:func:`mps_ld_isstale` returns true.
@ -164,43 +102,20 @@ references from one dependency to another.
For example, in an address-based hash table implementation, each key
that is added to the table must be added to the dependency before its
address is hashed. In the toy Scheme interpreter, addresses are hashed
during the call to the function ``buckets_find``, so the key must be
added to the location dependency before that:
address is hashed. In the toy Scheme interpreter this is most easily
done in the function that hashes an address:
.. code-block:: c
:emphasize-lines: 4
static int table_try_set(obj_t tbl, obj_t key, obj_t value)
static unsigned long eq_hash(obj_t obj, mps_ld_t ld)
{
struct bucket_s *b;
mps_ld_add(&tbl->table.ld, arena, key);
b = buckets_find(tbl->table.buckets, key);
if (b == NULL)
return 0;
if (b->key == NULL)
b->key = key;
b->value = value;
return 1;
union {char s[sizeof(obj_t)]; obj_t addr;} u;
if (ld) mps_ld_add(ld, arena, obj);
u.addr = obj;
return hash(u.s, sizeof(obj_t));
}
static void table_set(obj_t tbl, obj_t key, obj_t value)
{
if (!table_try_set(tbl, key, value)) {
int res;
table_rehash(tbl, tbl->table.buckets->buckets.length * 2, NULL);
res = table_try_set(tbl, key, value);
assert(res); /* rehash should have made room */
}
}
.. note::
The garbage collector may run at any time during this operation,
so the table may already be stale while the new key and value are
being added. We postpone worrying about this until the next
lookup, when the staleness will be discovered.
.. index::
single: location dependency; testing staleness
@ -244,46 +159,15 @@ point you need to:
3. re-add a dependency on each block.
For example, in the case of a hash table you should rehash based on
the new locations of the blocks:
the new locations of the blocks.
.. code-block:: c
:emphasize-lines: 13, 19, 37
/* Rehash 'tbl' so that it has 'new_length' buckets. If 'key' is found
* during this process, return the bucket containing 'key', otherwise
* return NULL.
*/
static struct bucket_s *table_rehash(obj_t tbl, size_t new_length, obj_t key)
{
size_t i;
obj_t new_buckets;
struct bucket_s *key_bucket = NULL;
assert(tbl->type.type == TYPE_TABLE);
new_buckets = make_buckets(new_length);
mps_ld_reset(&tbl->table.ld, arena);
for (i = 0; i < tbl->table.buckets->buckets.length; ++i) {
struct bucket_s *old_b = &tbl->table.buckets->buckets.bucket[i];
if (old_b->key != NULL) {
struct bucket_s *b;
mps_ld_add(&tbl->table.ld, arena, old_b->key);
b = buckets_find(new_buckets, old_b->key);
assert(b != NULL); /* new table shouldn't be full */
assert(b->key == NULL); /* shouldn't be in new table */
*b = *old_b;
if (b->key == key) key_bucket = b;
}
}
tbl->table.buckets = new_buckets;
return key_bucket;
}
:emphasize-lines: 6
static obj_t table_ref(obj_t tbl, obj_t key)
{
struct bucket_s *b = buckets_find(tbl->table.buckets, key);
if (b && b->key != NULL)
struct bucket_s *b = buckets_find(tbl, tbl->table.buckets, key, NULL);
if (b && b->key != NULL && b->key != obj_deleted)
return b->value;
if (mps_ld_isstale(&tbl->table.ld, arena, key)) {
b = table_rehash(tbl, tbl->table.buckets->buckets.length, key);
@ -306,52 +190,6 @@ back to a non-address-based version of the computation: here, since
it might as well find the bucket containing ``key`` at the same time
and return it.
By adding the line::
puts("Stale!");
after :c:func:`mps_ld_isstale` returns true, we get to see when the
location dependency becomes stale and the table has to be rehashed.
.. code-block:: none
:emphasize-lines: 21, 23
MPS Toy Scheme Example
10240, 0> (define ht (make-eq-hashtable))
ht
10584, 0> (hashtable-set! ht 'one 1)
10768, 0> ht
#[hashtable (one 1)]
10768, 0> (gc)
10792, 1> (hashtable-ref ht 'one #f)
Stale!
1
11080, 1> (hashtable-set! ht 'two 2)
11264, 1> (gc)
11288, 2> (hashtable-ref ht 'one #f)
Stale!
1
11576, 2> (hashtable-set! ht 'three 3)
11760, 2> (hashtable-ref ht 'two #f)
2
11904, 2> (gc)
11928, 3> (hashtable-ref ht 'one #f)
1
12072, 3> (hashtable-ref ht 'two #f)
Stale!
2
12360, 3> (hashtable-ref ht 'three #f)
3
.. note::
In case you're puzzled by the highlighted lines: the symbol
``'one`` must not have been moved by the collection, and so was
found in the table at the correct location. Thus
:c:func:`mps_ld_isstale` was not called. The symbol ``'two`` did
move in the collection, so it's not found in the table, and that
causes :c:func:`mps_ld_isstale` to be tested.
.. index::
pair: location dependency; thread safety