FORTH: nanosilver and nanoclay. Part 1

It's time to talk about another side of the wonderful use of language the Fort.
This series of articles I'll show you how it can be used to create a tiny client / server application. Each of which can be used as a research and teaching tool.
For entertainment, we need the Windows down to seven and the package SP-Forth. Andrey Cherezov has declared the possibility of launching its Fort system under Linux, but I have not tested it.

To begin, let's create a simple server program that will give the subscribing client well... let's say the current date and time on the server.


Create in Notepad or any other text editor (Akelpad) file datetimes.f in the same folder where the file spf4.exe.

What do we need to create a server? The sockets!
To begin to work with them it is necessary to connect appropriate library.
the ~nn\lib\sock2.f

Ideally, all libraries are stored in the source texts. You can always look and see what it is and how it works.

the
0 VALUE sockt
0 VALUE sockt_a
SocketsStartup THROW .( Sockets started) CR 
CreateSocket THROW TO sockt .( Socket created) CR

The first two lines — obviously the definition of variables. VALUE variables are to improve the traditional Fort. They allow you to avoid infinite dereferences (get the value at the address) and make the text more readable.
The third line speaks for itself, at last it is necessary to give a few comments.
The word CreateSoket clear about it, but there are nuances. Sockets-are different! Honestly the sorts of sockets I can't say much, but the simplest and, seemingly, the most commonly used is a blocking bi-directional streaming TCP/IP socket that is created by this word. How to create a socket of another type, you can look in the library. Magic THROW only catches errors and throws an exception if the error code is nonzero. Parenthesis is printed on the terminal the text between them, CR — line feed.
the
 
80 sockt BindSocket THROW .( Socket binded) CR
sockt ListenSocket THROW .( Listen) CR
AcceptSocket THROW TO sockt sockt_a .( Accept connection from:) 

That's almost all. Now we sit and listen on port 80, until someone knocks.
Of course, you can choose a completely arbitrary free port.
The word AcceptSoket will stop program execution until a connection is made.
Who has joined us?

the
sockt_a GetPeerIP&Port THROW SWAP NtoA TYPE ." port:" . 

displays in the console the IP address and port from which the connection originated. The only SWAP in the entire program arose only because of the not quite thought out the implementation of the word GetPeerIP&Port.

Prepare a date and time to be sent.
We need another library

the lib\include\facil.f

You want the word TIME&DATE. ( Had to fix it in the library, now it differs from complete. It was to issue a millisecond, and changed the order date. ) This word puts on stack the 7 values. Milliseconds, seconds, hours, year, month, day. Accordingly, the first from the stack will be removed. There is a view of the month.

the
S" Current time: sockt_a WriteSocket THROW
S > D (D.) sockt_a WriteSocket THROW ( day)
S" -" sockt_a WriteSocket THROW
S > D (D.) sockt_a WriteSocket THROW ( month)
S" -" sockt_a WriteSocket THROW
S > D (D.) sockt_a WriteSocket THROW ( year)
S" " sockt_a WriteSocket THROW
S > D (D.) sockt_a WriteSocket THROW ( hours)
S" -" sockt_a WriteSocket THROW
S > D (D.) sockt_a WriteSocket THROW ( minutes)
S" -" sockt_a WriteSocket THROW
S > D (D.) sockt_a WriteSocket THROW ( seconds)
S" -" sockt_a WriteSocket THROW
S > D (D.) sockt_a WriteSocket THROW ( milliseconds)


Looks terrible. The beauty of the Fort is that this mess can be turned into candy.
It is seen that the same text is repeated 7 two times 3. Of course, can be put into the cycle, but then the text is difficult to read.
Use the opportunities of the Fort.

Define additional words

the
: send_value S > D (D.) sockt_a WriteSocket THROW ;
: send_delimeter sockt_a WriteSocket THROW ;


It is logical, clear and easily readable. the { Note: the Word S>D extends the sign of the top element of the stack to double precision. Word (d) converts a double-precision number to a string and puts it on the stack its address and the counter.}
the
: Day send_value ;
: Month send_value ;
Year send_value ;
: Hours send_value ;
: Minutes send_value ;
: Seconds send_value ;
: Milliseconds send_value ; 


Still terrible. What can you do?
Comes to the aid of one key feature of the forth language. We can create your own defining words.

the
: make_value CREATE DOES> DROP send_value ;
: make_value make_values 0 DO LOOP ; 


The word make_value during your performance will select from the input stream the following set of characters bounded by spaces and put it on top of the current dictionary. The semantics of this new word set the word after DOES>. That is, we have a tool with which you can create concepts with a common semantics.

the
7 make_values Day Month Year Hours Minutes Seconds Milliseconds 


And for separators

the
: make_delimeter CREATE , DOES> 1 send_delimeter ;
: make_delimeters make_delimeter 0 DO LOOP ;

BL CHAR - CHAR : 3 make_delimeters : - _


Now can write beautifully

the
TIME&DATE
Day - Month - Year _ Hours : Minutes : Seconds : Milliseconds 


Tear connection

the
sockt_a THROW CloseSocket


And clean the sockets

the
SocketsCleanup THROW 


All.

As you can see the stages of execution and compilation can be interleaved. This is another basic feature of the Fort. Well-written forth program almost requires no comment.
Who were careful enough, you will notice that we have overridden the base word followed by a colon and a minus. How about this? Answer below.

the

Combed the code


the
~nn\lib\sock2.f 
lib\include\facil.f

CONSTANT port 80
0 VALUE sockt
0 VALUE sockt_a

: send_value S > D (D.) sockt_a WriteSocket THROW ;
: send_delimeter sockt_a WriteSocket THROW ;

: make_value CREATE DOES> DROP send_value ;
: make_value make_values 0 DO LOOP ;

7 make_values Day Month Year Hours Minutes Seconds Milliseconds 

: make_delimeter CREATE , DOES> 1 send_delimeter ;
: make_delimeters make_delimeter 0 DO LOOP ;

: define: : ;

BL CHAR - CHAR : 3 make_delimeters : - _



define: time&date_server 

SocketsStartup THROW ." Sockets started" CR 
CreateSocket THROW TO sockt ." Socket created" CR

port sockt BindSocket THROW ." Socket binded" CR
sockt ListenSocket THROW ." Listen to" CR

AcceptSocket THROW TO sockt sockt_a ." Accept connection from:" 
sockt_a GetPeerIP&Port THROW SWAP NtoA TYPE ." port:" . 

S" Current time:" sockt_a WriteSocket THROW

TIME&DATE 

Day - Month - Year _ Hours : Minutes : Seconds : Milliseconds 

sockt_a CloseSocket THROW 

SocketsCleanup THROW 
;

time&date_server 
Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

Wikia Search — first impressions

Emulator data from GNSS receiver NMEA

mSearch: search + filter for MODX Revolution