Mirror of CollapseOS
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

197 líneas
9.4KB

  1. Stack notation: "<stack before> -- <stack after>". Rightmost is top of stack
  2. (TOS). For example, in "a b -- c d", b is TOS before, d is TOS after. "R:" means
  3. that the Return Stack is modified. "I:" prefix means "IMMEDIATE", that is, that
  4. this stack transformation is made at compile time.
  5. DOES>: Used inside a colon definition that itself uses CREATE, DOES> transforms
  6. that newly created word into a "does cell", that is, a regular cell ( when
  7. called, puts the cell's addr on PS), but right after that, it executes words
  8. that appear after the DOES>.
  9. "does cells" always allocate 4 bytes (2 for the cell, 2 for the DOES> link) and
  10. there is no need for ALLOT in colon definition.
  11. At compile time, colon definition stops processing words when reaching the
  12. DOES>.
  13. Example: ": CONSTANT CREATE HERE @ ! DOES> @ ;"
  14. Word references (wordref): When we say we have a "word reference", it's a
  15. pointer to a words *code link*. For example, the label "PLUS:" in this unit is a
  16. word reference. Why not refer to the beginning of the word struct? Because we
  17. actually seldom refer to the name and prev link, except during compilation, so
  18. defining "word reference" this way makes the code easier to understand.
  19. Atom: A word of the type compiledWord contains, in its PF, a list of what we
  20. call "atoms". Those atoms are most of the time word references, but they can
  21. also be references to NUMBER and LIT.
  22. Words between "()" are "support words" that aren't really meant to be used
  23. directly, but as part of another word.
  24. "*I*" in description indicates an IMMEDIATE word.
  25. *** Defining words ***
  26. (find) x -- a f Read word x and find it in dict. If found, f=1 and
  27. a = wordref. If not found, f=0 and a = string addr.
  28. : x ... -- Define a new word
  29. ; R:I -- Exit a colon definition
  30. , n -- Write n in HERE and advance it.
  31. ' x -- a Push addr of word x to a. If not found, aborts
  32. ['] x -- *I* Like "'", but spits the addr as a number
  33. literal. If not found, aborts.
  34. ( -- *I* Comment. Ignore rest of line until ")" is read.
  35. ALLOT n -- Move HERE by n bytes
  36. C, b -- Write byte b in HERE and advance it.
  37. CREATE x -- Create cell named x. Doesn't allocate a PF.
  38. [COMPILE] x -- Compile word x and write it to HERE
  39. COMPILE x -- Meta compiles. Kind of blows the mind. See below.
  40. CONSTANT x n -- Creates cell x that when called pushes its value
  41. DOES> -- See description at top of file
  42. IMMED? a -- f Checks whether wordref at a is immediate.
  43. IMMEDIATE -- Flag the latest defined word as immediate.
  44. LITN n -- Write number n as a literal.
  45. VARIABLE c -- Creates cell x with 2 bytes allocation.
  46. Compilation vs meta-compilation. When you compile a word with "[COMPILE] foo",
  47. its straightforward: It writes down to HERE wither the address of the word or
  48. a number literal.
  49. When you *meta* compile, it's a bit more mind blowing. It fetches the address
  50. of the word specified by the caller, then writes that number as a literal,
  51. followed by a reference to ",".
  52. Example: ": foo [COMPILE] bar;" is the equivalent of ": foo bar ;" if bar is
  53. not an immediate. However, ": foo COMPILE bar ;" is the equivalent of
  54. ": foo ['] bar , ;". Got it?
  55. Meta-compile only works with real words, not number literals.
  56. *** Flow ***
  57. Note about flow words: flow words can only be used in definitions. In the
  58. INTERPRET loop, they don't have the desired effect because each word from the
  59. input stream is executed immediately. In this context, branching doesn't work.
  60. (fbr) -- Branches forward by the number specified in its
  61. atom's cell.
  62. (bbr) -- Branches backward by the number specified in its
  63. atom's cell.
  64. ABORT -- Resets PS and RS and returns to interpreter
  65. ABORT" x" -- *I* Compiles a ." followed by a ABORT.
  66. AGAIN I:a -- *I* Jump backwards to preceeding BEGIN.
  67. BEGIN -- I:a *I* Marker for backward branching with AGAIN.
  68. ELSE I:a -- *I* Compiles a (fbr) and set branching cell at a.
  69. EXECUTE a -- Execute wordref at addr a
  70. IF -- I:a *I* Compiles a (fbr?) and pushes its cell's addr
  71. INTERPRET -- Get a line from stdin, compile it in tmp memory,
  72. then execute the compiled contents.
  73. QUIT R:drop -- Return to interpreter prompt immediately
  74. RECURSE R:I -- R:I-2 Run the current word again.
  75. SKIP? f -- If f is true, skip the execution of the next atom.
  76. Use this right before ";" and you're gonna have a
  77. bad time.
  78. THEN I:a -- *I* Set branching cell at a.
  79. UNTIL f -- *I* Jump backwards to BEGIN if f is *false*.
  80. *** Parameter Stack ***
  81. DROP a --
  82. DUP a -- a a
  83. OVER a b -- a b a
  84. SWAP a b -- b a
  85. 2DUP a b -- a b a b
  86. 2OVER a b c d -- a b c d a b
  87. 2SWAP a b c d -- c d a b
  88. *** Return Stack ***
  89. >R n -- R:n Pops PS and push to RS
  90. R> R:n -- n Pops RS and push to PS
  91. I -- n Copy RS TOS to PS
  92. I' -- n Copy RS second item to PS
  93. J -- n Copy RS third item to PS
  94. *** Memory ***
  95. @ a -- n Set n to value at address a
  96. ! n a -- Store n in address a
  97. ? a -- Print value of addr a
  98. +! n a -- Increase value of addr a by n
  99. C@ a -- c Set c to byte at address a
  100. C! c a -- Store byte c in address a
  101. CURRENT -- a Set a to wordref of last added entry.
  102. HERE -- a Push HERE's address
  103. H -- a HERE @
  104. *** Arithmetic ***
  105. + a b -- c a + b -> c
  106. - a b -- c a - b -> c
  107. -^ a b -- c b - a -> c
  108. * a b -- c a * b -> c
  109. / a b -- c a / b -> c
  110. MOD a b -- c a % b -> c
  111. /MOD a b -- r q r:remainder q:quotient
  112. *** Logic ***
  113. = n1 n2 -- f Push true if n1 == n2
  114. < n1 n2 -- f Push true if n1 < n2
  115. > n1 n2 -- f Push true if n1 > n2
  116. CMP n1 n2 -- n Compare n1 and n2 and set n to -1, 0, or 1.
  117. n=0: a1=a2. n=1: a1>a2. n=-1: a1<a2.
  118. NOT f -- f Push the logical opposite of f
  119. *** Strings ***
  120. LITS x -- a Read following LIT and push its addr to a
  121. SCMP a1 a2 -- n Compare strings a1 and a2. See CMP
  122. SLEN a -- n Push length of str at a.
  123. *** I/O ***
  124. A little word about inputs. There are two kind of inputs: direct and buffered.
  125. As a general rule, we read line in a buffer, then feed words in it to the
  126. interpreter. That's what "WORD" does. If it's at the End Of Line, it blocks and
  127. wait until another line is entered.
  128. KEY input, however, is direct. Regardless of the input buffer's state, KEY will
  129. return the next typed key.
  130. PARSING AND BOOTSTRAP: Parsing number literal is a very "core" activity of
  131. Forth, and therefore generally seen as having to be implemented in native code.
  132. However, Collapse OS' Forth supports many kinds of literals: decimal, hex, char,
  133. binary. This incurs a significant complexity penalty.
  134. What if we could implement those parsing routines in Forth? "But it's a core
  135. routine!" you say. Yes, but here's the deal: at its native core, only decimal
  136. parsing is supported. It lives in the "(parsed)" word. The interpreter's main
  137. loop is initially set to simply call that word.
  138. However, in core.fs, "(parsex)", "(parsec)" and "(parseb)" are implemented, in
  139. Forth, then "(parse)", which goes through them all is defined. Then, "(parsef)",
  140. which is the variable in which the interpreter's word pointer is set, is
  141. updated to that new "(parse)" word.
  142. This way, we have a full-featured (and extensible) parsing with a tiny native
  143. core.
  144. (parse) a -- n Parses string at a as a number and push the result
  145. in n as well as whether parsing was a success in f
  146. (false = failure, true = success)
  147. (parse.) a -- n f Sub-parsing words. They all have the same signature.
  148. Parses string at a as a number and push the result
  149. in n as well as whether parsing was a success in f
  150. (0 = failure, 1 = success)
  151. (parse*) -- a Variable holding the current pointer for system
  152. number parsing. By default, (parse).
  153. (print) a -- Print string at addr a.
  154. . n -- Print n in its decimal form
  155. .X n -- Print n in its hexadecimal form. In hex, numbers
  156. ." xxx" -- *I* Compiles string literal xxx followed by a call
  157. to (print)
  158. are never considered negative. "-1 .X -> ffff"
  159. EMIT c -- Spit char c to output stream
  160. IN> -- a Address of variable containing current pos in input
  161. buffer.
  162. KEY -- c Get char c from direct input
  163. PC! c a -- Spit c to port a
  164. PC@ a -- c Fetch c from port a
  165. WORD -- a Read one word from buffered input and push its addr