about summary refs log tree commit diff stats
path: root/apps/calls.subx
diff options
context:
space:
mode:
Diffstat (limited to 'apps/calls.subx')
-rw-r--r--apps/calls.subx167
1 files changed, 167 insertions, 0 deletions
diff --git a/apps/calls.subx b/apps/calls.subx
index 00d7c3ac..6b8b6bc0 100644
--- a/apps/calls.subx
+++ b/apps/calls.subx
@@ -213,4 +213,171 @@ $emit-call:end:
     5d/pop-to-ebp
     c3/return
 
+next-word-string-or-expression-without-metadata:  # line : (address stream), word-slice : (address slice)
+    # pseudocode:
+    #   skip-chars-matching(line, ' ')
+    #   if line->read >= line->write              # end of line
+    #     out = {0, 0}
+    #     return
+    #   out->start = &line->data[line->read]
+    #   if line->data[line->read] == '#'          # comment
+    #     out.end = &line->data[line->write]      # skip to end of line
+    #     return
+    #   if line->data[line->read] == '"'          # string literal
+    #     skip-string(line)
+    #     out.end = &line->data[line->read]         # no metadata
+    #     return
+    #   if line->data[line->read] == '*'          # expression
+    #     if line->data[line->read + 1] == ' '
+    #       abort
+    #     if line->data[line->read + 1] == '('
+    #       skip-until-close-paren(line)
+    #       if (line->data[line->read] != ')'
+    #         abort
+    #       ++line->data[line->read] to skip ')'
+    #     out->end = &line->data[line->read]
+    #     return
+    #   if line->data[line->read] == ')'
+    #     ++line->read to skip ')'
+    #     # make sure there's nothing else of importance
+    #     if line->read >= line->write
+    #       out = {0, 0}
+    #       return
+    #     if line->data[line->read] != ' '
+    #       abort
+    #     skip-chars-matching-whitespace(line)
+    #     if line->read >= line->write
+    #       out = {0, 0}
+    #       return
+    #     if line->data[line->read] != '#'        # only thing permitted after ')' is a comment
+    #       abort
+    #     out.end = &line->data[line->write]      # skip to end of line
+    #     return
+    #   # default case: read a word -- but no metadata
+    #   while true
+    #     if line->read >= line->write
+    #       break
+    #     if line->data[line->read] == ' '
+    #       break
+    #     if line->data[line->read] == '/'
+    #       abort
+    #     ++line->read
+    #   out.end = &line->data[line->read]
+    #
+    # registers:
+    #   ecx: often line->read
+    #   eax: often line->data[line->read]
+    #
+    # . prolog
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    50/push-eax
+    51/push-ecx
+    56/push-esi
+    57/push-edi
+    # skip-chars-matching(line, ' ')
+    # . . push args
+    68/push 0x20/imm32/space
+    ff 6/subop/push *(ebp+8)
+    # . . call
+    e8/call skip-chars-matching/disp32
+    # . . discard args
+    81 0/subop/add %esp 8/imm32
+$next-word-string-or-expression-without-metadata:check0:
+    # if (line->read >= line->write) clear out and return
+    # . eax = line->read
+    8b/-> *(esi+4) 0/r32/eax
+    # . if (eax < line->write) goto next check
+    3b/compare *esi 0/r32/eax
+    7c/jump-if-lesser $next-word-string-or-expression-without-metadata:check-for-comment/disp8
+    # . return out = {0, 0}
+    c7 0/subop/copy *edi 0/imm32
+    c7 0/subop/copy *(edi+4) 0/imm32
+    e9/jump $next-word-string-or-expression-without-metadata:end/disp32
+$next-word-string-or-expression-without-metadata:check-for-comment:
+    # out->start = &line->data[line->read]
+    8b/-> *(esi+4) 1/r32/ecx
+    8d/copy-address *(esi+ecx+0xc) 0/r32/eax
+    89/<- *edi 0/r32/eax
+    # if (line->data[line->read] != '#') goto next check
+    # . eax = line->data[line->read]
+    31/xor %eax 0/r32/eax
+    8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
+    # . if (eax != '#') goto next check
+    3d/compare-eax-and 0x23/imm32/pound
+    75/jump-if-not-equal $next-word-string-or-expression-without-metadata:check-for-string-literal/disp8
+$next-word-string-or-expression-without-metadata:comment:
+    # out->end = &line->data[line->write]
+    8b/-> *esi 0/r32/eax
+    8d/copy-address *(esi+eax+0xc) 0/r32/eax
+    89/<- *(edi+4) 0/r32/eax
+    # line->read = line->write  # skip rest of line
+    8b/-> *esi 0/r32/eax
+    89/<- *(esi+4) 0/r32/eax
+    # return
+    eb/jump $next-word-string-or-expression-without-metadata:end/disp8
+$next-word-string-or-expression-without-metadata:check-for-string-literal:
+    # if (line->data[line->read] != '"') goto next check
+    3d/compare-eax-and 0x22/imm32/dquote
+    75/jump-if-not-equal $next-word-string-or-expression-without-metadata:check-for-expression/disp8
+$next-word-string-or-expression-without-metadata:string-literal:
+    # skip-string(line)
+    # . . push args
+    56/push-esi
+    # . . call
+    e8/call skip-string/disp32
+    # . . discard args
+    81 0/subop/add %esp 4/imm32
+    # out->end = &line->data[line->read]
+    8b/-> *(esi+4) 1/r32/ecx
+    8d/copy-address *(esi+ecx+0xc) 0/r32/eax
+    89/<- *(edi+4) 0/r32/eax
+    # return
+    eb/jump $next-word-string-or-expression-without-metadata:end/disp8
+$next-word-string-or-expression-without-metadata:check-for-expression:
+    # if (line->data[line->read] != '*') goto next check
+    3d/compare-eax-and 0x2a/imm32/asterisk
+    75/jump-if-not-equal $next-word-string-or-expression-without-metadata:check-for-end-of-call/disp8
+    # if (line->data[line->read + 1] == ' ') goto error1
+    8a/copy-byte *(esi+ecx+0xd) 0/r32/AL
+    3d/compare-eax-and 0x20/imm32/space
+    74/jump-if-equal $next-word-string-or-expression-without-metadata:error1/disp8
+    # if (line->data[line->read] != '(') goto regular word
+    3d/compare-eax-and 0x28/imm32/open-paren
+    75/jump-if-not-equal $next-word-string-or-expression-without-metadata:regular-word/disp8
+$next-word-string-or-expression-without-metadata:paren:
+    # skip-until-close-paren(line)
+    # . . push args
+    56/push-esi
+    # . . call
+    e8/call skip-until-close-paren/disp32
+    # . . discard args
+    81 0/subop/add %esp 4/imm32
+    # if (line->data[line->read] != ')') goto error2
+    # . eax = line->data[line->read]
+    8b/-> *(esi+4) 1/r32/ecx
+    8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
+    # . if (eax != ')') goto error2
+    3d/compare-eax-and 0x29/imm32/close-paren
+    75/jump-if-not-equal $next-word-string-or-expression-without-metadata:error2/disp8
+    # skip ')'
+    ff 0/subop/increment *(esi+4)
+    # out->end = &line->data[line->read]
+    8b/-> *(esi+4) 1/r32/ecx
+    8d/copy-address *(esi+ecx+0xc) 0/r32/eax
+    89/<- *(edi+4) 0/r32/eax
+    # return
+    eb/jump $next-word-string-or-expression-without-metadata:end/disp8
+$next-word-string-or-expression-without-metadata:end:
+    # . restore registers
+    5f/pop-to-edi
+    5e/pop-to-esi
+    59/pop-to-ecx
+    58/pop-to-eax
+    # . epilog
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 # . . vim:nowrap:textwidth=0