no longer try using the same port for reading and writing
parent
7d583b43d1
commit
6165c935d3
|
@ -1,13 +1,11 @@
|
||||||
0.62:
|
0.62:
|
||||||
|
|
||||||
- stdout hangs
|
|
||||||
- read-line: handle \r\n
|
- read-line: handle \r\n
|
||||||
- flush output buffer before reading line
|
|
||||||
- print: only flush in stdio stream
|
|
||||||
- ignore errors from flush
|
- ignore errors from flush
|
||||||
- can-read-line?
|
- can-read-line?
|
||||||
- EOF in client connections
|
|
||||||
- vector-each/map examples
|
- vector-each/map examples
|
||||||
|
- unparse examples
|
||||||
|
- finish second practical
|
||||||
- sbuf-hashcode
|
- sbuf-hashcode
|
||||||
- vector-hashcode
|
- vector-hashcode
|
||||||
- listener backspace overzealous
|
- listener backspace overzealous
|
||||||
|
@ -52,7 +50,6 @@
|
||||||
|
|
||||||
- read#
|
- read#
|
||||||
- to_fixnum and friends: error on float
|
- to_fixnum and friends: error on float
|
||||||
ERROR: I/O error: [ "primitive_read_line_fd_8" "Resource temporarily unavailable" ]
|
|
||||||
- parsing should be parsing
|
- parsing should be parsing
|
||||||
- describe-word
|
- describe-word
|
||||||
- contains ==> contains?
|
- contains ==> contains?
|
||||||
|
|
|
@ -1167,7 +1167,7 @@ Vectors are applicable to a different class of problems than lists.
|
||||||
Compare the relative performance of common operations on vectors and
|
Compare the relative performance of common operations on vectors and
|
||||||
lists:
|
lists:
|
||||||
|
|
||||||
\begin{tabular}{|c|c|c|}
|
\begin{tabular}{|r|l|l|}
|
||||||
\hline
|
\hline
|
||||||
&
|
&
|
||||||
Lists&
|
Lists&
|
||||||
|
@ -1298,7 +1298,7 @@ can write:
|
||||||
Other special characters, such as quotes and tabs can be input in
|
Other special characters, such as quotes and tabs can be input in
|
||||||
a similar manner. Here is the full list of supported character escapes:
|
a similar manner. Here is the full list of supported character escapes:
|
||||||
|
|
||||||
\begin{tabular}{|c|c|}
|
\begin{tabular}{|r|l|}
|
||||||
\hline
|
\hline
|
||||||
Character&
|
Character&
|
||||||
Escape\tabularnewline
|
Escape\tabularnewline
|
||||||
|
@ -1773,6 +1773,25 @@ Reading a number, showing a menu
|
||||||
|
|
||||||
\subsection{The name stack}
|
\subsection{The name stack}
|
||||||
|
|
||||||
|
So far, we have seen what we called ``the stack'' store intermediate values between computations. In fact Factor maintains a number of other stacks, and the formal name for the stack we've been dealing with so far is the \emph{data stack}.
|
||||||
|
|
||||||
|
Another stack is the \emph{call stack}. When a colon definition is invoked, the position within the current colon definition is pushed on the stack. This ensures that calling words return to the caller, just as in any other language with subroutines.\footnote{Factor supports a variety of structures for implementing non-local word exits, such as exceptions, co-routines, continuations, and so on. They all rely on manipulating the call stack and are described in later sections.}
|
||||||
|
|
||||||
|
The \emph{name stack} is the focus of this section. The \texttt{bind} combinator creates dynamic scope by pushing and popping namespaces on the name stack. Its definition is simpler than one would expect:
|
||||||
|
|
||||||
|
\begin{alltt}
|
||||||
|
: bind ( namespace quot -- )
|
||||||
|
swap >n call n> drop ;
|
||||||
|
\end{alltt}
|
||||||
|
|
||||||
|
The words \texttt{>n} and \texttt{n>} push and pop the name stack, respectively. Observe the stack flow in the definition of \texttt{bind}; the namespace goes on the name stack, the quotation is called, and the name space is popped and discarded.
|
||||||
|
|
||||||
|
The name stack is really just a vector. The words \texttt{>n} and \texttt{n>} are implemented as follows:
|
||||||
|
|
||||||
|
\begin{alltt}
|
||||||
|
: >n ( namespace -- n:namespace ) namestack* vector-push ;
|
||||||
|
: n> ( n:namespace -- namespace ) namestack* vector-pop ;
|
||||||
|
\end{alltt}
|
||||||
|
|
||||||
\subsection{The inspector}
|
\subsection{The inspector}
|
||||||
|
|
||||||
|
@ -1780,15 +1799,75 @@ Reading a number, showing a menu
|
||||||
\section{PRACTICAL: Music player}
|
\section{PRACTICAL: Music player}
|
||||||
|
|
||||||
|
|
||||||
\section{Deeper in the beast}
|
\section{Metaprogramming}
|
||||||
|
|
||||||
Text -> objects - parser, objects -> text - unparser for atoms, prettyprinter
|
Recall that code quotations are in fact just linked lists. Factor code is data, and vice versa. Essentially, the interpreter iterates through code quotations, pushing literals and executing words. When a word is executed, one of two things happen -- either the word has a colon definition, and the interpreter is invoked recursively on the definition, or the word is primitive, and it is executed by the underlying virtual machine. A word is itself a first-class object.
|
||||||
for collections.
|
|
||||||
|
|
||||||
What really is a word -- primitive, parameter, property list.
|
It is the job of the parser to transform source code denoting literals and words into their internal representations. This is done using a vocabulary of \emph{parsing words}. The prettyprinter does the converse, by printing out data structures in a parsable form (both to humans and Factor). Because code is data, text representation of source code doubles as a way to serialize almost any Factor object.
|
||||||
|
|
||||||
Call stack how it works and >r/r>
|
\subsection{Looking at words}
|
||||||
|
|
||||||
|
Try pushing a list of words on the stack, and take its first element:
|
||||||
|
|
||||||
|
\begin{alltt}
|
||||||
|
{[} * + {]} car .s
|
||||||
|
\emph{\{ * \}}
|
||||||
|
\end{alltt}
|
||||||
|
|
||||||
|
What happened here? Instead of being executed, a ``naked'', unquoted word was pushed on the stack. The predicate \texttt{word? ( obj -{}- ? )} from the \texttt{words} vocabulary tests if the top of the stack is a word. Another way to get a word on the stack is to do a vocabulary search using a word name and a list of vocabularies to search in:
|
||||||
|
|
||||||
|
\begin{alltt}
|
||||||
|
"car" {[} "lists" {]} search .s
|
||||||
|
\emph{\{ car \}}
|
||||||
|
\end{alltt}
|
||||||
|
|
||||||
|
The \texttt{search} word will push \texttt{f} if the word is not defined. A new word can be created in a specified vocabulary explicitly:
|
||||||
|
|
||||||
|
\begin{alltt}
|
||||||
|
"start-server" "user" create .s
|
||||||
|
\emph{\{ start-server \}}
|
||||||
|
\end{alltt}
|
||||||
|
|
||||||
|
Two words are only ever equal under the \texttt{=} operator if they identify the same underlying object. Word objects are composed of three slots, named as follows.
|
||||||
|
|
||||||
|
\begin{tabular}{|r|l|}
|
||||||
|
\hline
|
||||||
|
Slot&
|
||||||
|
Description\tabularnewline
|
||||||
|
\hline
|
||||||
|
\hline
|
||||||
|
Primitive&
|
||||||
|
A number identifying a virtual machine operation.\tabularnewline
|
||||||
|
\hline
|
||||||
|
Parameter&
|
||||||
|
An object parameter for the virtual machine operation.\tabularnewline
|
||||||
|
\hline
|
||||||
|
Property list&
|
||||||
|
An association list of name/value pairs.\tabularnewline
|
||||||
|
\hline
|
||||||
|
\end{tabular}
|
||||||
|
|
||||||
|
If the primitive number is set to 1, the word is a colon definition and the parameter must be a quotation. Any other primitive number denotes a function of the virtual machine, and the parameter is ignored. Do not rely on primitive numbers in your code, instead use the \texttt{compound? ( obj -{}- ? )} and \texttt{primitive? ( obj -{}- ? )} predicates.
|
||||||
|
|
||||||
|
The word \texttt{define ( word quot -{}- )} defines a word to have the specified colon definition. Note that \texttt{create} and \texttt{define} perform an action somewhat analagous to the \texttt{: ... ;} notation for colon definitions, except at parse time rather than run time.
|
||||||
|
|
||||||
|
\subsection{The prettyprinter}
|
||||||
|
|
||||||
|
We've already seen the word \texttt{.} which prints the top of the stack in a form that may be read back in. The word \texttt{prettyprint} is similar, except the output is in an indented, multiple-line format. Both words are in the \texttt{prettyprint} vocabulary. Here is an example:
|
||||||
|
|
||||||
|
\begin{alltt}
|
||||||
|
{[} 1 {[} 2 3 4 {]} 5 {]} .
|
||||||
|
\emph{{[} 1 {[} 2 3 4 {]} 5 {]}}
|
||||||
|
{[} 1 {[} 2 3 4 {]} 5 {]} prettyprint
|
||||||
|
\emph{{[}
|
||||||
|
1 {[}
|
||||||
|
2 3 4
|
||||||
|
{]} 5
|
||||||
|
{]}}
|
||||||
|
\end{alltt}
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{The parser}
|
||||||
|
|
||||||
\subsection{Parsing words}
|
\subsection{Parsing words}
|
||||||
|
|
||||||
|
@ -1864,6 +1943,8 @@ types of objects. Strings are covered in great detail later.
|
||||||
|
|
||||||
\section{Continuations}
|
\section{Continuations}
|
||||||
|
|
||||||
|
Call stack how it works and >r/r>
|
||||||
|
|
||||||
Generators, co-routines, multitasking, exception handling
|
Generators, co-routines, multitasking, exception handling
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@ USE: streams
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: vectors
|
USE: vectors
|
||||||
USE: vectors
|
USE: vectors
|
||||||
USE: vocabularies
|
|
||||||
USE: words
|
USE: words
|
||||||
|
|
||||||
IN: arithmetic
|
IN: arithmetic
|
||||||
|
|
|
@ -42,7 +42,6 @@ USE: streams
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: test
|
USE: test
|
||||||
USE: vectors
|
USE: vectors
|
||||||
USE: vocabularies
|
|
||||||
USE: unparser
|
USE: unparser
|
||||||
USE: words
|
USE: words
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,6 @@ USE: stdio
|
||||||
USE: streams
|
USE: streams
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: words
|
USE: words
|
||||||
USE: vocabularies
|
|
||||||
|
|
||||||
! This file is run as the last stage of boot.factor; it relies
|
! This file is run as the last stage of boot.factor; it relies
|
||||||
! on all other words already being defined.
|
! on all other words already being defined.
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
IN: vocabularies
|
IN: words
|
||||||
USE: combinators
|
USE: combinators
|
||||||
USE: inspector
|
USE: inspector
|
||||||
USE: lists
|
USE: lists
|
||||||
|
@ -36,7 +36,6 @@ USE: stack
|
||||||
USE: stdio
|
USE: stdio
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: unparser
|
USE: unparser
|
||||||
USE: words
|
|
||||||
|
|
||||||
: word-uses? ( of in -- ? )
|
: word-uses? ( of in -- ? )
|
||||||
2dup = [
|
2dup = [
|
||||||
|
|
|
@ -40,7 +40,6 @@ USE: words
|
||||||
USE: prettyprint
|
USE: prettyprint
|
||||||
USE: unparser
|
USE: unparser
|
||||||
USE: vectors
|
USE: vectors
|
||||||
USE: vocabularies
|
|
||||||
|
|
||||||
: relative>absolute-object-path ( string -- string )
|
: relative>absolute-object-path ( string -- string )
|
||||||
"object-path" get [ "'" rot cat3 ] when* ;
|
"object-path" get [ "'" rot cat3 ] when* ;
|
||||||
|
|
|
@ -31,7 +31,7 @@ USE: combinators
|
||||||
USE: namespaces
|
USE: namespaces
|
||||||
USE: stack
|
USE: stack
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: vocabularies
|
USE: words
|
||||||
|
|
||||||
: view ( -- view )
|
: view ( -- view )
|
||||||
[ ] "org.gjt.sp.jedit.jEdit"
|
[ ] "org.gjt.sp.jedit.jEdit"
|
||||||
|
|
|
@ -32,7 +32,6 @@ USE: namespaces
|
||||||
USE: stack
|
USE: stack
|
||||||
USE: stdio
|
USE: stdio
|
||||||
USE: words
|
USE: words
|
||||||
USE: vocabularies
|
|
||||||
|
|
||||||
: class-name ( class -- name )
|
: class-name ( class -- name )
|
||||||
[ ] "java.lang.Class" "getName" jinvoke ;
|
[ ] "java.lang.Class" "getName" jinvoke ;
|
||||||
|
|
|
@ -36,7 +36,6 @@ USE: streams
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: vectors
|
USE: vectors
|
||||||
USE: vectors
|
USE: vectors
|
||||||
USE: vocabularies
|
|
||||||
USE: words
|
USE: words
|
||||||
|
|
||||||
: worddef, ( word -- )
|
: worddef, ( word -- )
|
||||||
|
|
|
@ -33,7 +33,6 @@ USE: prettyprint
|
||||||
USE: stack
|
USE: stack
|
||||||
USE: stdio
|
USE: stdio
|
||||||
USE: unparser
|
USE: unparser
|
||||||
USE: vocabularies
|
|
||||||
USE: words
|
USE: words
|
||||||
|
|
||||||
: prettyprint-~<< ( indent -- indent )
|
: prettyprint-~<< ( indent -- indent )
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
IN: vocabularies
|
IN: words
|
||||||
USE: combinators
|
USE: combinators
|
||||||
USE: kernel
|
USE: kernel
|
||||||
USE: lists
|
USE: lists
|
||||||
|
|
|
@ -32,7 +32,6 @@ USE: lists
|
||||||
USE: logic
|
USE: logic
|
||||||
USE: namespaces
|
USE: namespaces
|
||||||
USE: stack
|
USE: stack
|
||||||
USE: vocabularies
|
|
||||||
|
|
||||||
: worddef? ( obj -- boolean )
|
: worddef? ( obj -- boolean )
|
||||||
"factor.FactorWordDefinition" is ;
|
"factor.FactorWordDefinition" is ;
|
||||||
|
|
|
@ -48,7 +48,6 @@ USE: streams
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: styles
|
USE: styles
|
||||||
USE: vectors
|
USE: vectors
|
||||||
USE: vocabularies
|
|
||||||
USE: words
|
USE: words
|
||||||
USE: unparser
|
USE: unparser
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,6 @@ USE: strings
|
||||||
: wait-to-accept ( socket -- )
|
: wait-to-accept ( socket -- )
|
||||||
[ swap add-accept-io-task next-io-task drop ( call ) ] callcc0 ;
|
[ swap add-accept-io-task next-io-task drop ( call ) ] callcc0 ;
|
||||||
|
|
||||||
: blocking-accept ( socket -- host port socket )
|
: blocking-accept ( socket -- host port in out )
|
||||||
dup wait-to-accept accept-fd ;
|
dup wait-to-accept accept-fd ;
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ USE: namespaces
|
||||||
USE: stack
|
USE: stack
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: words
|
USE: words
|
||||||
USE: vocabularies
|
|
||||||
USE: unparser
|
USE: unparser
|
||||||
|
|
||||||
! Number parsing
|
! Number parsing
|
||||||
|
|
|
@ -42,7 +42,6 @@ USE: stack
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: words
|
USE: words
|
||||||
USE: vectors
|
USE: vectors
|
||||||
USE: vocabularies
|
|
||||||
USE: unparser
|
USE: unparser
|
||||||
|
|
||||||
! Constants
|
! Constants
|
||||||
|
|
|
@ -36,7 +36,6 @@ USE: namespaces
|
||||||
USE: stack
|
USE: stack
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: words
|
USE: words
|
||||||
USE: vocabularies
|
|
||||||
USE: unparser
|
USE: unparser
|
||||||
|
|
||||||
! The parser uses a number of variables:
|
! The parser uses a number of variables:
|
||||||
|
|
|
@ -32,7 +32,6 @@ USE: prettyprint
|
||||||
USE: stack
|
USE: stack
|
||||||
USE: stdio
|
USE: stdio
|
||||||
USE: unparser
|
USE: unparser
|
||||||
USE: vocabularies
|
|
||||||
USE: words
|
USE: words
|
||||||
|
|
||||||
: see-compound ( word -- )
|
: see-compound ( word -- )
|
||||||
|
|
|
@ -61,10 +61,10 @@ USE: namespaces
|
||||||
] extend ;
|
] extend ;
|
||||||
|
|
||||||
: <filecr> ( path -- stream )
|
: <filecr> ( path -- stream )
|
||||||
t f open-file f <fd-stream> ;
|
t f open-file <fd-stream> ;
|
||||||
|
|
||||||
: <filecw> ( path -- stream )
|
: <filecw> ( path -- stream )
|
||||||
f t open-file f swap <fd-stream> ;
|
f t open-file <fd-stream> ;
|
||||||
|
|
||||||
: <filebr> ( path -- stream )
|
: <filebr> ( path -- stream )
|
||||||
<filecr> ;
|
<filecr> ;
|
||||||
|
@ -83,8 +83,8 @@ USE: namespaces
|
||||||
[ "socket" get close-fd ] "fclose" set
|
[ "socket" get close-fd ] "fclose" set
|
||||||
] extend ;
|
] extend ;
|
||||||
|
|
||||||
: <client-stream> ( host port socket -- stream )
|
: <client-stream> ( host port in out -- stream )
|
||||||
dup <fd-stream> [ "port" set "client" set ] extend ;
|
<fd-stream> [ "port" set "client" set ] extend ;
|
||||||
|
|
||||||
: accept ( server -- client )
|
: accept ( server -- client )
|
||||||
#! Accept a connection from a server socket.
|
#! Accept a connection from a server socket.
|
||||||
|
|
|
@ -38,7 +38,6 @@ USE: stack
|
||||||
USE: stdio
|
USE: stdio
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: words
|
USE: words
|
||||||
USE: vocabularies
|
|
||||||
|
|
||||||
: integer% ( num -- )
|
: integer% ( num -- )
|
||||||
"base" get /mod swap dup 0 > [
|
"base" get /mod swap dup 0 > [
|
||||||
|
|
|
@ -25,11 +25,10 @@
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
IN: vocabularies
|
IN: words
|
||||||
USE: lists
|
USE: lists
|
||||||
USE: namespaces
|
USE: namespaces
|
||||||
USE: stack
|
USE: stack
|
||||||
USE: words
|
|
||||||
|
|
||||||
: (search) ( name vocab -- word )
|
: (search) ( name vocab -- word )
|
||||||
vocab dup [ get* ] [ 2drop f ] ifte ;
|
vocab dup [ get* ] [ 2drop f ] ifte ;
|
||||||
|
|
|
@ -32,7 +32,6 @@ USE: lists
|
||||||
USE: logic
|
USE: logic
|
||||||
USE: namespaces
|
USE: namespaces
|
||||||
USE: stack
|
USE: stack
|
||||||
USE: vocabularies
|
|
||||||
|
|
||||||
: word-property ( pname word -- pvalue )
|
: word-property ( pname word -- pvalue )
|
||||||
word-plist assoc ;
|
word-plist assoc ;
|
||||||
|
|
|
@ -41,7 +41,6 @@ USE: strings
|
||||||
USE: styles
|
USE: styles
|
||||||
USE: unparser
|
USE: unparser
|
||||||
USE: vectors
|
USE: vectors
|
||||||
USE: vocabularies
|
|
||||||
USE: words
|
USE: words
|
||||||
|
|
||||||
: tab-size
|
: tab-size
|
||||||
|
|
|
@ -35,7 +35,16 @@ USE: streams
|
||||||
: <stdio-stream> ( stream -- stream )
|
: <stdio-stream> ( stream -- stream )
|
||||||
#! We disable fclose on stdio so that various tricks like
|
#! We disable fclose on stdio so that various tricks like
|
||||||
#! with-stream can work.
|
#! with-stream can work.
|
||||||
clone [ [ ] "fclose" set ] extend ;
|
clone [
|
||||||
|
( string -- )
|
||||||
|
[
|
||||||
|
namespace fwrite
|
||||||
|
"\n" namespace fwrite
|
||||||
|
namespace fflush
|
||||||
|
] "fprint" set
|
||||||
|
|
||||||
|
[ ] "fclose" set
|
||||||
|
] extend ;
|
||||||
|
|
||||||
: flush ( -- )
|
: flush ( -- )
|
||||||
"stdio" get fflush ;
|
"stdio" get fflush ;
|
||||||
|
|
|
@ -81,7 +81,6 @@ USE: strings
|
||||||
[
|
[
|
||||||
namespace fwrite
|
namespace fwrite
|
||||||
"\n" namespace fwrite
|
"\n" namespace fwrite
|
||||||
namespace fflush
|
|
||||||
] "fprint" set
|
] "fprint" set
|
||||||
] extend ;
|
] extend ;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
IN: scratchpad
|
IN: scratchpad
|
||||||
USE: inspector
|
USE: inspector
|
||||||
USE: namespaces
|
USE: namespaces
|
||||||
USE: vocabularies
|
USE: words
|
||||||
|
|
||||||
"httpd" apropos.
|
"httpd" apropos.
|
||||||
"car" usages.
|
"car" usages.
|
||||||
|
|
|
@ -12,7 +12,6 @@ USE: stack
|
||||||
USE: stdio
|
USE: stdio
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: test
|
USE: test
|
||||||
USE: vocabularies
|
|
||||||
USE: words
|
USE: words
|
||||||
|
|
||||||
"Checking dictionary words." print
|
"Checking dictionary words." print
|
||||||
|
|
|
@ -6,7 +6,6 @@ USE: namespaces
|
||||||
USE: stack
|
USE: stack
|
||||||
USE: test
|
USE: test
|
||||||
USE: words
|
USE: words
|
||||||
USE: vocabularies
|
|
||||||
|
|
||||||
[ [ 1 0 0 0 ] ] [ [ >n ] ] [ balance>list ] test-word
|
[ [ 1 0 0 0 ] ] [ [ >n ] ] [ balance>list ] test-word
|
||||||
[ [ 1 1 0 0 ] ] [ [ get ] ] [ balance>list ] test-word
|
[ [ 1 1 0 0 ] ] [ [ get ] ] [ balance>list ] test-word
|
||||||
|
|
|
@ -4,7 +4,6 @@ USE: namespaces
|
||||||
USE: test
|
USE: test
|
||||||
USE: stack
|
USE: stack
|
||||||
USE: words
|
USE: words
|
||||||
USE: vocabularies
|
|
||||||
|
|
||||||
<namespace> "test-namespace" set
|
<namespace> "test-namespace" set
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,6 @@ IN: scratchpad
|
||||||
USE: lists
|
USE: lists
|
||||||
USE: prettyprint
|
USE: prettyprint
|
||||||
USE: test
|
USE: test
|
||||||
USE: vocabularies
|
USE: words
|
||||||
|
|
||||||
[ vocabs [ words [ see ] each ] each ] time
|
[ vocabs [ words [ see ] each ] each ] time
|
||||||
|
|
|
@ -17,7 +17,6 @@ USE: stdio
|
||||||
USE: strings
|
USE: strings
|
||||||
USE: words
|
USE: words
|
||||||
USE: unparser
|
USE: unparser
|
||||||
USE: vocabularies
|
|
||||||
|
|
||||||
: assert ( t -- )
|
: assert ( t -- )
|
||||||
[ "Assertion failed!" throw ] unless ;
|
[ "Assertion failed!" throw ] unless ;
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
IN: vocabularies
|
IN: words
|
||||||
USE: combinators
|
USE: combinators
|
||||||
USE: kernel
|
USE: kernel
|
||||||
USE: lists
|
USE: lists
|
||||||
|
@ -57,7 +57,8 @@ USE: strings
|
||||||
|
|
||||||
: words ( vocab -- list )
|
: words ( vocab -- list )
|
||||||
#! Push a list of all words in a vocabulary.
|
#! Push a list of all words in a vocabulary.
|
||||||
vocab [ values ] bind ;
|
#! Filter empty slots.
|
||||||
|
vocab [ values ] bind [ ] subset ;
|
||||||
|
|
||||||
: intern ( "word" -- word )
|
: intern ( "word" -- word )
|
||||||
#! Returns the top of the stack if it already been interned.
|
#! Returns the top of the stack if it already been interned.
|
||||||
|
|
|
@ -25,15 +25,13 @@
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
IN: vocabularies
|
IN: words
|
||||||
USE: combinators
|
USE: combinators
|
||||||
USE: lists
|
USE: lists
|
||||||
USE: kernel
|
USE: kernel
|
||||||
USE: namespaces
|
USE: namespaces
|
||||||
USE: stack
|
USE: stack
|
||||||
USE: styles
|
USE: styles
|
||||||
USE: vocabularies
|
|
||||||
USE: words
|
|
||||||
|
|
||||||
: get-vocab-style ( vocab -- style )
|
: get-vocab-style ( vocab -- style )
|
||||||
#! Each vocab has a style object specifying how words are
|
#! Each vocab has a style object specifying how words are
|
||||||
|
|
19
native/fd.c
19
native/fd.c
|
@ -2,9 +2,8 @@
|
||||||
|
|
||||||
void init_io(void)
|
void init_io(void)
|
||||||
{
|
{
|
||||||
env.user[STDIN_ENV] = tag_object(port(0));
|
env.user[STDIN_ENV] = tag_object(port(PORT_READ,0));
|
||||||
env.user[STDOUT_ENV] = tag_object(port(1));
|
env.user[STDOUT_ENV] = tag_object(port(PORT_WRITE,1));
|
||||||
env.user[STDERR_ENV] = tag_object(port(2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_read_line(PORT* port)
|
bool can_read_line(PORT* port)
|
||||||
|
@ -98,13 +97,11 @@ bool can_write(PORT* port, FIXNUM len)
|
||||||
{
|
{
|
||||||
CELL buf_capacity;
|
CELL buf_capacity;
|
||||||
|
|
||||||
switch(port->buf_mode)
|
switch(port->type)
|
||||||
{
|
{
|
||||||
case B_NONE:
|
case PORT_READ:
|
||||||
return true;
|
|
||||||
case B_READ_LINE:
|
|
||||||
return false;
|
return false;
|
||||||
case B_WRITE:
|
case PORT_WRITE:
|
||||||
buf_capacity = port->buffer->capacity * CHARS;
|
buf_capacity = port->buffer->capacity * CHARS;
|
||||||
/* Is the string longer than the buffer? */
|
/* Is the string longer than the buffer? */
|
||||||
if(port->buf_fill == 0 && len > buf_capacity)
|
if(port->buf_fill == 0 && len > buf_capacity)
|
||||||
|
@ -116,7 +113,7 @@ bool can_write(PORT* port, FIXNUM len)
|
||||||
else
|
else
|
||||||
return (port->buf_fill + len <= buf_capacity);
|
return (port->buf_fill + len <= buf_capacity);
|
||||||
default:
|
default:
|
||||||
critical_error("Bad buf_mode",port->buf_mode);
|
critical_error("Bad port->type",port->type);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,8 +132,6 @@ void write_fd_char_8(PORT* port, FIXNUM ch)
|
||||||
if(!can_write(port,1))
|
if(!can_write(port,1))
|
||||||
io_error(port,__FUNCTION__);
|
io_error(port,__FUNCTION__);
|
||||||
|
|
||||||
init_buffer(port,B_WRITE);
|
|
||||||
|
|
||||||
bput((CELL)port->buffer + sizeof(STRING) + port->buf_fill,c);
|
bput((CELL)port->buffer + sizeof(STRING) + port->buf_fill,c);
|
||||||
port->buf_fill++;
|
port->buf_fill++;
|
||||||
}
|
}
|
||||||
|
@ -149,8 +144,6 @@ void write_fd_string_8(PORT* port, STRING* str)
|
||||||
if(!can_write(port,str->capacity))
|
if(!can_write(port,str->capacity))
|
||||||
io_error(port,__FUNCTION__);
|
io_error(port,__FUNCTION__);
|
||||||
|
|
||||||
init_buffer(port,B_WRITE);
|
|
||||||
|
|
||||||
c_str = to_c_string(str);
|
c_str = to_c_string(str);
|
||||||
|
|
||||||
/* Append string to buffer */
|
/* Append string to buffer */
|
||||||
|
|
|
@ -21,5 +21,6 @@ void primitive_open_file(void)
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
io_error(NULL,__FUNCTION__);
|
io_error(NULL,__FUNCTION__);
|
||||||
|
|
||||||
dpush(tag_object(port(fd)));
|
dpush(read ? tag_object(port(PORT_READ,fd)) : F);
|
||||||
|
dpush(write ? tag_object(port(PORT_WRITE,fd)) : F);
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,11 @@ bool set_up_fd_set(fd_set* fdset, int fd_count, IO_TASK* io_tasks)
|
||||||
|
|
||||||
bool perform_read_line_io_task(PORT* port)
|
bool perform_read_line_io_task(PORT* port)
|
||||||
{
|
{
|
||||||
init_buffer(port,B_READ_LINE);
|
if(port->line == F)
|
||||||
|
port->line = tag_object(sbuf(LINE_SIZE));
|
||||||
|
else
|
||||||
|
untag_sbuf(port->line)->top = 0;
|
||||||
|
|
||||||
if(port->buf_pos >= port->buf_fill)
|
if(port->buf_pos >= port->buf_fill)
|
||||||
{
|
{
|
||||||
if(!read_step(port))
|
if(!read_step(port))
|
||||||
|
@ -130,7 +134,6 @@ bool perform_read_line_io_task(PORT* port)
|
||||||
|
|
||||||
bool perform_write_io_task(PORT* port)
|
bool perform_write_io_task(PORT* port)
|
||||||
{
|
{
|
||||||
init_buffer(port,B_WRITE);
|
|
||||||
if(write_step(port))
|
if(write_step(port))
|
||||||
{
|
{
|
||||||
if(port->buf_pos == port->buf_fill)
|
if(port->buf_pos == port->buf_fill)
|
||||||
|
@ -243,7 +246,15 @@ CELL next_io_task(void)
|
||||||
|
|
||||||
void primitive_next_io_task(void)
|
void primitive_next_io_task(void)
|
||||||
{
|
{
|
||||||
dpush(next_io_task());
|
CELL callback;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
callback = next_io_task();
|
||||||
|
if(callback != F)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dpush(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_io_tasks(void)
|
void collect_io_tasks(void)
|
||||||
|
|
|
@ -11,19 +11,25 @@ PORT* untag_port(CELL tagged)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
PORT* port(CELL fd)
|
PORT* port(PORT_MODE type, CELL fd)
|
||||||
{
|
{
|
||||||
PORT* port = allot_object(PORT_TYPE,sizeof(PORT));
|
PORT* port = allot_object(PORT_TYPE,sizeof(PORT));
|
||||||
|
port->type = type;
|
||||||
port->fd = fd;
|
port->fd = fd;
|
||||||
port->buffer = NULL;
|
port->buffer = NULL;
|
||||||
port->line = F;
|
port->line = F;
|
||||||
port->client_host = F;
|
port->client_host = F;
|
||||||
port->client_port = F;
|
port->client_port = F;
|
||||||
port->client_socket = F;
|
port->client_socket = F;
|
||||||
port->buf_mode = B_NONE;
|
port->line = F;
|
||||||
port->buf_fill = 0;
|
port->buf_fill = 0;
|
||||||
port->buf_pos = 0;
|
port->buf_pos = 0;
|
||||||
|
|
||||||
|
if(type == PORT_SPECIAL)
|
||||||
|
port->buffer = NULL;
|
||||||
|
else
|
||||||
|
port->buffer = string(BUF_SIZE,'\0');
|
||||||
|
|
||||||
if(fcntl(port->fd,F_SETFL,O_NONBLOCK,1) == -1)
|
if(fcntl(port->fd,F_SETFL,O_NONBLOCK,1) == -1)
|
||||||
io_error(port,__FUNCTION__);
|
io_error(port,__FUNCTION__);
|
||||||
|
|
||||||
|
@ -35,28 +41,6 @@ void primitive_portp(void)
|
||||||
drepl(tag_boolean(typep(PORT_TYPE,dpeek())));
|
drepl(tag_boolean(typep(PORT_TYPE,dpeek())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_buffer(PORT* port, int mode)
|
|
||||||
{
|
|
||||||
if(port->buf_mode == B_NONE)
|
|
||||||
port->buffer = string(BUF_SIZE,'\0');
|
|
||||||
|
|
||||||
if(port->buf_mode != mode)
|
|
||||||
{
|
|
||||||
port->buf_fill = port->buf_pos = 0;
|
|
||||||
port->buf_mode = mode;
|
|
||||||
|
|
||||||
if(mode == B_READ_LINE)
|
|
||||||
port->line = tag_object(sbuf(LINE_SIZE));
|
|
||||||
}
|
|
||||||
else if(port->buf_mode == B_READ_LINE)
|
|
||||||
{
|
|
||||||
if(port->line == F)
|
|
||||||
port->line = tag_object(sbuf(LINE_SIZE));
|
|
||||||
else
|
|
||||||
untag_sbuf(port->line)->top = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void fixup_port(PORT* port)
|
void fixup_port(PORT* port)
|
||||||
{
|
{
|
||||||
port->fd = -1;
|
port->fd = -1;
|
||||||
|
@ -65,7 +49,6 @@ void fixup_port(PORT* port)
|
||||||
fixup(&port->line);
|
fixup(&port->line);
|
||||||
fixup(&port->client_host);
|
fixup(&port->client_host);
|
||||||
fixup(&port->client_port);
|
fixup(&port->client_port);
|
||||||
fixup(&port->client_socket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_port(PORT* port)
|
void collect_port(PORT* port)
|
||||||
|
@ -75,5 +58,4 @@ void collect_port(PORT* port)
|
||||||
copy_object(&port->line);
|
copy_object(&port->line);
|
||||||
copy_object(&port->client_host);
|
copy_object(&port->client_host);
|
||||||
copy_object(&port->client_port);
|
copy_object(&port->client_port);
|
||||||
copy_object(&port->client_socket);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/* Buffer mode */
|
typedef enum { PORT_READ, PORT_WRITE, PORT_SPECIAL } PORT_MODE;
|
||||||
typedef enum { B_READ_LINE, B_WRITE, B_NONE } B_MODE;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CELL header;
|
CELL header;
|
||||||
|
/* one of PORT_READ or PORT_WRITE */
|
||||||
|
PORT_MODE type;
|
||||||
FIXNUM fd;
|
FIXNUM fd;
|
||||||
STRING* buffer;
|
STRING* buffer;
|
||||||
/* tagged partial line used by read_line_fd */
|
/* tagged partial line used by read_line_fd */
|
||||||
|
@ -10,9 +11,8 @@ typedef struct {
|
||||||
/* tagged client info used by accept_fd */
|
/* tagged client info used by accept_fd */
|
||||||
CELL client_host;
|
CELL client_host;
|
||||||
CELL client_port;
|
CELL client_port;
|
||||||
|
/* untagged fd of accepted connection */
|
||||||
CELL client_socket;
|
CELL client_socket;
|
||||||
/* one of B_READ, B_WRITE or B_NONE */
|
|
||||||
B_MODE buf_mode;
|
|
||||||
/* top of buffer */
|
/* top of buffer */
|
||||||
CELL buf_fill;
|
CELL buf_fill;
|
||||||
/* current read/write position */
|
/* current read/write position */
|
||||||
|
@ -20,8 +20,7 @@ typedef struct {
|
||||||
} PORT;
|
} PORT;
|
||||||
|
|
||||||
PORT* untag_port(CELL tagged);
|
PORT* untag_port(CELL tagged);
|
||||||
PORT* port(CELL fd);
|
PORT* port(PORT_MODE type, CELL fd);
|
||||||
void init_buffer(PORT* port, int mode);
|
|
||||||
void primitive_portp(void);
|
void primitive_portp(void);
|
||||||
void fixup_port(PORT* port);
|
void fixup_port(PORT* port);
|
||||||
void collect_port(PORT* port);
|
void collect_port(PORT* port);
|
||||||
|
|
|
@ -40,7 +40,7 @@ int make_server_socket(CHAR port)
|
||||||
void primitive_server_socket(void)
|
void primitive_server_socket(void)
|
||||||
{
|
{
|
||||||
CHAR p = (CHAR)to_fixnum(dpop());
|
CHAR p = (CHAR)to_fixnum(dpop());
|
||||||
dpush(tag_object(port(make_server_socket(p))));
|
dpush(tag_object(port(PORT_SPECIAL,make_server_socket(p))));
|
||||||
}
|
}
|
||||||
|
|
||||||
CELL accept_connection(PORT* p)
|
CELL accept_connection(PORT* p)
|
||||||
|
@ -60,15 +60,16 @@ CELL accept_connection(PORT* p)
|
||||||
p->client_host = tag_object(from_c_string(inet_ntoa(
|
p->client_host = tag_object(from_c_string(inet_ntoa(
|
||||||
clientname.sin_addr)));
|
clientname.sin_addr)));
|
||||||
p->client_port = tag_fixnum(ntohs(clientname.sin_port));
|
p->client_port = tag_fixnum(ntohs(clientname.sin_port));
|
||||||
p->client_socket = tag_object(port(new));
|
p->client_socket = new;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void primitive_accept_fd(void)
|
void primitive_accept_fd(void)
|
||||||
{
|
{
|
||||||
PORT* port = untag_port(dpop());
|
PORT* p = untag_port(dpop());
|
||||||
dpush(port->client_host);
|
dpush(p->client_host);
|
||||||
dpush(port->client_port);
|
dpush(p->client_port);
|
||||||
dpush(port->client_socket);
|
dpush(tag_object(port(PORT_READ,p->client_socket)));
|
||||||
|
dpush(tag_object(port(PORT_WRITE,p->client_socket)));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue