diff options
-rw-r--r-- | apps/calls.subx | 167 | ||||
-rwxr-xr-x | apps/sigils | bin | 52856 -> 52840 bytes | |||
-rw-r--r-- | apps/sigils.subx | 50 |
3 files changed, 200 insertions, 17 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 diff --git a/apps/sigils b/apps/sigils index 745b71e5..a26d299c 100755 --- a/apps/sigils +++ b/apps/sigils Binary files differdiff --git a/apps/sigils.subx b/apps/sigils.subx index 2e1daa4a..aaf67833 100644 --- a/apps/sigils.subx +++ b/apps/sigils.subx @@ -1650,6 +1650,32 @@ test-emit-direct-mode-2: # * ... -> error: no space after '*' # *(... -> error: *(...) expression must be all on a single line next-word-or-expression: # line : (address stream byte), out : (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] + # return + # if line->data[line->read] == '"' # string literal + # skip-string(line) + # else 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 ')' + # skip-chars-not-matching-whitespace(line) + # out->end = &line->data[line->read] + # + # registers: + # ecx: often line->read + # eax: often line->data[line->read] + # # . prolog 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -1690,7 +1716,7 @@ $next-word-or-expression:check-for-comment: # . eax = line->data[line->read] 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL - # . compare + # . if (eax != '#') goto next check 3d/compare-eax-and 0x23/imm32/pound 75/jump-if-not-equal $next-word-or-expression:check-for-string-literal/disp8 $next-word-or-expression:comment: @@ -1705,12 +1731,8 @@ $next-word-or-expression:comment: eb/jump $next-word-or-expression:end/disp8 $next-word-or-expression:check-for-string-literal: # if (line->data[line->read] != '"') goto next check - # . eax = line->data[line->read] - 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax - 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL - # . compare 3d/compare-eax-and 0x22/imm32/dquote - 75/jump-if-not-equal $next-word-or-expression:check-for-paren/disp8 + 75/jump-if-not-equal $next-word-or-expression:check-for-expression/disp8 $next-word-or-expression:string-literal: # skip-string(line) # . . push args @@ -1721,22 +1743,15 @@ $next-word-or-expression:string-literal: 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # skip rest of word eb/jump $next-word-or-expression:regular-word/disp8 -$next-word-or-expression:check-for-paren: +$next-word-or-expression:check-for-expression: # if (line->data[line->read] != '*') goto next check - # . eax = line->data[line->read] - 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax - 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL - # . compare 3d/compare-eax-and 0x2a/imm32/asterisk 75/jump-if-not-equal $next-word-or-expression:regular-word/disp8 - # if (line->data[line->read] == ' ') goto error1 + # if (line->data[line->read + 1] == ' ') goto error1 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xd/disp8 . # copy byte at *(esi+ecx+12+1) to AL - # . compare 3d/compare-eax-and 0x20/imm32/space 74/jump-if-equal $next-word-or-expression:error1/disp8 - # if (line->data[line->read] != '(') goto regular word - 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xd/disp8 . # copy byte at *(esi+ecx+12+1) to AL - # . compare + # if (line->data[line->read + 1] != '(') goto regular word 3d/compare-eax-and 0x28/imm32/open-paren 75/jump-if-not-equal $next-word-or-expression:regular-word/disp8 $next-word-or-expression:paren: @@ -1748,9 +1763,10 @@ $next-word-or-expression:paren: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # if (line->data[line->read] != ')') goto error2 + # . eax = line->data[line->read] 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL - # . compare + # . if (eax != ')') goto error2 3d/compare-eax-and 0x29/imm32/close-paren 75/jump-if-not-equal $next-word-or-expression:error2/disp8 # skip ')' |