235 lines
7.7 KiB
Forth
235 lines
7.7 KiB
Forth
type line {
|
|
name: (handle array byte)
|
|
data: (handle word)
|
|
cursor: (handle word)
|
|
next: (handle line)
|
|
prev: (handle line)
|
|
}
|
|
|
|
# initialize line with a single empty word
|
|
fn initialize-line _line: (addr line) {
|
|
var line/esi: (addr line) <- copy _line
|
|
var word-ah/eax: (addr handle word) <- get line, data
|
|
allocate word-ah
|
|
var cursor-ah/ecx: (addr handle word) <- get line, cursor
|
|
copy-object word-ah, cursor-ah
|
|
var word/eax: (addr word) <- lookup *word-ah
|
|
initialize-word word
|
|
}
|
|
|
|
fn num-words-in-line _in: (addr line) -> _/eax: int {
|
|
var in/esi: (addr line) <- copy _in
|
|
var curr-ah/ecx: (addr handle word) <- get in, data
|
|
var result/edi: int <- copy 0
|
|
{
|
|
var curr/eax: (addr word) <- lookup *curr-ah
|
|
compare curr, 0
|
|
break-if-=
|
|
curr-ah <- get curr, next
|
|
result <- increment
|
|
loop
|
|
}
|
|
return result
|
|
}
|
|
|
|
fn line-list-length lines: (addr handle line) -> _/eax: int {
|
|
var curr-ah/esi: (addr handle line) <- copy lines
|
|
var result/edi: int <- copy 0
|
|
{
|
|
var curr/eax: (addr line) <- lookup *curr-ah
|
|
compare curr, 0
|
|
break-if-=
|
|
curr-ah <- get curr, next
|
|
result <- increment
|
|
loop
|
|
}
|
|
return result
|
|
}
|
|
|
|
fn render-line screen: (addr screen), _line: (addr line), x: int, y: int, render-cursor?: boolean -> _/eax: int {
|
|
var line/eax: (addr line) <- copy _line
|
|
var first-word-ah/esi: (addr handle word) <- get line, data
|
|
# cursor-word
|
|
var cursor-word/edi: int <- copy 0
|
|
compare render-cursor?, 0/false
|
|
{
|
|
break-if-=
|
|
var cursor-word-ah/eax: (addr handle word) <- get line, cursor
|
|
var _cursor-word/eax: (addr word) <- lookup *cursor-word-ah
|
|
cursor-word <- copy _cursor-word
|
|
}
|
|
#
|
|
var result/eax: int <- render-words screen, first-word-ah, x, y, cursor-word
|
|
return result
|
|
}
|
|
|
|
fn parse-line in: (addr array byte), _out: (addr line) {
|
|
var out/edi: (addr line) <- copy _out
|
|
initialize-line out
|
|
var dest/eax: (addr handle word) <- get out, data
|
|
parse-words in, dest
|
|
}
|
|
|
|
#? fn main {
|
|
#? # line = [aaa, bbb, ccc, ddd]
|
|
#? var line-storage: line
|
|
#? var w-ah/eax: (addr handle word) <- get line-storage, data
|
|
#? allocate-word-with w-ah, "aaa"
|
|
#? append-word-at-end-with w-ah, "bbb"
|
|
#? append-word-at-end-with w-ah, "ccc"
|
|
#? append-word-at-end-with w-ah, "ddd"
|
|
#? var cursor-ah/ecx: (addr handle word) <- get line-storage, cursor
|
|
#? var w/eax: (addr word) <- lookup *w-ah
|
|
#? var next-ah/eax: (addr handle word) <- get w, next
|
|
#? copy-object next-ah, cursor-ah
|
|
#? var line-addr/eax: (addr line) <- address line-storage
|
|
#? var dummy/eax: int <- render-line 0/screen, line-addr, 0/x, 0/y, 1/render-cursor
|
|
#? }
|
|
|
|
fn render-line-with-stack screen: (addr screen), _line: (addr line), x: int, y: int, render-cursor?: boolean -> _/eax: int, _/ecx: int {
|
|
var line/esi: (addr line) <- copy _line
|
|
# cursor-word
|
|
var cursor-word/edi: int <- copy 0
|
|
compare render-cursor?, 0/false
|
|
{
|
|
break-if-=
|
|
var cursor-word-ah/eax: (addr handle word) <- get line, cursor
|
|
var _cursor-word/eax: (addr word) <- lookup *cursor-word-ah
|
|
cursor-word <- copy _cursor-word
|
|
}
|
|
#
|
|
var curr-word-ah/eax: (addr handle word) <- get line, data
|
|
var _curr-word/eax: (addr word) <- lookup *curr-word-ah
|
|
var curr-word/edx: (addr word) <- copy _curr-word
|
|
var new-x/eax: int <- copy x # increases each iteration
|
|
var new-y/ebx: int <- copy y # compute max across all iterations
|
|
{
|
|
compare curr-word, 0
|
|
break-if-=
|
|
var curr-y/ecx: int <- copy 0
|
|
new-x, curr-y <- render-word-with-stack-and-cursor screen, line, curr-word, new-x, y, cursor-word
|
|
compare curr-y, new-y
|
|
{
|
|
break-if-<=
|
|
new-y <- copy curr-y
|
|
}
|
|
new-x <- add 1/inter-word-spacing
|
|
# update
|
|
var next-word-ah/eax: (addr handle word) <- get curr-word, next
|
|
var next-word/eax: (addr word) <- lookup *next-word-ah
|
|
curr-word <- copy next-word
|
|
loop
|
|
}
|
|
return new-x, new-y
|
|
}
|
|
|
|
fn render-word-with-stack-and-cursor screen: (addr screen), line: (addr line), curr-word: (addr word), x: int, y: int, _cursor-word-addr: int -> _/eax: int, _/ecx: int {
|
|
# print curr-word, with cursor if necessary
|
|
var render-cursor?/eax: boolean <- copy 0/false
|
|
var cursor-word-addr/ecx: int <- copy _cursor-word-addr
|
|
{
|
|
compare cursor-word-addr, curr-word
|
|
break-if-!=
|
|
render-cursor? <- copy 1/true
|
|
}
|
|
var new-x/eax: int <- render-word screen, curr-word, x, y, render-cursor?
|
|
add-to x, 1/word-stack-indent
|
|
var new-x-saved/edx: int <- copy new-x
|
|
add-to y, 2/word-stack-spacing
|
|
# compute stack until word
|
|
var stack-storage: value-stack
|
|
var stack/edi: (addr value-stack) <- address stack-storage
|
|
evaluate line, curr-word, stack
|
|
# render stack
|
|
var new-y/ecx: int <- copy 0
|
|
new-x, new-y <- render-value-stack screen, stack, x, y
|
|
#? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, new-x, 0xc/fg, 0/bg
|
|
#? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, new-y, 3/fg, 0/bg
|
|
compare new-x, new-x-saved
|
|
{
|
|
break-if->=
|
|
new-x <- copy new-x-saved
|
|
}
|
|
#? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, new-x, 7/fg, 0/bg
|
|
return new-x, new-y
|
|
}
|
|
|
|
fn test-render-line-with-stack-singleton {
|
|
# line = [1]
|
|
var line-storage: line
|
|
var line/esi: (addr line) <- address line-storage
|
|
parse-line "1", line
|
|
# setup: screen
|
|
var screen-on-stack: screen
|
|
var screen/edi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 0x20, 4
|
|
#
|
|
var new-x/eax: int <- copy 0
|
|
var new-y/ecx: int <- copy 0
|
|
new-x, new-y <- render-line-with-stack screen, line, 0/x, 0/y, 0/no-cursor
|
|
check-screen-row screen, 0/y, "1 ", "F - test-render-line-with-stack-singleton/0"
|
|
check-screen-row screen, 1/y, " ", "F - test-render-line-with-stack-singleton/1"
|
|
# ___
|
|
check-screen-row screen, 2/y, " 1 ", "F - test-render-line-with-stack-singleton/2"
|
|
# not bothering to test hash colors for numbers
|
|
}
|
|
|
|
fn test-render-line-with-stack {
|
|
# line = [1 2]
|
|
var line-storage: line
|
|
var line/esi: (addr line) <- address line-storage
|
|
parse-line "1 2", line
|
|
# setup: screen
|
|
var screen-on-stack: screen
|
|
var screen/edi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 0x20, 4
|
|
#
|
|
var new-x/eax: int <- copy 0
|
|
var new-y/ecx: int <- copy 0
|
|
new-x, new-y <- render-line-with-stack screen, line, 0/x, 0/y, 0/no-cursor
|
|
check-screen-row screen, 0/y, "1 2 ", "F - test-render-line-with-stack/0"
|
|
check-screen-row screen, 1/y, " ", "F - test-render-line-with-stack/1"
|
|
# ___ ___
|
|
check-screen-row screen, 2/y, " 1 2 ", "F - test-render-line-with-stack/2"
|
|
check-screen-row screen, 3/y, " 1 ", "F - test-render-line-with-stack/3"
|
|
# not bothering to test hash colors for numbers
|
|
}
|
|
|
|
fn edit-line _self: (addr line), key: byte {
|
|
var self/esi: (addr line) <- copy _self
|
|
var cursor-word-ah/edx: (addr handle word) <- get self, cursor
|
|
var _cursor-word/eax: (addr word) <- lookup *cursor-word-ah
|
|
var cursor-word/ecx: (addr word) <- copy _cursor-word
|
|
compare key, 0x20/space
|
|
$edit-line:space: {
|
|
break-if-!=
|
|
append-word cursor-word-ah
|
|
var next-word-ah/eax: (addr handle word) <- get cursor-word, next
|
|
copy-object next-word-ah, cursor-word-ah
|
|
return
|
|
}
|
|
# otherwise insert key within current word
|
|
var g/edx: grapheme <- copy key
|
|
add-grapheme-to-word cursor-word, g
|
|
# silently ignore other hotkeys
|
|
}
|
|
|
|
fn main {
|
|
var line-storage: line
|
|
var line/esi: (addr line) <- address line-storage
|
|
initialize-line line
|
|
{
|
|
clear-screen 0/screen
|
|
var dummy1/eax: int <- copy 0
|
|
var dummy2/ecx: int <- copy 0
|
|
dummy1, dummy2 <- render-line-with-stack 0/screen, line, 2/x, 2/y, 1/show-cursor
|
|
{
|
|
var key/eax: byte <- read-key 0/keyboard
|
|
compare key, 0
|
|
loop-if-=
|
|
edit-line line, key
|
|
}
|
|
loop
|
|
}
|
|
}
|