about summary refs log tree commit diff stats
path: root/cpp/.traces/string-equal-distinct-lengths
blob: 8d2c674d4ae5fd7543c9d590c8b5ac0559162bb8 (plain) (blame)
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
parse/0: instruction: 38
parse/0:   ingredient: {name: "location", value: 0, type: 0, properties: ["location": "type"]}
parse/0:   ingredient: {name: "30", value: 0, type: 0, properties: ["30": "literal"]}
parse/0:   product: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]}
parse/0: instruction: 38
parse/0:   ingredient: {name: "abc", value: 0, type: 0, properties: ["abc": "literal-string"]}
parse/0:   product: {name: "x", value: 0, type: 2-5-4, properties: ["x": "address":"array":"character"]}
parse/0: instruction: 38
parse/0:   ingredient: {name: "abcd", value: 0, type: 0, properties: ["abcd": "literal-string"]}
parse/0:   product: {name: "y", value: 0, type: 2-5-4, properties: ["y": "address":"array":"character"]}
parse/0: instruction: 100
parse/0:   ingredient: {name: "x", value: 0, type: 2-5-4, properties: ["x": "address":"array":"character"]}
parse/0:   ingredient: {name: "y", value: 0, type: 2-5-4, properties: ["y": "address":"array":"character"]}
parse/0:   product: {name: "3", value: 0, type: 3, properties: ["3": "boolean", "raw": ]}
new/0: location -> 1
new/0: abc -> 0
name/0: assign x 1
new/0: abcd -> 0
name/0: assign y 2
after-brace/0: recipe test-string-equal-distinct-lengths
after-brace/0: new ...
after-brace/0: new ...
after-brace/0: new ...
after-brace/0: string-equal ...
new/0: routine allocated memory from 1000 to 101000
schedule/0: test-string-equal-distinct-lengths
run/0: instruction test-string-equal-distinct-lengths/0
mem/0: array size is 30
mem/0: new alloc: 1000
run/0: instruction test-string-equal-distinct-lengths/1
mem/0: storing 1030 in location 1002
run/0: instruction test-string-equal-distinct-lengths/2
mem/0: storing 1034 in location 1003
run/0: instruction test-string-equal-distinct-lengths/3
mem/0: location 1002 is 1030
mem/0: location 1003 is 1034
run/0: instruction string-equal/0
mem/0: array size is 30
mem/0: new alloc: 1039
run/0: instruction string-equal/1
run/0: product 0 is 1030
mem/0: storing 1030 in location 1041
run/0: instruction string-equal/2
mem/0: location 1041 is 1030
mem/0: storing 3 in location 1042
run/0: instruction string-equal/3
run/0: product 0 is 1034
mem/0: storing 1034 in location 1043
run/0: instruction string-equal/4
mem/0: location 1043 is 1034
mem/0: storing 4 in location 1044
run/0: instruction string-equal/6
string-equal/0: comparing lengths
run/0: instruction string-equal/7
run/0: ingredient 0 is a-len
mem/0: location 1042 is 3
run/0: ingredient 1 is b-len
mem/0: location 1044 is 4
run/0: product 0 is 0
mem/0: storing 0 in location 1045
run/0: instruction string-equal/8
mem/0: location 1045 is 0
run/0: ingredient 0 is 0
run/0: jump-if fell through
run/0: instruction string-equal/9
run/0: result 0 is 0
mem/0: storing 0 in location 3
tring.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
# Function calls in a single line.
#
# To run (on Linux):
#   $ ./ntranslate 0*.subx apps/subx-common.subx apps/calls.subx
#   $ mv a.elf apps/calls
#   $ chmod +x apps/calls
#
# Example 1:
#   $ echo '(foo %eax)'                         |  apps/calls
#   # . (foo %eax)                                      # output has comments
#   ff 6/subop/push %eax                                # push
#   e8/call foo/disp32                                  # call
#   81 0/subop/add %esp 4/imm32                         # undo push
#
# Example 2:
#   $ echo '(foo Var1 *(eax + 4) "blah")'       |  apps/calls
#   # . (foo Var1 *(eax + 4) "blah")
#   68/push "blah"/imm32
#   ff 6/subop/push *(eax + 4)                          # push args in..
#   68/push Var1/imm32                                  # ..reverse order
#   e8/call foo/disp32
#   81 0/subop/add %esp 4/imm32                         # undo pushes
#
# Calls always begin with '(' as the first non-whitespace on a line.

== code

Entry:  # run tests if necessary, convert stdin if not
    # . prolog
    89/<- %ebp 4/r32/esp

    # initialize heap
    # . Heap = new-segment(Heap-size)
    # . . push args
    68/push Heap/imm32
    ff 6/subop/push *Heap-size
    # . . call
    e8/call new-segment/disp32
    # . . discard args
    81 0/subop/add %esp 8/imm32

    # - if argc > 1 and argv[1] == "test", then return run_tests()
    # if (argc <= 1) goto run-main
    81 7/subop/compare *ebp 1/imm32
    7e/jump-if-lesser-or-equal $run-main/disp8
    # if (!kernel-string-equal?(argv[1], "test")) goto run-main
    # . eax = kernel-string-equal?(argv[1], "test")
    # . . push args
    68/push "test"/imm32
    ff 6/subop/push *(ebp+8)
    # . . call
    e8/call kernel-string-equal?/disp32
    # . . discard args
    81 0/subop/add %esp 8/imm32
    # . if (eax == 0) goto run-main
    3d/compare-eax-and 0/imm32
    74/jump-if-equal $run-main/disp8
    # run-tests()
    e8/call run-tests/disp32
    # syscall(exit, *Num-test-failures)
    8b/-> *Num-test-failures 3/r32/ebx
    eb/jump $main:end/disp8
$run-main:
    # - otherwise convert stdin
    # convert(Stdin, Stdout)
    # . . push args
    68/push Stdout/imm32
    68/push Stdin/imm32
    # . . call
    e8/call convert/disp32
    # . . discard args
    81 0/subop/add %esp 8/imm32
    # syscall(exit, 0)
    bb/copy-to-ebx 0/imm32
$main:end:
    b8/copy-to-eax 1/imm32/exit
    cd/syscall 0x80/imm8

convert:  # in : (address buffered-file), out : (address buffered-file) -> <void>
    # pseudocode:
    #   var line = new-stream(512, 1)
    #   var words : (address stream slice) = new-stream(16, 8)  # at most function name and 15 args
    #   while true
    #     clear-stream(line)
    #     read-line-buffered(in, line)
    #     if (line->write == 0) break                           # end of file
    #     skip-chars-matching-whitespace(line)
    #     if line->data[line->read] != '('
    #       write-stream-data(out, line)
    #       continue
    #     # emit comment
    #     write-buffered(out, "# ")
    #     write-stream-data(out, line)
    #     # emit code
    #     ++line->read  # skip '('
    #     clear-stream(words)
    #     words = parse-line(line)
    #     emit-call(out, words)
    #   flush(out)
    #
    # . prolog
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    # var line/ecx : (address stream byte) = stream(512)
    81 5/subop/subtract %esp 0x200/imm32
    68/push 0x200/imm32/length
    68/push 0/imm32/read
    68/push 0/imm32/write
    89/<- %ecx 4/r32/esp
    # var words/edx : (address stream slice) = stream(16, 8)
    81 5/subop/subtract %esp 0x80/imm32
    68/push 0x80/imm32/length
    68/push 0/imm32/read
    68/push 0/imm32/write
    89/<- %edx 4/r32/esp
$convert:loop:
    # clear-stream(line)
    # . . push args
    51/push-ecx
    # . . call
    e8/call clear-stream/disp32
    # . . discard args
    81 0/subop/add %esp 4/imm32
    # read-line-buffered(in, line)
    # . . push args
    51/push-ecx
    ff 6/subop/push *(ebp+8)
    # . . call
    e8/call read-line-buffered/disp32
    # . . discard args
    81 0/subop/add %esp 8/imm32
$convert:check0:
    # if (line->write == 0) break
    81 7/subop/compare *ecx 0/imm32
    0f 84/jump-if-equal $convert:break/disp32
    # TODO
    e9/jump $convert:loop/disp32
$convert:break:
    # flush(out)
    # . . push args
    ff 6/subop/push *(ebp+0xc)
    # . . call
    e8/call  flush/disp32
    # . . discard args
    81 0/subop/add %esp 4/imm32
$convert:end:
    # . reclaim locals
    81 0/subop/add %esp 0x298/imm32  # 0x20c + 0x8c
    # . restore registers
    # . epilog
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

parse-line:  # line : (address stream byte), words : (address stream slice)
    # pseudocode:
    #   var word-slice : (address slice)
    #   while true
    #     word-slice = next-word-string-or-expression-without-metadata(line)
    #     if slice-empty?(word-slice)
    #       break                                 # end of line
    #     write-int(words, word-slice->start)
    #     write-int(words, word-slice->end)
    #
    # . prolog
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
$parse-line:end:
    # . reclaim locals
    # . restore registers
    # . epilog
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

emit-call:  # out : (address buffered-file), words : (address stream slice)
    # pseudocode:
    #   if (words->write < 8) abort
    #   curr = &words->data[words->write-8]
    #   min = words->data
    #   # emit pushes
    #   while true
    #     if (curr <= min) break
    #     if (*curr == '%' || *curr == '*')
    #       write-buffered(out, "ff 6/subop/push ")
    #       write-slice-buffered(out, curr)
    #       write-buffered(out, "/imm32\n")
    #     else
    #       write-buffered(out, "68/push ")
    #       write-slice-buffered(out, curr)
    #       write-buffered(out, "/imm32\n")
    #     curr -= 8
    #   # emit call
    #   write-buffered(out, "e8/call ")
    #   write-slice-buffered(out, curr)
    #   write-buffered(out, "/disp32\n")
    #   # emit pops
    #   write-buffered(out, "81 0/subop/add %esp ")
    #   print-int32-buffered(out, words->write >> 1 - 4)
    #   write-buffered(out, "/imm32\n")
    #
    # . prolog
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
$emit-call:end:
    # . reclaim locals
    # . restore registers
    # . epilog
    89/<- %esp  5/r32/ebp
    5d/pop-to-ebp
    c3/return

# . . vim:nowrap:textwidth=0