duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 78aae7ce65101e43bc1f46a5f58c546d572f9743
parent b0394749eb3a2f18a8c863d650bd388d596ba401
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Fri,  2 Sep 2022 15:41:10 -0400

Add doc/dict

Diffstat:
Mfs/doc/dict.txt | 188++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mfs/xcomp/bootlo.fs | 2+-
2 files changed, 163 insertions(+), 27 deletions(-)

diff --git a/fs/doc/dict.txt b/fs/doc/dict.txt @@ -27,8 +27,10 @@ f -- flag s -- string w -- word e -- entry +m -- entry metadata r -- range u -- count +c -- character, a 8-bit value a b c -- order of elements matter The description of the words can contain letters in between "*" characters, @@ -36,6 +38,9 @@ indicating a special attribute: *I* indicates an immediate word. *B* indicates that it is "binary modulable". +*C* indicates that the word can be compiled. Its description is its behavior in + interpret mode, but when in compile mode, it will "do the right thing" to + compile the same behvior. ## Symbols @@ -69,6 +74,13 @@ MAIN Address containing the value of "main". ABORT Address containing the value of "abort". EMIT Address containing the value of "emit". IN< Address containing the value of "in<". +CELLSZ Size of a cell: 4 +CALLSZ The size in bytes of a native call. + +SPC $20 +CR $0d +LF $0a +BS $08 ### Values @@ -90,8 +102,10 @@ main -- Stack words move elements around in PS and RS. drop a -- +2drop a b -- dup a -- a a ?dup a -- a? a dup if a is nonzero. +2dup a b -- a b a b swap a b -- b a over a b -- a b a nip a b -- b @@ -99,6 +113,13 @@ tuck a b -- b a b rot a b c -- b c a rot> a b c -- c a b +rdrop -- *I* Compile a RS shrink of 4 bytes. +r@ -- *I* Compile a push of current RS top to PS. +r> -- *I* Equivalent to r@ rdrop +>r -- *I* Compiles a RS grow of 4 bytes followed by a pop + of PS into that new RS space. +rfree -- *I* Shrink RS by the current [rcnt] level and reset + [rcnt] to 0. r+, n -- Compile a RS grow (n is negative) or shrink (n is positive) operation by n bytes. r', off -- Compile the yield of RSP with "off" offset applied to @@ -127,15 +148,27 @@ width", a value that can be 1, 2 or 4 depending of the width of the operation. 16b -- *I* Set binary width to 16-bit allot u -- Increase here by u. +allot0 u -- Allot u and fill this space with zeroes. move src dst u -- Copy u bytes from address src to address dst, moving upwards. move, src u -- Copy u bytes to "here" and increase "here" by u. +fill a u c -- Fill range [a, a+u] with byte c. +align4 -- Allot 0, 1, 2 or 3 bytes so that "here" is divisible + by 4. +nc, n -- Parse n numbers from input stream and write them as + 8-bit values. +[c]? c a u -- i Search for character c in range [a, a+u] and yield its + index or -1 if not found. Convenience shortcuts: -c@ --> 8b @ -c! --> 8b ! -c, --> 8b , +c@ --> 8b @ +c! --> 8b ! +c, --> 8b , +w@ --> 16b @ +w! --> 16b ! +c@+ --> 8b @+ +c!+ --> 8b !+ ## Arithmetics @@ -143,16 +176,24 @@ c, --> 8b , 1- a -- a-1 + a b -- a+b - a b -- a-b +-^ a b -- b-a * a b -- a*b / a b -- a/b /mod a b -- r q r is remainder, q is quotient +mod a b -- n n is the remainder of a divided by b +neg a -- -a and a b -- n n is the result of a binary "and" of a and b or a b -- n n is the result of a binary "or" of a and b xor a b -- n n is the result of a binary "exclusive or" of a and b +^ a -- n n is the result of "a -1 xor", flipping all bits. lshift n u -- n Shift n by u bits to the left rshift n u -- n Shift n by u bits to the right +<< n -- n Shift n left by 1 +>> n -- n Shift n right by 1 <<c n -- n c Shift n left by 1, yielding c as the 32-bit carry bit >>c n -- n c Shift n right by 1, yielding c as the 32-bit carry bit +upcase c -- c If c is between "a" and "z", yield their upcase version. + Otherwise, yield c. ## Logic @@ -160,31 +201,62 @@ rshift n u -- n Shift n by u bits to the right Other conditions yield f=0. < a b -- f f=1 if a is lower than b +> a b -- f f=1 if a is higher than b = a b -- f f=1 if a equals b +<> a b -- f f=1 if a is not equal to b +>= a b -- f f=1 if a is higher than or equal to b +<= a b -- f f=1 if a is lower than or equal to b +0< a -- f f=1 if a is negative +0>= a -- f f=1 if a is not negative not a -- f f=1 if a is zero bool a -- f f=1 if a is nonzero +min a b -- n n is the lowest number between a and b. +max a b -- n n is the highest number between a and b. +=><= n l h -- f f=1 if n >= l and n <= h. +?swap a b -- l h Sort a and b, putting the highest number on TOS. []= r1 r2 u -- f f=1 if memory ranges [r1, r1+u] and [r2, r2+u] have the same content. +s= s1 s2 -- f f=1 if s1 and s2 have the same length and content. ## Flow +noop -- Do nothing bye -- Halt the machine. quit -- Reset RS and return to the "main" loop. abort -- Reset PS and quit. execute a -- Call address a. exit -- *I* Compile a return from call. main -- The mainloop. Repeatedly call "word" and "runword". - -if -- a *I* Write an conditional branch. a is its target. -then a -- *I* Make branch target point to here. -else a1 -- a2 *I* Compile an unconditional branch and make supplied - branch target point to after it. -begin -- a *I* Yield a branch target. -again a -- *I* Compile an unconditional branch to target. -until a -- *I* Compile an conditional branch to target. -next a -- *I* Compile a "next" branch to target. leave -- *I* Set "next" counter so that we leave the loop at the next "next" branch. +[if] f -- If f=0, skip all following words until a "[then]" word is + reached. +[then] -- No-op. + +Structured flow words are better explained in their interaction together rather +than their individual effect and this is done in doc/usage. Below is a list of +all the flow words for reference. All these words are immediate. + +if .. else .. then +begin .. again +begin .. until +n >r begin .. next +begin .. while .. repeat +begin .. while .. while .. repeat .. else .. then +n case .. of condition .. endof .. endcase + +## Linked list + +llnext ll -- ll Yield next LL element. +llend ll -- ll Iterate LL until we reach the last element. +llprev tgt ll -- ll From "ll", iterate LL until we reach the element when the + LL pointer points to "tgt". +lladd ll -- ll Write a new LL element to here, yield it, then write its + address to the last element of "ll". +llinsert 'll -- ll Given a *pointer* to a LL, write a new LL to here and + replace that first element in that pointer with the new + LL element. +llcnt ll -- n Yield the number of elements in "ll". ## Dictionary @@ -198,13 +270,49 @@ e>w e -- w Yield a word reference (executable) from an entry. entry s -- Create entry with name s in system dictionary. code "x" -- Same as "entry", but reads name from input stream. current -- w Yield the last word to be added to the system dictionary. +emeta w -- m Yield the value of the "metadata" field of the entry + associated with word w. +'emeta w -- 'm Same as "emeta", but yield the address of that field. +wordlen w -- n Yield the length of the name of word w. +wordname[] w -- a u Yields a range with the name of word w. +.word w -- Emit name of word w. +words -- Emit names of all words of the system dictionary. + +## Entry metadata + +An entry metadata is a linked list followed by a type id. + +emetatype m -- n Yield the type id of metadata m. +'emetadata m -- a Yield the address of the "arbitrary data" part of m. +findmeta typeid m -- m-or-0 + Find a metadata element of type "typeid" in meta LL "m" and + yield this meta if found. Otherwise, yield 0. + +## Structure + +struct[ "x" -- Create new struct "x" and begin defining it. +]struct -- Exit current struct definition. +extends "x" -- Find struct "x" in system dictionary and make the next + defined struct extend it. +sfield "x" -- Add a new struct field named "x". +smethod "x" -- Add a new struct method named "x". +structbind 'data "x y" -- + Create a new binding named "x" that binds 'data to struct + named "y". +rebind 'data 'bind -- + Bind 'data to structbind 'bind. ## I/O key -- c Read next character from system interactive input source. in< -- c Read next character from system input source. emit c -- Emit character to system output destination. +nl> -- Emit CR then LF. +spc> -- Emit SPC. rtype a u -- Emit characters in range [a, a+u]. +stype s -- Emit all characters in s. +." x" -- *IC* Emit string x. +abort" x" -- *IC* Emit string x then abort. maybeword -- s-or-0 Try to read word from system input source and yield it as a string if it could be read. If EOF (c = -1) is reached, yield 0. @@ -226,17 +334,45 @@ runword s -- Execute string s according to our general logic: compile it Compiling words operate on a higher plane: they write native code to "here", which can then be executed to have the desired effect. -[ -- *I* Stop compiling. The following words will be interpreted. -] -- Begin compiling. The following words will be compiled. -: "x" -- Create entry x and begin compiling. -; -- *I* Compile a return from call and then stop compiling. -litn n -- Compile a literal with value n. -execute, a -- Compile a call to address a. -exit, -- Compile a return from call. -compile "x" -- *I* Find word x and compile a compilation of a call to it. -[compile] "x" -- *I* Find immediate word x and instead of executing it - immediately as we would normally do, compile it as if it - wasn't immediate. -compiling -- f f=1 if we're currently compiling. -immediate -- Make last added entry into an immediate entry. - +[ -- *I* Stop compiling. The following words will be interpreted. +] -- Begin compiling. The following words will be compiled. +: "x" -- Create entry x and begin compiling. +; -- *I* Compile a return from call and then stop compiling. +litn n -- Compile a literal with value n. +execute, a -- Compile a call to address a. +exit, -- Compile a return from call. +compile "x" -- *I* Find word x and compile a compilation of a call to it. +[compile] "x" -- *I* Find immediate word x and instead of executing it + immediately as we would normally do, compile it as if it + wasn't immediate. +compiling -- f f=1 if we're currently compiling. +immediate -- Make last added entry into an immediate entry. +create "x" -- Create a new entry named "x" of type "cell". +const n "x" -- Create a new constant named "x" of value n. +doer "x" -- Create a new "doer" word, to be paired with does>. +does> -- Begin compiling the runtime behavior of a doer word. +does' w -- a Yields the address of the "data" part of a doer word w. +value n "x" -- Create a new entry of type "value" with n as its initial + value +ivalue a "x" -- Create a new entry of type "indirect value" with a being the + address holding the pointer to the value. +alias "x y" -- Find word "x" in system dictionary and create entry "y" of + type "alias" pointing to it. +ialias a "x" -- Create a new entry of type "indirect alias" with a being the + address holding the pointer to the word to execute. +S" x" -- *IC* Yield string literal with contents "x". +chain "x y" -- Create a new "chain" targeting alias "x" and chaining "y" to + it. + +## "to" words + +The way "to" words work is that they compile their associated word right +after a literal that yields the address of the word which obeys "to" semantics. + +to --> ! +to+ --> +! +to' --> noop +to@ --> @ +to@! --> @! +to@+ --> @@+ +to!+ --> @!+ diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs @@ -80,7 +80,7 @@ create toptr 0 , : w! 16b ! ; : c@+ 8b @+ ; : c!+ 8b !+ ; -: fill ( a u b -- ) >r >r begin V1 swap c!+ next drop rdrop ; +: fill ( a u c -- ) >r >r begin V1 swap c!+ next drop rdrop ; : allot0 ( n -- ) HERE @ over 0 fill allot ; : align4 ( -- ) HERE @ 4 mod ?dup if 4 -^ allot0 then ; : nc, ( n -- ) >r begin word runword c, next ;