about summary refs log blame commit diff stats
path: root/512array.mu
blob: b2a0ceb0b82c45722d596329cd08b075f5d97bd1 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #
# Inserting and deleting in arrays.
#
# The primitives here just do the work of making space and compacting.

fn slide-up _a: (addr array int), start: int, end: int, target: int {
  var a/esi: (addr array int) <- copy _a
  var src-idx/ecx: int <- copy start
  var dest-idx/edx: int <- copy target
  # if start == target, nothing to do
  {
    compare src-idx, dest-idx
    break-if-!=
    return
  }
  # if start < target, abort
  {
    compare src-idx, dest-idx
    break-if->
    abort "slide-up: target > start; use slide-down instead"
  }
  # perform the copy
  {
    compare src-idx, end
    break-if->=
    var dest/ebx: (addr int) <- index a, dest-idx
    var src/eax: (addr int) <- index a, src-idx
    var val/eax: int <- copy *src
    copy-to *dest, val
    src-idx <- increment
    dest-idx <- increment
    loop
  }
}

fn slide-down _a: (addr array int), start: int, end: int, target: int {
  var a/esi: (addr array int) <- copy _a
  var src-idx/ecx: int <- copy end
  src-idx <- decrement
  var dest-idx/edx: int <- copy target
  dest-idx <- add end
  dest-idx <- subtract start
  dest-idx <- decrement
  # if start == target, nothing to do
  {
    compare src-idx, dest-idx
    break-if-!=
    return
  }
  # if start > target, abort
  {
    compare src-idx, dest-idx
    break-if-<
    abort "slide-down: target < start; use slide-down instead"
  }
  # perform the copy
  {
    compare src-idx, start
    break-if-<
    var dest/ebx: (addr int) <- index a, dest-idx
    var src/eax: (addr int) <- index a, src-idx
    var val/eax: int <- copy *src
    copy-to *dest, val
    src-idx <- decrement
    dest-idx <- decrement
    loop
  }
}

fn test-slide-up {
  check-slide-up "0 1 2 3 0", 1/start 1/end, 0/target, "0 1 2 3 0", "F - test-slide-up/empty-interval"
  check-slide-up "0 1 2 3 0", 1/start 2/end, 0/target, "1 1 2 3 0", "F - test-slide-up/single-non-overlapping"
  check-slide-up "0 0 0 1 2 3 0", 3/start 6/end, 0/target, "1 2 3 1 2 3 0", "F - test-slide-up/multiple-non-overlapping"
  check-slide-up "0 1 2 3 0", 1/start 4/end, 0/target, "1 2 3 3 0", "F - test-slide-up/overlapping"
}

fn test-slide-down {
  check-slide-down "0 1 2 3 0", 1/start 1/end, 4/target, "0 1 2 3 0", "F - test-slide-down/empty-interval"
  check-slide-down "0 1 2 3 0", 1/start 2/end, 4/target, "0 1 2 3 1", "F - test-slide-down/single-non-overlapping"
  check-slide-down "0 1 2 3 0 0 0", 1/start 4/end, 4/target, "0 1 2 3 1 2 3", "F - test-slide-down/multiple-non-overlapping"
  check-slide-down "0 1 2 3 0", 1/start 4/end, 2/target, "0 1 1 2 3", "F - test-slide-down/overlapping"
}

# Return the index that val is at.
# If not found, return len-1.
# That way the result is always a valid index to pass into slide-down.
fn find-slide-down-slot-in-array _a: (addr array int), _val: int -> _/ecx: int {
  var a/esi: (addr array int) <- copy _a
  var val/ebx: int <- copy _val
  var max/edx: int <- length a
  max <- decrement
  var i/ecx: int <- copy 0
  {
    compare i, max
    break-if->=
    var curr/eax: (addr int) <- index a, i
    compare *curr, val
    break-if-=
    i <- increment
    loop
  }
  return i
}

# helpers for tests
fn check-slide-up before: (addr array byte), start: int, end: int, target: int, after: (addr array byte), msg: (addr array byte) {
  var arr-h: (handle array int)
  var arr-ah/eax: (addr handle array int) <- address arr-h
  parse-array-of-decimal-ints before, arr-ah
  var arr/eax: (addr array int) <- lookup *arr-ah
  slide-up arr, start, end, target
  check-array-equal arr, after, msg
}

fn check-slide-down before: (addr array byte), start: int, end: int, target: int, after: (addr array byte), msg: (addr array byte) {
  var arr-h: (handle array int)
  var arr-ah/eax: (addr handle array int) <- address arr-h
  parse-array-of-decimal-ints before, arr-ah
  var arr/eax: (addr array int) <- lookup *arr-ah
  slide-down arr, start, end, target
  check-array-equal arr, after, msg
}
class="na">class="LineNr">54 </span> <span class="subxS1Comment"># . restore registers</span> <span id="L55" class="LineNr">55 </span> 59/pop-to-ecx <span id="L56" class="LineNr">56 </span> <span class="subxS1Comment"># . epilogue</span> <span id="L57" class="LineNr">57 </span> 89/&lt;- %esp 5/r32/ebp <span id="L58" class="LineNr">58 </span> 5d/pop-to-ebp <span id="L59" class="LineNr">59 </span> c3/return </pre> </body> </html> <!-- vim: set foldmethod=manual : -->