couple of helpers for parsing expressions in parens

This commit is contained in:
Kartik Agaram 2019-08-22 00:25:41 -07:00
parent db1874cae2
commit ab87ccf62e
2 changed files with 330 additions and 0 deletions

Binary file not shown.

View File

@ -792,6 +792,336 @@ test-emit-indirect-mode-2:
5d/pop-to-EBP
c3/return
# update line->read to end of string literal surrounded by double quotes
# line->read must start out at a double-quote
skip-until-close-paren: # line : (address stream)
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# . save registers
50/push-EAX
51/push-ECX
52/push-EDX
# ECX = line
8b/copy 1/mod/*+disp8 5/rm32/EBP . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX
# EAX = skip-until-close-paren-in-slice(&line->data[line->read], &line->data[line->write])
# . . push &line->data[line->write]
8b/copy 1/mod/*+disp8 1/rm32/ECX . . 2/r32/EDX 8/disp8 . # copy *(ECX+8) to EDX
8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ECX 2/index/EDX . 2/r32/EDX 0xc/disp8 . # copy ECX+EDX+12 to EDX
52/push-EDX
# . . push &line->data[line->read]
8b/copy 1/mod/*+disp8 1/rm32/ECX . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX
8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ECX 2/index/EDX . 2/r32/EDX 0xc/disp8 . # copy ECX+EDX+12 to EDX
52/push-EDX
# . . call
e8/call skip-until-close-paren-in-slice/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# line->read = EAX - line->data
29/subtract 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # subtract ECX from EAX
2d/subtract-from-EAX 0xc/imm32
89/copy 1/mod/*+disp8 1/rm32/ECX . . 0/r32/EAX 4/disp8 . # copy EAX to *(ECX+4)
$skip-until-close-paren:end:
# . restore registers
5a/pop-to-EDX
59/pop-to-ECX
58/pop-to-EAX
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
test-skip-until-close-paren:
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# setup
# . clear-stream(_test-input-stream)
# . . push args
68/push _test-input-stream/imm32
# . . call
e8/call clear-stream/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# . write(_test-input-stream, "*(abc) def")
# . indices: 0123 45
# . . push args
68/push "*(abc) def"/imm32
68/push _test-input-stream/imm32
# . . call
e8/call write/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# precondition: line->read == 0
# . . push args
68/push "F - test-skip-until-close-paren/precondition"/imm32
68/push 0/imm32
b8/copy-to-EAX _test-input-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
# . . call
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# skip-until-close-paren(_test-input-stream)
# . . push args
68/push _test-input-stream/imm32
# . . call
e8/call skip-until-close-paren/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# check-ints-equal(line->read, 6, msg)
# . . push args
68/push "F - test-skip-until-close-paren"/imm32
68/push 6/imm32
b8/copy-to-EAX _test-input-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
# . . call
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
test-skip-until-close-paren-ignores-spaces:
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# setup
# . clear-stream(_test-input-stream)
# . . push args
68/push _test-input-stream/imm32
# . . call
e8/call clear-stream/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# . write(_test-input-stream, "*(a b)/yz")
# . . push args
68/push "*(a b)/yz"/imm32
68/push _test-input-stream/imm32
# . . call
e8/call write/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# precondition: line->read == 0
# . . push args
68/push "F - test-skip-until-close-paren-ignores-spaces/precondition"/imm32
68/push 0/imm32
b8/copy-to-EAX _test-input-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
# . . call
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# skip-until-close-paren(_test-input-stream)
# . . push args
68/push _test-input-stream/imm32
# . . call
e8/call skip-until-close-paren/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# check-ints-equal(line->read, 6, msg)
# . . push args
68/push "F - test-skip-until-close-paren-ignores-spaces"/imm32
68/push 6/imm32
b8/copy-to-EAX _test-input-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
# . . call
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
test-skip-until-close-paren-works-from-mid-stream:
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# setup
# . clear-stream(_test-input-stream)
# . . push args
68/push _test-input-stream/imm32
# . . call
e8/call clear-stream/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# . write(_test-input-stream, "0 *(a b)/yz")
# . . push args
68/push "0 *(a b)/yz"/imm32
68/push _test-input-stream/imm32
# . . call
e8/call write/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# precondition: _test-input-stream->read == 2
c7 0/subop/copy 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 2/imm32 # copy to *(EAX+4)
# skip-until-close-paren(_test-input-stream)
# . . push args
68/push _test-input-stream/imm32
# . . call
e8/call skip-until-close-paren/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# check-ints-equal(_test-input-stream->read, 8, msg)
# . . push args
68/push "F - test-skip-until-close-paren-works-from-mid-stream"/imm32
68/push 8/imm32
b8/copy-to-EAX _test-input-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
# . . call
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
skip-until-close-paren-in-slice: # curr : (address byte), end : (address byte) -> new_curr/EAX
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# . save registers
51/push-ECX
52/push-EDX
# ECX = curr
8b/copy 1/mod/*+disp8 5/rm32/EBP . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX
# EDX = end
8b/copy 1/mod/*+disp8 5/rm32/EBP . . 2/r32/EDX 0xc/disp8 . # copy *(EBP+12) to EDX
# EAX = 0
31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX
# skip initial dquote
41/increment-ECX
$skip-until-close-paren-in-slice:loop:
# if (curr >= end) return curr
39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX
73/jump-if-greater-unsigned-or-equal $skip-until-close-paren-in-slice:return-curr/disp8
# AL = *curr
8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL
$skip-until-close-paren-in-slice:check-close:
# if (EAX == ')') break
3d/compare-EAX-and 0x29/imm32/close-paren
74/jump-if-equal $skip-until-close-paren-in-slice:break/disp8
# ++curr
41/increment-ECX
eb/jump $skip-until-close-paren-in-slice:loop/disp8
$skip-until-close-paren-in-slice:break:
# skip close-paren itself
41/increment-ECX
$skip-until-close-paren-in-slice:return-curr:
# return curr
89/copy 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # copy ECX to EAX
$skip-until-close-paren-in-slice:end:
# . restore registers
5a/pop-to-EDX
59/pop-to-ECX
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
test-skip-until-close-paren-in-slice:
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# setup: (EAX..ECX) = "*(abc) def"
b8/copy-to-EAX "*(abc) def"/imm32
8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX
05/add-to-EAX 4/imm32
# EAX = skip-until-close-paren-in-slice(EAX, ECX)
# . . push args
51/push-ECX
50/push-EAX
# . . call
e8/call skip-until-close-paren-in-slice/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check-ints-equal(ECX-EAX, 4, msg) # number of chars remaining after the string literal
# . . push args
68/push "F - test-skip-until-close-paren-in-slice"/imm32
68/push 4/imm32
# . . push ECX-EAX
29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX
51/push-ECX
# . . call
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
test-skip-until-close-paren-in-slice-ignores-spaces:
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# setup: (EAX..ECX) = "*(a b)/yz"
b8/copy-to-EAX "*(a b)/yz"/imm32
8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX
05/add-to-EAX 4/imm32
# EAX = skip-until-close-paren-in-slice(EAX, ECX)
# . . push args
51/push-ECX
50/push-EAX
# . . call
e8/call skip-until-close-paren-in-slice/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check-ints-equal(ECX-EAX, 3, msg) # number of chars remaining after the string literal
# . . push args
68/push "F - test-skip-until-close-paren-in-slice-ignores-spaces"/imm32
68/push 3/imm32
# . . push ECX-EAX
29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX
51/push-ECX
# . . call
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
test-skip-until-close-paren-in-slice-stops-at-end:
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# setup: (EAX..ECX) = "*(abc" # unbalanced dquote
b8/copy-to-EAX "*(abc"/imm32
8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX
05/add-to-EAX 4/imm32
# EAX = skip-until-close-paren-in-slice(EAX, ECX)
# . . push args
51/push-ECX
50/push-EAX
# . . call
e8/call skip-until-close-paren-in-slice/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check-ints-equal(ECX-EAX, 0, msg) # skipped to end of slice
# . . push args
68/push "F - test-skip-until-close-paren-in-slice-stops-at-end"/imm32
68/push 0/imm32
# . . push ECX-EAX
29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX
51/push-ECX
# . . call
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
== data
Registers: # (table string int)
# a table is a stream