Translating common bits from sigils.subx expression-aware variant of
next-word to use sigils in calls.subx.
This commit is contained in:
Kartik Agaram 2019-09-03 18:02:33 -07:00
parent ae07bf353c
commit 904a053e9c
3 changed files with 200 additions and 17 deletions

View File

@ -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

Binary file not shown.

View File

@ -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 ')'