mirror of
https://github.com/ganelson/inform.git
synced 2024-07-16 22:14:23 +03:00
1167 lines
185 KiB
HTML
1167 lines
185 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>BlockValues Template</title>
|
|
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<meta name="viewport" content="width=device-width initial-scale=1">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
|
|
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<script>
|
|
MathJax = {
|
|
tex: {
|
|
inlineMath: '$', '$'], ['\\(', '\\)'
|
|
},
|
|
svg: {
|
|
fontCache: 'global'
|
|
}
|
|
};
|
|
</script>
|
|
<script type="text/javascript" id="MathJax-script" async
|
|
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
|
|
</script>
|
|
|
|
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
|
|
</head>
|
|
<body class="commentary-font">
|
|
<nav role="navigation">
|
|
<h1><a href="../index.html">
|
|
<img src="../docs-assets/Inform.png" height=72">
|
|
</a></h1>
|
|
<ul><li><a href="../compiler.html">compiler tools</a></li>
|
|
<li><a href="../other.html">other tools</a></li>
|
|
<li><a href="../extensions.html">extensions and kits</a></li>
|
|
<li><a href="../units.html">unit test tools</a></li>
|
|
</ul><h2>Extensions</h2><ul>
|
|
<li><a href="../basic_inform/index.html">basic_inform</a></li>
|
|
<li><a href="../standard_rules/index.html">standard_rules</a></li>
|
|
</ul><h2>Kits</h2><ul>
|
|
<li><a href="index.html"><span class="selectedlink">BasicInformKit</span></a></li>
|
|
<li><a href="../BasicInformExtrasKit/index.html">BasicInformExtrasKit</a></li>
|
|
<li><a href="../CommandParserKit/index.html">CommandParserKit</a></li>
|
|
<li><a href="../EnglishLanguageKit/index.html">EnglishLanguageKit</a></li>
|
|
<li><a href="../WorldModelKit/index.html">WorldModelKit</a></li>
|
|
|
|
</ul>
|
|
</nav>
|
|
<main role="main">
|
|
<!--Weave of 'BlockValues Template' generated by Inweb-->
|
|
<div class="breadcrumbs">
|
|
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../extensions.html">Kits</a></li><li><a href="index.html">BasicInformKit</a></li><li><b>BlockValues Template</b></li></ul></div>
|
|
<p class="purpose">Routines for copying, comparing, creating and destroying block values, and for reading and writing them as if they were arrays.</p>
|
|
|
|
<ul class="toc"><li><a href="S-blc.html#SP1">§1. Overview</a></li><li><a href="S-blc.html#SP2">§2. Short Block Format</a></li><li><a href="S-blc.html#SP3">§3. Long Block Access</a></li><li><a href="S-blc.html#SP4">§4. Weak Kind</a></li><li><a href="S-blc.html#SP5">§5. Reference counting</a></li><li><a href="S-blc.html#SP6">§6. Changing Reference Counts</a></li><li><a href="S-blc.html#SP7">§7. Long Block Capacity</a></li><li><a href="S-blc.html#SP8">§8. Long Block Array Access</a></li><li><a href="S-blc.html#SP9">§9. First Zero Entry</a></li><li><a href="S-blc.html#SP10">§10. Mass Copy Entries</a></li><li><a href="S-blc.html#SP11">§11. Mass Copy From Array</a></li><li><a href="S-blc.html#SP12">§12. KOVS Routines</a></li><li><a href="S-blc.html#SP13">§13. Creation</a></li><li><a href="S-blc.html#SP14">§14. Errors</a></li><li><a href="S-blc.html#SP15">§15. Short Block Allocation</a></li><li><a href="S-blc.html#SP16">§16. Block Values On Stack</a></li><li><a href="S-blc.html#SP17">§17. Freeing</a></li><li><a href="S-blc.html#SP18">§18. Quick Copy</a></li><li><a href="S-blc.html#SP19">§19. Short Block Copy</a></li><li><a href="S-blc.html#SP20">§20. Slow Copy</a></li><li><a href="S-blc.html#SP21">§21. Copy</a></li><li><a href="S-blc.html#SP22">§22. Destruction</a></li><li><a href="S-blc.html#SP23">§23. Recycling</a></li><li><a href="S-blc.html#SP24">§24. Mutability</a></li><li><a href="S-blc.html#SP25">§25. Casting</a></li><li><a href="S-blc.html#SP26">§26. Comparison</a></li><li><a href="S-blc.html#SP27">§27. Hashing</a></li><li><a href="S-blc.html#SP28">§28. Serialisation</a></li><li><a href="S-blc.html#SP29">§29. Debugging</a></li><li><a href="S-blc.html#SP30">§30. Printing Memory Addresses</a></li><li><a href="S-blc.html#SP31">§31. Hexadecimal Printing</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>§1. Overview. </b>Each I7 value is represented at run-time by an I6 word: on the Z-machine,
|
|
a 16-bit number, and on Glulx, a 32-bit number. The correspondence between
|
|
these numbers and the original values depends on the kind of value: "number"
|
|
comes out as a signed twos-complement number, but "time" as an integer
|
|
number of minutes since midnight, "rulebook" as the index of the rulebook
|
|
in order of creation, and so on.
|
|
</p>
|
|
|
|
<p class="commentary">Even if a 32-bit number is available, this is not enough to represent the
|
|
full range of values we might want: consider all the possible hundred-word
|
|
essays of text, for instance. So for a whole range of kinds — "text",
|
|
"list of K", "stored action" and so on — the I6 value at run-time is only
|
|
a pointer to what is called a "short block". This is typically only a few
|
|
words long, and often only a single word: hence the term "short". It has
|
|
no header or other overhead, and its contents depend on the kind of value.
|
|
</p>
|
|
|
|
<p class="commentary">If we know that a given kind of value can be stored in, say, exactly 128
|
|
bits, then it's possible simply to store the whole thing in the short block.
|
|
More often, though, the data needs to be flexible in size, or needs to
|
|
be large. In that case, the short block will include (and sometimes, will
|
|
consist only of) a pointer to data stored in a "long block". Unlike the
|
|
short block, the long block is a chunk of memory stored using the Flex
|
|
system, and thus is genuinely a "block" in the sense of the Flex
|
|
documentation.
|
|
</p>
|
|
|
|
<p class="commentary">It's possible to have several different short blocks each pointing to the
|
|
same long block of underlying data: for example, the result of the I7 code
|
|
</p>
|
|
|
|
<p class="commentary"> let L1 be { 2, 3, 5, 7, 11 };
|
|
let L2 be L1;
|
|
</p>
|
|
|
|
<p class="commentary">is to create L1 and L2 as pointers to two different short blocks, but the
|
|
two SBs each point to the same long block, which contains the data for the
|
|
list 2, 3, 5, 7, 11. Note that this makes it very fast to copy L1's contents
|
|
into L2, because only L2's short block needs to change.
|
|
</p>
|
|
|
|
<p class="commentary">The rules for customers who want to deal with values like this are much like
|
|
the rules for allocating memory with Flex. Calling <span class="extract"><span class="extract-syntax">BlkValueCreate</span></span>
|
|
creates a new value, but this must always, and only once, later be disposed
|
|
of using <span class="extract"><span class="extract-syntax">BlkValueFree</span></span>.
|
|
</p>
|
|
|
|
<p class="commentary">So if the short blocks of L1 and L2 both point to the same long block of
|
|
actual data, what happens when only one of them is freed? The answer is that
|
|
every long block has a reference count attached, which counts the number of
|
|
short blocks pointing to it. In our example, this count is 2. If list L1
|
|
is freed, the long block's reference count is decremented to 1, but it
|
|
remains in memory, and only L1's short block is given up; when list L2 is
|
|
subsequently freed, both its short block and the now unwanted long block
|
|
are given up.
|
|
</p>
|
|
|
|
<p class="commentary">The harder case to handle is what happens when L1 and L2 share a long
|
|
block containing 2, 3, 5, 7, 11, but when the source text asks to "add 13
|
|
to L1". If we simply changed the long block, that would affect L2 as well.
|
|
So we must first make L1 "mutable". This means copying the long block
|
|
to make a new unique copy with reference count 1; assigning that to L1
|
|
in place of the original; and decrementing the reference count of the
|
|
original from 2 to 1. L1 and L2 now point to two different long blocks,
|
|
so it's safe to modify L1's.
|
|
</p>
|
|
|
|
<p class="commentary">Subtle and beautiful bugs can occur as a result of making a value mutable
|
|
at the wrong moment. Beware in particular of reading data out of a long
|
|
block, then writing it back again, because the act of writing may force
|
|
the value owning the long block to become mutable; this will make a new
|
|
copy of the data; but you will be left holding the old copy. Since these
|
|
are functionally identical, you may not even notice, but calamities will
|
|
occur later because the version of the value you're holding really
|
|
belongs to somebody else and may be freed at any point.
|
|
</p>
|
|
|
|
<p class="commentary">Finally, note that the I7 compiler also creates block values representing
|
|
constants. For example, the source text
|
|
</p>
|
|
|
|
<p class="commentary"> let L1 be { 2, 3, 5, 7, 11 };
|
|
</p>
|
|
|
|
<p class="commentary">causes a block value representing this list to be stored in memory. The
|
|
long block for a constant needs to be immortal, since this memory must
|
|
never be freed: it's therefore given a reference count of "infinity".
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">RC_INFINITY</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MAX_POSITIVE_NUMBER</span><span class="plain-syntax">;</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>§2. Short Block Format. </b>A short block begins with a word which is usually, but not always, a pointer
|
|
to the long block. There are three possibilities:
|
|
</p>
|
|
|
|
<ul class="items"><li>(a) 0 means the short block has length 1 and the long block begins at the
|
|
very next word in memory. This makes it more convenient for I7 to compile
|
|
BV constants, but isn't otherwise used.
|
|
</li><li>(b) 1 to 255 means the short block has length 2 or more. The value is expected
|
|
to be a bitmap in bits 4 to 8 together with a nonzero ID in bits 1 to 4.
|
|
If the <span class="extract"><span class="extract-syntax">BLK_BVBITMAP_LONGBLOCK</span></span> bit is set, a pointer to the long block
|
|
is stored in the second word of the short block.
|
|
</li><li>(c) Otherwise the short block has length 1 and contains only a pointer to
|
|
the long block.
|
|
</li></ul>
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP</span><span class="plain-syntax"> = </span><span class="constant-syntax">$ff</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_LONGBLOCK</span><span class="plain-syntax"> = </span><span class="constant-syntax">$10</span><span class="plain-syntax">; </span><span class="comment-syntax">Word 1 of SB is pointer to LB</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_TEXT</span><span class="plain-syntax"> = </span><span class="constant-syntax">$20</span><span class="plain-syntax">; </span><span class="comment-syntax">BV holds a TEXT_TY value</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_CONSTANT</span><span class="plain-syntax"> = </span><span class="constant-syntax">$40</span><span class="plain-syntax">; </span><span class="comment-syntax">BV holds a TEXT_TY value</span>
|
|
|
|
<span class="plain-syntax">#</span><span class="identifier-syntax">IFTRUE</span><span class="plain-syntax"> </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax"> == </span><span class="constant-syntax">4</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_LONGBLOCKMASK</span><span class="plain-syntax"> = </span><span class="constant-syntax">$ffffff10</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_TEXTMASK</span><span class="plain-syntax"> = </span><span class="constant-syntax">$ffffff20</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_CONSTANTMASK</span><span class="plain-syntax"> = </span><span class="constant-syntax">$ffffff40</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">#</span><span class="identifier-syntax">IFNOT</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_LONGBLOCKMASK</span><span class="plain-syntax"> = </span><span class="constant-syntax">$ff10</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_TEXTMASK</span><span class="plain-syntax"> = </span><span class="constant-syntax">$ff20</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_CONSTANTMASK</span><span class="plain-syntax"> = </span><span class="constant-syntax">$ff40</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">#</span><span class="identifier-syntax">ENDIF</span><span class="plain-syntax">;</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>§3. Long Block Access. </b>Illustrating this:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-->0;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> + </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_BVBITMAP</span><span class="plain-syntax"> == </span><span class="identifier-syntax">o</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_BVBITMAP_LONGBLOCK</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-->1;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>§4. Weak Kind. </b>This returns the weak kind ID of a block value. Most of the time this
|
|
information is stored in the long block, but that poses a problem for BVs
|
|
which have no long block: we must use the bitmap instead.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-->0;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">BLK_HEADER_KOV</span><span class="plain-syntax">+1);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_BVBITMAP</span><span class="plain-syntax"> == </span><span class="identifier-syntax">o</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_BVBITMAP_TEXT</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TEXT_TY</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-->1;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax">--></span><span class="identifier-syntax">BLK_HEADER_KOV</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NIL_TY</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>§5. Reference counting. </b>Reference counts lie in a word at a fixed offset from the start of the
|
|
long block: doctrinally, any block value with no long block at all (such
|
|
as a piece of packed text) has reference count infinity.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueGetRefCountPrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--></span><span class="identifier-syntax">BLK_HEADER_RCOUNT</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">RC_INFINITY</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>§6. Changing Reference Counts. </b>When incrementing, infinity's the limit; when decrementing, it never
|
|
reduces. Note that the decrement function returns the new reference count,
|
|
but the increment function returns nothing. It's only when reference counts
|
|
go downwards that we have to worry about whether something happens.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueIncRefCountPrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">refc</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">refc</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--></span><span class="identifier-syntax">BLK_HEADER_RCOUNT</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">refc</span><span class="plain-syntax"> < </span><span class="identifier-syntax">RC_INFINITY</span><span class="plain-syntax">) </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--></span><span class="identifier-syntax">BLK_HEADER_RCOUNT</span><span class="plain-syntax"> = </span><span class="identifier-syntax">refc</span><span class="plain-syntax"> + </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueDecRefCountPrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">refc</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">refc</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--></span><span class="identifier-syntax">BLK_HEADER_RCOUNT</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">refc</span><span class="plain-syntax"> < </span><span class="identifier-syntax">RC_INFINITY</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">refc</span><span class="plain-syntax">--;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">refc</span><span class="plain-syntax"> < </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"reference count negative"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--></span><span class="identifier-syntax">BLK_HEADER_RCOUNT</span><span class="plain-syntax"> = </span><span class="identifier-syntax">refc</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">refc</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">RC_INFINITY</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>§7. Long Block Capacity. </b>As we've seen, the long block has some metadata in a header, but otherwise
|
|
it's organised as if it were an array, with entries 8, 16 or 32 bits wide.
|
|
At any given time, the "capacity" of the LB is the number of entries in
|
|
this array: that doesn't mean that the BV is using them all at any given moment.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueLBCapacity</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">array_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">array_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexTotalSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-></span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_16_BIT</span><span class="plain-syntax">) </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">array_size_in_bytes</span><span class="plain-syntax"> / </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueSetLBCapacity</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">new_capacity</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkMakeMutable</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-></span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_16_BIT</span><span class="plain-syntax">) </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">FlexResize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">, </span><span class="identifier-syntax">new_capacity</span><span class="plain-syntax">*</span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">rtrue</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>§8. Long Block Array Access. </b>Though the customer thinks he's getting an array, in fact the storage in
|
|
the LB is not necessarily contiguous, since it can span multiple Flex blocks.
|
|
We abstract that with two routines to read and write entries.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="extract"><span class="extract-syntax">BlkValueRead</span></span> takes two compulsory arguments and one optional one. Thus:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueRead</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">reads the nth entry in the long block for <span class="extract"><span class="extract-syntax">bv</span></span>, whereas
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueRead</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax">, </span><span class="reserved-syntax">true</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">read it from the given long block directly. <span class="extract"><span class="extract-syntax">BlkValueWrite</span></span> is similar.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueRead</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> </span><span class="identifier-syntax">do_not_indirect</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">do_not_indirect</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-></span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_16_BIT</span><span class="plain-syntax">) </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pos</span><span class="plain-syntax">*</span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (: </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">~=</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">: </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">=</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--></span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"><</span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> + </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax">: </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">->0;</span>
|
|
<span class="plain-syntax"> </span><span class="constant-syntax">2</span><span class="plain-syntax">: #</span><span class="identifier-syntax">Iftrue</span><span class="plain-syntax"> (</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax"> == </span><span class="constant-syntax">2</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-->0;</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifnot</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">->0)*256 + (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">->1);</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="constant-syntax">4</span><span class="plain-syntax">: </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-->0;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> - </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">print_ret</span><span class="plain-syntax"> </span><span class="string-syntax">"*** BlkValueRead: reading from index out of range: "</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="string-syntax">" in "</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="string-syntax">" ***"</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueWrite</span><span class="plain-syntax"> </span><span class="reserved-syntax">to</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> </span><span class="identifier-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">do_not_indirect</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="reserved-syntax">to</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">do_not_indirect</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="reserved-syntax">to</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkMakeMutable</span><span class="plain-syntax">(</span><span class="reserved-syntax">to</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="reserved-syntax">to</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-></span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_16_BIT</span><span class="plain-syntax">) </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pos</span><span class="plain-syntax">*</span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (:</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">~=</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">:</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">=</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--></span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"><</span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> + </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax">: </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">->0 = </span><span class="identifier-syntax">val</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="constant-syntax">2</span><span class="plain-syntax">: #</span><span class="identifier-syntax">Iftrue</span><span class="plain-syntax"> (</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax"> == </span><span class="constant-syntax">2</span><span class="plain-syntax">); </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-->0 = </span><span class="identifier-syntax">val</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifnot</span><span class="plain-syntax">; </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">->0 = (</span><span class="identifier-syntax">val</span><span class="plain-syntax">/256)%256; </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">->1 = </span><span class="identifier-syntax">val</span><span class="plain-syntax">%256;</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="constant-syntax">4</span><span class="plain-syntax">: </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-->0 = </span><span class="identifier-syntax">val</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> - </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">print_ret</span><span class="plain-syntax"> </span><span class="string-syntax">"*** BlkValueWrite: writing to index out of range: "</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="string-syntax">" in "</span><span class="plain-syntax">, </span><span class="reserved-syntax">to</span><span class="plain-syntax">, </span><span class="string-syntax">" ***"</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>§9. First Zero Entry. </b>This returns the entry index of the first zero entry in the long block's array,
|
|
or -1 if it has no zeros.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueSeekZeroEntry</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> -1;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-></span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_16_BIT</span><span class="plain-syntax">) </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (: </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">~=</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">: </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">=</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--></span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> + </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax">:</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">: </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> < </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">: </span><span class="identifier-syntax">addr</span><span class="plain-syntax">++)</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">addr</span><span class="plain-syntax">->0 == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> + </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> - </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="constant-syntax">2</span><span class="plain-syntax">:</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">iftrue</span><span class="plain-syntax"> </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax"> == </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">: </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> < </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">: </span><span class="identifier-syntax">addr</span><span class="plain-syntax">=</span><span class="identifier-syntax">addr</span><span class="plain-syntax">+2)</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">addr</span><span class="plain-syntax">-->0 == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> + </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> - </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">)/2;</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifnot</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">: </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> < </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">: </span><span class="identifier-syntax">addr</span><span class="plain-syntax">=</span><span class="identifier-syntax">addr</span><span class="plain-syntax">+2)</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">addr</span><span class="plain-syntax">->0 == </span><span class="constant-syntax">0</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">addr</span><span class="plain-syntax">->1 == </span><span class="constant-syntax">0</span><span class="plain-syntax">))</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> + </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> - </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">)/2;</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="constant-syntax">4</span><span class="plain-syntax">:</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">: </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> < </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">: </span><span class="identifier-syntax">addr</span><span class="plain-syntax">=</span><span class="identifier-syntax">addr</span><span class="plain-syntax">+4)</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">addr</span><span class="plain-syntax">-->0 == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> + </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> - </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">)/4;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> + </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> -1;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP10" class="paragraph-anchor"></a><b>§10. Mass Copy Entries. </b>This copies a given number of entries from one BV's long block to another;
|
|
they must both be of the same word size but can differ in header size.
|
|
Functionally, it's identical to
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">n</span><span class="plain-syntax">=0: </span><span class="identifier-syntax">n</span><span class="plain-syntax"><</span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">: </span><span class="identifier-syntax">n</span><span class="plain-syntax">++)</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueWrite</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax">, </span><span class="identifier-syntax">BlkValueRead</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax">));</span>
|
|
</pre>
|
|
<p class="commentary">but it's much, much faster, and runs in a reasonably small number of cycles
|
|
given what it needs to do.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueMassCopyEntries</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_entries_to_copy</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_header_size_in_bytes</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_header_size_in_bytes</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">min</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkMakeMutable</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax">-></span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_16_BIT</span><span class="plain-syntax">) </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & (</span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax"> + </span><span class="identifier-syntax">BLK_FLAG_TRUNCMULT</span><span class="plain-syntax">)) &&</span>
|
|
<span class="plain-syntax"> (</span><span class="identifier-syntax">BlkValueSetLBCapacity</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">) == </span><span class="reserved-syntax">false</span><span class="plain-syntax">))</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy resizing failed"</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">from_header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">-></span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">from_header_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">from_header_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">to_header_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">to_header_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax">*</span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="reserved-syntax">true</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax">--></span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy destination exhausted"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">from_header_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">from_header_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">--></span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy source exhausted"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">to_header_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">to_header_size_in_bytes</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">min</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax">; </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> < </span><span class="identifier-syntax">min</span><span class="plain-syntax">) </span><span class="identifier-syntax">min</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax"> <= </span><span class="identifier-syntax">min</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Memcpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">, </span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Memcpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">, </span><span class="identifier-syntax">min</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax"> - </span><span class="identifier-syntax">min</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> + </span><span class="identifier-syntax">min</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax"> - </span><span class="identifier-syntax">min</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> + </span><span class="identifier-syntax">min</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> - </span><span class="identifier-syntax">min</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP11" class="paragraph-anchor"></a><b>§11. Mass Copy From Array. </b>The following is helpful when reading an array of characters into a text:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueMassCopyFromArray</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_array</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_entry_size</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_entries_to_copy</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_entry_size</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkMakeMutable</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">-></span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_16_BIT</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax"> = </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & (</span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax"> + </span><span class="identifier-syntax">BLK_FLAG_TRUNCMULT</span><span class="plain-syntax">)) &&</span>
|
|
<span class="plain-syntax"> (</span><span class="identifier-syntax">BlkValueSetLBCapacity</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">) == </span><span class="reserved-syntax">false</span><span class="plain-syntax">))</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy resizing failed"</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> & </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax">)/</span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> > </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Arrcpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_array</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_entry_size</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> - </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_array</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_array</span><span class="plain-syntax"> + </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax">*</span><span class="identifier-syntax">from_entry_size</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">--></span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy source exhausted"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax">)/</span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> > </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Arrcpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_array</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_entry_size</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP12" class="paragraph-anchor"></a><b>§12. KOVS Routines. </b>Different kinds of value use different data formats for both their short and
|
|
long blocks, so it follows that each kind needs its own routines to carry out
|
|
the fundamental operations of creating, destroying, copying and comparing.
|
|
This is organised at run-time by giving each kind of block value a "KOVS", a
|
|
"kind of value support" routine. These are named systematically by suffixing
|
|
<span class="extract"><span class="extract-syntax">_Support</span></span>: that is, the support function for <span class="extract"><span class="extract-syntax">TEXT_TY</span></span> is called
|
|
<span class="extract"><span class="extract-syntax">TEXT_TY_Support</span></span> and so on.
|
|
</p>
|
|
|
|
<p class="commentary">I7 automatically compiles a function called <span class="extract"><span class="extract-syntax">KOVSupportFunction</span></span> which returns
|
|
the KOVS for a given kind. Note that this depends only on the weak kind, not
|
|
the strong one: so "list of numbers" and "list of texts", for example, share a
|
|
common KOVS which handles all list support.
|
|
</p>
|
|
|
|
<p class="commentary">The support function can be called with any of the following task constants
|
|
as its first argument: it then has a further one to three arguments
|
|
depending on the task in hand.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">CREATE_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">CAST_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">DESTROY_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">3</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">MAKEMUTABLE_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">4</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">COPYKIND_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">5</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">EXTENT_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">6</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">COPYQUICK_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">7</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">COPYSB_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">8</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">KINDDATA_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">9</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">COPY_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">10</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">COMPARE_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">11</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">READ_FILE_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">12</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_FILE_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">13</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">HASH_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">14</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">DEBUG_KOVS</span><span class="plain-syntax"> = </span><span class="constant-syntax">15</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="comment-syntax">Constant BLKVALUE_TRACE; ! Uncomment this to expose masses of tracery</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP13" class="paragraph-anchor"></a><b>§13. Creation. </b>To create a block value, call:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueCreate</span><span class="plain-syntax">(</span><span class="identifier-syntax">kind</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">where <span class="extract"><span class="extract-syntax">K</span></span> is its (strong) kind ID. Optionally, call:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueCreate</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">to mandate that the short block needs to be located at the given address
|
|
outside the heap: but don't do this unless you can guarantee that space of the
|
|
necessary length will be available there for as long as the lifetime of
|
|
the value; and please note, it really does matter that this address lies
|
|
outside the heap, for reasons to be seen below.
|
|
</p>
|
|
|
|
<p class="commentary">These work by delegating to:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">CREATE_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">strong_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">which returns the address of the short block for the new value.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCreate</span><span class="plain-syntax"> </span><span class="identifier-syntax">strong_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> = </span><span class="identifier-syntax">KOVSupportFunction</span><span class="plain-syntax">(</span><span class="identifier-syntax">strong_kind</span><span class="plain-syntax">, </span><span class="string-syntax">"impossible allocation"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">CREATE_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">strong_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLKVALUE_TRACE</span><span class="plain-syntax">; </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Created: "</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax">) </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">; #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="comment-syntax">The new value is represented in I6 as the pointer to its short block:</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP14" class="paragraph-anchor"></a><b>§14. Errors. </b>No I7 source text should ever result in a call to this, unless it does
|
|
unpleasant things at the I6 level.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax"> </span><span class="identifier-syntax">reason</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"*** Value handling failed: "</span><span class="plain-syntax">, (</span><span class="reserved-syntax">string</span><span class="plain-syntax">) </span><span class="identifier-syntax">reason</span><span class="plain-syntax">, </span><span class="string-syntax">" ***^"</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">RunTimeProblem</span><span class="plain-syntax">(</span><span class="identifier-syntax">RTP_HEAPERROR</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> @</span><span class="reserved-syntax">quit</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP15" class="paragraph-anchor"></a><b>§15. Short Block Allocation. </b>The first thing a KOVS does when creating a value is to initialise its
|
|
short block. The following routines provide for a one-word and a two-word
|
|
short block respectively. The KOVS should pass these routines the same
|
|
<span class="extract"><span class="extract-syntax">short_block</span></span> value it was called with. As can be seen, if this is zero
|
|
then we need to conjure up memory from somewhere: we do this using Flex.
|
|
That incurs a fair amount of overhead in time and memory, though. The
|
|
SB data is stored in the data portion of the Flex block, which is why
|
|
we get its address from by adding the data offset to the block address.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCreateSB1</span><span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">val</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">short_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexAllocate</span><span class="plain-syntax">(</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) + </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">-->0 = </span><span class="identifier-syntax">val</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCreateSB2</span><span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">val1</span><span class="plain-syntax"> </span><span class="identifier-syntax">val2</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">short_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexAllocate</span><span class="plain-syntax">(2*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) + </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">-->0 = </span><span class="identifier-syntax">val1</span><span class="plain-syntax">; </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">-->1 = </span><span class="identifier-syntax">val2</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP16" class="paragraph-anchor"></a><b>§16. Block Values On Stack. </b>As noted above, it's wasteful to keep allocating short blocks using Flex.
|
|
For the short blocks of block values in local variables, we store them on
|
|
a stack instead. This is a top-down stack, so the current stack frame
|
|
starts out just after the end of the stack area in memory (and therefore
|
|
points to an empty stack frame); it drops down as new frames are created.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="extract"><span class="extract-syntax">BlkValueCreateOnStack</span></span> acts exactly like <span class="extract"><span class="extract-syntax">BlkValueCreate</span></span>, but stores
|
|
the short block at the given word offset in the current stack frame.
|
|
(I7 compiles calls to these routines when compiling code to manage
|
|
local variables.)
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">StackFramingInitialise</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax"> = </span><span class="identifier-syntax">blockv_stack</span><span class="plain-syntax"> + </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">*</span><span class="identifier-syntax">BLOCKV_STACK_SIZE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">StackFrameCreate</span><span class="plain-syntax"> </span><span class="identifier-syntax">size</span><span class="plain-syntax"> </span><span class="identifier-syntax">new</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">new</span><span class="plain-syntax"> = </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax"> - </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">*</span><span class="identifier-syntax">size</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">new</span><span class="plain-syntax"> < </span><span class="identifier-syntax">blockv_stack</span><span class="plain-syntax">) { </span><span class="identifier-syntax">RunTimeProblem</span><span class="plain-syntax">(</span><span class="identifier-syntax">RTP_HEAPERROR</span><span class="plain-syntax">); @</span><span class="reserved-syntax">quit</span><span class="plain-syntax">; }</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax"> = </span><span class="identifier-syntax">new</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCreateOnStack</span><span class="plain-syntax"> </span><span class="identifier-syntax">offset</span><span class="plain-syntax"> </span><span class="identifier-syntax">strong_kind</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueCreate</span><span class="plain-syntax">(</span><span class="identifier-syntax">strong_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax"> + </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">*</span><span class="identifier-syntax">offset</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueFreeOnStack</span><span class="plain-syntax"> </span><span class="identifier-syntax">offset</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueFree</span><span class="plain-syntax">(</span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax"> + </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">*</span><span class="identifier-syntax">offset</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP17" class="paragraph-anchor"></a><b>§17. Freeing. </b>As noted above, every value returned by <span class="extract"><span class="extract-syntax">BlkValueCreate</span></span> must later be
|
|
freed by calling the following routine exactly once:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueFree</span><span class="plain-syntax">(</span><span class="identifier-syntax">value</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">In particular, if a block value is stored in any I6 location which is about
|
|
to be overwritten with a new value, it's essential to call this in order
|
|
properly to dispose of the old value.
|
|
</p>
|
|
|
|
<p class="commentary">As noted above, short blocks are sometimes created within Flex blocks on
|
|
the heap, using <span class="extract"><span class="extract-syntax">FlexAllocate</span></span>; and if this is one of those, we need to free
|
|
the relevant Flex block.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueFree</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> </span><span class="identifier-syntax">d</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="comment-syntax">Dispose of any data in the long block</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> = </span><span class="identifier-syntax">KOVSupportFunction</span><span class="plain-syntax">(</span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">), </span><span class="string-syntax">"impossible deallocation"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueDestroyPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="comment-syntax">Free any heap memory occupied by the short block</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">d</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> - </span><span class="identifier-syntax">Flex_Heap</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">d</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">d</span><span class="plain-syntax"> < </span><span class="identifier-syntax">MEMORY_HEAP_SIZE</span><span class="plain-syntax"> + </span><span class="constant-syntax">16</span><span class="plain-syntax">))</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">FlexFree</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax"> - </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP18" class="paragraph-anchor"></a><b>§18. Quick Copy. </b>The basic method of copying block value B into block value A is to destroy the
|
|
old contents of A, which are about to be overwritten; then copy the short
|
|
block of A into the short block of B, a quick process; and increment the
|
|
reference count of B.
|
|
</p>
|
|
|
|
<p class="commentary">The support function should respond to:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">COPYSB_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">by copying the short blocks alone.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueQuickCopyPrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueDestroyPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">COPYSB_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueIncRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP19" class="paragraph-anchor"></a><b>§19. Short Block Copy. </b>In fact, most of the work of copying a short block is standard. If a SB
|
|
consists only a single word pointing to the LB, the first routine below
|
|
handles all the work needed to handle the <span class="extract"><span class="extract-syntax">COPYSB_KOVS</span></span> task. The
|
|
surprising line in this routine is to deal with the convention that a
|
|
pointer value of 0 means the LB immediately follows the SB: if that's
|
|
true in <span class="extract"><span class="extract-syntax">from_bv</span></span>, it won't be true in <span class="extract"><span class="extract-syntax">to_bv</span></span>, so we must correct it.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCopySB1</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">-->0 = </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">-->0;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">-->0 == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">-->0 = </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> + </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCopySB2</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">-->0 = </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">-->0;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">-->1 = </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">-->1;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">-->1 == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">-->1 = </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> + </span><span class="constant-syntax">2</span><span class="plain-syntax">*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP20" class="paragraph-anchor"></a><b>§20. Slow Copy. </b>Why don't we always do this? Consider the case where B is a list of rooms, and
|
|
A is a list of objects. If we give A's short block a pointer to the long block
|
|
of B, A will suddenly change its kind as well as its contents, because the
|
|
strong kind of a list is stored inside the long block. So there are a few
|
|
cases where it's not safe to make a quick copy. In any case, sooner or later
|
|
you have to duplicate actual data, not just rearrange pointers to it, and
|
|
here's where.
|
|
</p>
|
|
|
|
<p class="commentary">We first call:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">KINDDATA_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">which asks for an ID for the kinds stored in the BV: for example, for a
|
|
list of rooms it would return the kind ID for "room". We ask for this
|
|
because it's information stored in the long block, which is about to be
|
|
overwritten.
|
|
</p>
|
|
|
|
<p class="commentary">As with the quick copy, we must now make sure any data currently in the
|
|
destination is properly destroyed. We could do so by making the destination
|
|
mutable and then destroying its contents, but that would be inefficient,
|
|
in that it might create a whole lot of temporary copies and then delete
|
|
them again. So if the long block has a high reference count, we decrement
|
|
it and then replace the short block (in place) with a fresh one pointing
|
|
to empty data; we only destroy the contents if the long block has reference
|
|
count 1.
|
|
</p>
|
|
|
|
<p class="commentary">All of which finally means we can scribble over the destination without
|
|
spoiling anybody else's day. We resize it to make room for the incoming data;
|
|
we copy the raw data of the long block; and finally we:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">COPY_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">k</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">This is where the KOVS should make a proper copy, using <span class="extract"><span class="extract-syntax">BlkValueCopy</span></span> and
|
|
thus perhaps recursing, if any of that data contained block values in turn:
|
|
as for instance it will if we're copying a list of texts. Note that <span class="extract"><span class="extract-syntax">k</span></span>
|
|
is the value given us by <span class="extract"><span class="extract-syntax">KINDDATA_KOVS</span></span>.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueSlowCopyPrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> </span><span class="identifier-syntax">recycling</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">k</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">k</span><span class="plain-syntax"> = </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">KINDDATA_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">recycling</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueRecyclePrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">EXTENT_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> == -1) </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueLBCapacity</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueMassCopyEntries</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">COPY_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">k</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP21" class="paragraph-anchor"></a><b>§21. Copy. </b>As noted above, some copies are quick, and some are slow. We decide by
|
|
asking the kind's support function:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">COPYQUICK_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">which should return true if a quick copy is okay, or false if not.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCopy</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy to null value"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy from null value"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> == </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLKVALUE_TRACE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Copy: "</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="string-syntax">" to equal "</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax">) </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">to_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">from_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_kind</span><span class="plain-syntax"> ~= </span><span class="identifier-syntax">from_kind</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy incompatible kinds"</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> = </span><span class="identifier-syntax">KOVSupportFunction</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_kind</span><span class="plain-syntax">, </span><span class="string-syntax">"impossible copy"</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">COPYQUICK_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">))</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueQuickCopyPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueSlowCopyPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">, </span><span class="reserved-syntax">true</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCopyAZ</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueCopy</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP22" class="paragraph-anchor"></a><b>§22. Destruction. </b>We will also need primitives for two different forms of destruction. This
|
|
is something which should happen whenever a block value is thrown away,
|
|
not to be used again: either because it's being freed, or because new
|
|
contents are being copied into it.
|
|
</p>
|
|
|
|
<p class="commentary">The idea of destruction is that any data stored in the long block should
|
|
safely be disposed of. If the reference count of the long block is 2 or
|
|
more, there's no problem, because we can simply decrement the count and
|
|
let other people worry about the data from now on. But if it's only 1,
|
|
then destroying the data is on us. Since we don't know what's in the
|
|
long block, we have to ask the KOVS to do this by means of:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">DESTROY_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">Note that all of this frequently causes recursion: destruction leads to
|
|
freeing of some of the data, which in turn means that that data must be
|
|
destroyed, and so on. So it's essential that block values be well-founded:
|
|
a list must not, for example, contain itself.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueDestroyPrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLKVALUE_TRACE</span><span class="plain-syntax">; </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Destroying "</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax">) </span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">; #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">BlkValueDecRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">DESTROY_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) </span><span class="identifier-syntax">FlexFree</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP23" class="paragraph-anchor"></a><b>§23. Recycling. </b>This is like destruction in that it disposes of the value safely, but it
|
|
tries to keep the long block for reuse, rather than deallocating it. This
|
|
won't work if other people are still using it, so in the case where its
|
|
reference count is 2 or more, we simply reduce the count by 1 and then
|
|
replace the small block with a new one (at the same address).
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueRecyclePrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLKVALUE_TRACE</span><span class="plain-syntax">; </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Recycling "</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax">) </span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">; #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">BlkValueDecRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">DESTROY_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueIncRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueCreate</span><span class="plain-syntax">(</span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">), </span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP24" class="paragraph-anchor"></a><b>§24. Mutability. </b>A block value is by definition mutable if it has a long block with reference
|
|
count 1, because then the data in the long block can freely be changed without
|
|
corrupting other block values.
|
|
</p>
|
|
|
|
<p class="commentary">We offer the KOVS a chance to handle this for us:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">MAKEMUTABLE_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">should return 0 to say that it has done so, or else return the size of the
|
|
short block in words to ask us to handle it. The way we do this is to create
|
|
a temporary value to make a safe copy into; it would be unnecessarily slow
|
|
to allocate the short block for this safe copy on the heap and then free it
|
|
again moments later, so instead we put the short block on the stack, making
|
|
a temporary one-value stack frame instead to hold it.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkMakeMutable</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">block</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> </span><span class="identifier-syntax">sb_size</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to make null block mutable"</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">BlkValueGetRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) > </span><span class="constant-syntax">1</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLKVALUE_TRACE</span><span class="plain-syntax">; </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Make mutable: "</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax">) </span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">; #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueDecRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> = </span><span class="identifier-syntax">KOVSupportFunction</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax">, </span><span class="string-syntax">"impossible mutability"</span><span class="plain-syntax">);</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">sb_size</span><span class="plain-syntax"> = </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">MAKEMUTABLE_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">sb_size</span><span class="plain-syntax"> > </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> @</span><span class="identifier-syntax">push</span><span class="plain-syntax"> </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">StackFrameCreate</span><span class="plain-syntax">(</span><span class="identifier-syntax">sb_size</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueCreateOnStack</span><span class="plain-syntax">(0, </span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">COPYKIND_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueSlowCopyPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">, </span><span class="reserved-syntax">false</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">COPYSB_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> @</span><span class="identifier-syntax">pull</span><span class="plain-syntax"> </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP25" class="paragraph-anchor"></a><b>§25. Casting. </b>We can also perform an assignment to an already-created block value in the
|
|
form of a cast, that is, a conversion of data from one kind to another:
|
|
or at least, for some kinds of value we can.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">CAST_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">original_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">original_value</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">casts from the given value, with the given kind, into the existing block
|
|
value <span class="extract"><span class="extract-syntax">to_bv</span></span>. Note that the source value doesn't need to be a BV itself.
|
|
This mechanism is used, for example, to cast snippets to text.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCast</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">original_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">original_value</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> = </span><span class="identifier-syntax">KOVSupportFunction</span><span class="plain-syntax">(</span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">), </span><span class="string-syntax">"impossible cast"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">CAST_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">original_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">original_value</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP26" class="paragraph-anchor"></a><b>§26. Comparison. </b>And it's a similar story with comparison:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">COMPARE_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv_left</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv_right</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">looks at the data in the two BVs and returns 0 if they are equal, a positive
|
|
number if <span class="extract"><span class="extract-syntax">bv_right</span></span> is "greater than" <span class="extract"><span class="extract-syntax">bv_left</span></span>, and a negative number if
|
|
not. The interpretation of "greater than" depends on the kind, but should be
|
|
something which the user would find natural.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCompare</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv_left</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv_right</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind_left</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind_right</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">bv_left</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">bv_right</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv_left</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv_right</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> -1;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kind_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv_left</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kind_right</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv_right</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">kind_left</span><span class="plain-syntax"> ~= </span><span class="identifier-syntax">kind_right</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind_left</span><span class="plain-syntax"> - </span><span class="identifier-syntax">kind_right</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> = </span><span class="identifier-syntax">KOVSupportFunction</span><span class="plain-syntax">(</span><span class="identifier-syntax">kind_left</span><span class="plain-syntax">, </span><span class="string-syntax">"impossible comparison"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">COMPARE_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv_left</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv_right</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP27" class="paragraph-anchor"></a><b>§27. Hashing. </b>Given a value of any kind, assign it a hash code which fits in a single
|
|
virtual machine word, maximizing the chances that two different values
|
|
will have different hash codes.
|
|
</p>
|
|
|
|
<p class="commentary">If the value can be stored in a single word already, it can be its own
|
|
hash code. Otherwise, we ask:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">HASH_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">to return one for us. Whatever this does, it must at minimum have the
|
|
property that two equivalent blocks (for which <span class="extract"><span class="extract-syntax">COMPARE_KOVS</span></span> returns 0)
|
|
produce the same hash value.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">GetHashValue</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">value</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">KOVIsBlockValue</span><span class="plain-syntax">(</span><span class="identifier-syntax">kind</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueHash</span><span class="plain-syntax">(</span><span class="identifier-syntax">value</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">value</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueHash</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> = </span><span class="identifier-syntax">KOVSupportFunction</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax">, </span><span class="string-syntax">"impossible hashing"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">HASH_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP28" class="paragraph-anchor"></a><b>§28. Serialisation. </b>Some block values can be written to external files (on Glulx): others cannot.
|
|
The following routines abstract that.
|
|
</p>
|
|
|
|
<p class="commentary">If <span class="extract"><span class="extract-syntax">ch</span></span> is \(-1\), then:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">READ_FILE_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">auxf</span><span class="plain-syntax">, </span><span class="identifier-syntax">ch</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">returns <span class="extract"><span class="extract-syntax">true</span></span> or <span class="extract"><span class="extract-syntax">false</span></span> according to whether it is possible to read data
|
|
from an auxiliary file <span class="extract"><span class="extract-syntax">auxf</span></span> into the block value <span class="extract"><span class="extract-syntax">bv</span></span>. If <span class="extract"><span class="extract-syntax">ch</span></span> is any
|
|
other value, then the routine should do exactly that, taking <span class="extract"><span class="extract-syntax">ch</span></span> to be the
|
|
first character of the text read from the file which makes up the serialised
|
|
form of the data.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">WRITE_FILE_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary">is simpler because, strictly speaking, it doesn't write to a file at all: it
|
|
simply prints a serialised form of the data in <span class="extract"><span class="extract-syntax">bv</span></span> to the output stream.
|
|
Since it is called only when that output stream has been redirected to an
|
|
auxiliary file, and since the serialised form would often be illegible on
|
|
screen, it seems reasonable to call it a file input-output function just the
|
|
same. The <span class="extract"><span class="extract-syntax">WRITE_FILE_KOVS</span></span> should return <span class="extract"><span class="extract-syntax">true</span></span> or <span class="extract"><span class="extract-syntax">false</span></span> according to
|
|
whether it was able to write the data.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueReadFromFile</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">auxf</span><span class="plain-syntax"> </span><span class="identifier-syntax">ch</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> = </span><span class="identifier-syntax">KOVSupportFunction</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">kovs</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">READ_FILE_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">auxf</span><span class="plain-syntax">, </span><span class="identifier-syntax">ch</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueWriteToFile</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> = </span><span class="identifier-syntax">KOVSupportFunction</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">kovs</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">WRITE_FILE_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP29" class="paragraph-anchor"></a><b>§29. Debugging. </b>Surprisingly, the above system of reference-counted double indirection didn't
|
|
work first time, so it turned out to be useful to have these routines on hand.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">flag</span><span class="plain-syntax"> </span><span class="identifier-syntax">refc</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"(BV"</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkDebugAddress</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">flag</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax">-->0 == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"..."</span><span class="plain-syntax">; </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"-->"</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"L"</span><span class="plain-syntax">; </span><span class="identifier-syntax">BlkDebugAddress</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">, </span><span class="identifier-syntax">flag</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">" 2**"</span><span class="plain-syntax">, </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-></span><span class="identifier-syntax">BLK_HEADER_N</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">refc</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">refc</span><span class="plain-syntax"> == </span><span class="identifier-syntax">RC_INFINITY</span><span class="plain-syntax">) </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">" resident"</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> { </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">" "</span><span class="plain-syntax">, </span><span class="identifier-syntax">refc</span><span class="plain-syntax">, </span><span class="string-syntax">" ref"</span><span class="plain-syntax">; </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">refc</span><span class="plain-syntax"> ~= </span><span class="constant-syntax">1</span><span class="plain-syntax">) </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"s"</span><span class="plain-syntax">; }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">kovs</span><span class="plain-syntax"> = </span><span class="identifier-syntax">KOVSupportFunction</span><span class="plain-syntax">(</span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">));</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">kovs</span><span class="plain-syntax">) </span><span class="identifier-syntax">kovs</span><span class="plain-syntax">(</span><span class="identifier-syntax">DEBUG_KOVS</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">")"</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP30" class="paragraph-anchor"></a><b>§30. Printing Memory Addresses. </b>The point of the anonymity flag is that, with this set, the output can be
|
|
used as the required output in an Inform test case without tiny movements
|
|
in memory between builds invalidating this required output.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkDebugAddress</span><span class="plain-syntax"> </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> </span><span class="identifier-syntax">flag</span><span class="plain-syntax"> </span><span class="identifier-syntax">d</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flag</span><span class="plain-syntax">) { </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"###"</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">d</span><span class="plain-syntax"> = </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> - </span><span class="identifier-syntax">blockv_stack</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">d</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">d</span><span class="plain-syntax"> <= </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">*</span><span class="identifier-syntax">BLOCKV_STACK_SIZE</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"s+"</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkPrintHexadecimal</span><span class="plain-syntax">) </span><span class="identifier-syntax">d</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">d</span><span class="plain-syntax"> = </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> - </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"=f"</span><span class="plain-syntax">; </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">d</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"+"</span><span class="plain-syntax">; </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="identifier-syntax">d</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">d</span><span class="plain-syntax"> = </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> - </span><span class="identifier-syntax">Flex_Heap</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">d</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">d</span><span class="plain-syntax"> < </span><span class="identifier-syntax">MEMORY_HEAP_SIZE</span><span class="plain-syntax"> + </span><span class="constant-syntax">16</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"h+"</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkPrintHexadecimal</span><span class="plain-syntax">) </span><span class="identifier-syntax">d</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> (</span><span class="identifier-syntax">BlkPrintHexadecimal</span><span class="plain-syntax">) </span><span class="identifier-syntax">addr</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP31" class="paragraph-anchor"></a><b>§31. Hexadecimal Printing. </b></p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkPrintHexadecimal</span><span class="plain-syntax"> </span><span class="identifier-syntax">v</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">iftrue</span><span class="plain-syntax"> </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax"> == </span><span class="constant-syntax">4</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax"> & </span><span class="constant-syntax">$ffff0000</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax"> & </span><span class="constant-syntax">$ff000000</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$10000000</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$1000000</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$100000</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$10000</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$1000</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$100</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$10</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax"> </span><span class="identifier-syntax">v</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">v</span><span class="plain-syntax"> = </span><span class="identifier-syntax">v</span><span class="plain-syntax"> & </span><span class="constant-syntax">$F</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax"> < </span><span class="constant-syntax">10</span><span class="plain-syntax">) </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="identifier-syntax">v</span><span class="plain-syntax">; </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> (</span><span class="identifier-syntax">char</span><span class="plain-syntax">) </span><span class="character-syntax">'A'</span><span class="plain-syntax"> + </span><span class="identifier-syntax">v</span><span class="plain-syntax"> - </span><span class="constant-syntax">10</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<nav role="progress"><div class="progresscontainer">
|
|
<ul class="progressbar"><li class="progressprev"><a href="S-flx.html">❮</a></li><li class="progresssection"><a href="S-dfn.html">dfn</a></li><li class="progresssection"><a href="S-utl.html">utl</a></li><li class="progresssection"><a href="S-gll.html">gll</a></li><li class="progresssection"><a href="S-zmc.html">zmc</a></li><li class="progresssection"><a href="S-prg.html">prg</a></li><li class="progresssection"><a href="S-mth.html">mth</a></li><li class="progresssection"><a href="S-fl.html">fl</a></li><li class="progresssection"><a href="S-srt.html">srt</a></li><li class="progresssection"><a href="S-tbl.html">tbl</a></li><li class="progresssection"><a href="S-mst.html">mst</a></li><li class="progresssection"><a href="S-rlb.html">rlb</a></li><li class="progresssection"><a href="S-flx.html">flx</a></li><li class="progresscurrent">blc</li><li class="progresssection"><a href="S-txt.html">txt</a></li><li class="progresssection"><a href="S-unc.html">unc</a></li><li class="progresssection"><a href="S-chr.html">chr</a></li><li class="progresssection"><a href="S-rgx.html">rgx</a></li><li class="progresssection"><a href="S-lst.html">lst</a></li><li class="progresssection"><a href="S-cmb.html">cmb</a></li><li class="progresssection"><a href="S-rlt.html">rlt</a></li><li class="progresssection"><a href="S-rlt2.html">rlt2</a></li><li class="progresssection"><a href="S-rtp.html">rtp</a></li><li class="progressnext"><a href="S-txt.html">❯</a></li></ul></div>
|
|
</nav><!--End of weave-->
|
|
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|