350 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			350 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# HAK - Command Language
 | 
						|
 | 
						|

 | 
						|
 | 
						|
## Language Syntax
 | 
						|
 | 
						|
A HAK program is composed of expressions.
 | 
						|
 | 
						|
## Keywords
 | 
						|
- nil
 | 
						|
- true
 | 
						|
- false
 | 
						|
 | 
						|
## Special Form Expression
 | 
						|
- and
 | 
						|
- break
 | 
						|
- class
 | 
						|
- fun
 | 
						|
- do
 | 
						|
- elif
 | 
						|
- else
 | 
						|
- fun
 | 
						|
- if
 | 
						|
- lambda
 | 
						|
- or
 | 
						|
- return
 | 
						|
- set
 | 
						|
- until
 | 
						|
- while
 | 
						|
 | 
						|
### do
 | 
						|
 | 
						|
```
 | 
						|
do;
 | 
						|
do 10;
 | 
						|
do { | k | set k 20; printf "k=%d\n" k; };
 | 
						|
```
 | 
						|
 | 
						|
## Literals
 | 
						|
- integer
 | 
						|
- character `'c'`
 | 
						|
- small pointer
 | 
						|
- error
 | 
						|
- string `"string"`
 | 
						|
- byte-string `b"string"`
 | 
						|
- symbol `#"symbol"`
 | 
						|
 | 
						|
## Basic Expressions
 | 
						|
- dictionary `#{ }`
 | 
						|
- array `#[ ]`
 | 
						|
- byte array `#b[ ]`
 | 
						|
- character array `#c[ ]`
 | 
						|
- list `#( )`
 | 
						|
- function calls `( )`
 | 
						|
- message sends `(rcv:msg arg1 ...)`
 | 
						|
- variable declaration `| |`
 | 
						|
- class variable delcarations `:: [ v1 [cv1 cv2 ...] v2 ... ] `
 | 
						|
- assignment `var :=  value`
 | 
						|
 | 
						|
## Builtin functions
 | 
						|
 | 
						|
* not
 | 
						|
* _and
 | 
						|
* _or
 | 
						|
* eqv?
 | 
						|
* eql?
 | 
						|
* eqk?
 | 
						|
* nqv?
 | 
						|
* nql?
 | 
						|
* nqk?
 | 
						|
* sprintf
 | 
						|
* printf
 | 
						|
* _+_
 | 
						|
* _-_
 | 
						|
* _*_
 | 
						|
* mlt
 | 
						|
* /
 | 
						|
* quo
 | 
						|
* mod
 | 
						|
* sqrt
 | 
						|
* bit-and
 | 
						|
* bit-or
 | 
						|
* bit-xor
 | 
						|
* bit-not
 | 
						|
* bit-shift
 | 
						|
* bit-left-shift
 | 
						|
* bit-right-shift
 | 
						|
 | 
						|
## Defining a function
 | 
						|
 | 
						|
```
 | 
						|
fun function-name(arguments) {
 | 
						|
	| local variables |
 | 
						|
	function body
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
```
 | 
						|
set function-name (fun(arguments) {
 | 
						|
	| local variables |
 | 
						|
	function body
 | 
						|
})
 | 
						|
```
 | 
						|
 | 
						|
## Class
 | 
						|
 | 
						|
```
 | 
						|
class[attributes] Name: Superclass (ivars (cvars)) {
 | 
						|
    ivar ivar1
 | 
						|
    cvar cvar1
 | 
						|
 | 
						|
    set cvar1 20
 | 
						|
 | 
						|
    fun[attributes] name(arguments) {
 | 
						|
        | local variables |
 | 
						|
        function body
 | 
						|
    }
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
 | 
						|
```
 | 
						|
class[#b] B (a b) {
 | 
						|
    fun[#ci] new() {
 | 
						|
        self.a := 88
 | 
						|
        self.b := 99
 | 
						|
    }
 | 
						|
 | 
						|
    fun print() {
 | 
						|
        printf "A: %d B: %d\n" self.a self.b
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class[#b] C: B (c) {
 | 
						|
    fun[#ci] new() {
 | 
						|
        super:new
 | 
						|
        self.c := 77
 | 
						|
    }
 | 
						|
 | 
						|
    fun print() {
 | 
						|
        super:print
 | 
						|
        printf "C: %d\n" self.c
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
x := (C:new)
 | 
						|
x:print
 | 
						|
```
 | 
						|
 | 
						|
 | 
						|
## Redefining a primitive function
 | 
						|
 | 
						|
```
 | 
						|
fun + (a b) {
 | 
						|
	core.+ a b 9999
 | 
						|
)
 | 
						|
printf "%d\n" (+ 10 20)
 | 
						|
```
 | 
						|
 | 
						|
## Variadic arguments
 | 
						|
 | 
						|
```
 | 
						|
fun fn-y (t1 t2 va-ctx) {
 | 
						|
        | i |
 | 
						|
        set i 0
 | 
						|
        while (< i (va-count va-ctx)) {
 | 
						|
                printf "fn-y=>Y-VA[%d]=>[%d]\n" i (va-get i va-ctx)
 | 
						|
                set i (+ i 1)
 | 
						|
        }
 | 
						|
}
 | 
						|
 | 
						|
fun x(a b ... :: x y z) {
 | 
						|
    |i|
 | 
						|
 | 
						|
##  printf "VA_COUNT(x) = %d\n" (va-count)
 | 
						|
    set x "xxx"
 | 
						|
    set y "yyy"
 | 
						|
    set z "zzz"
 | 
						|
    set z (+ a b)
 | 
						|
 | 
						|
    set i 0
 | 
						|
    while (< i (va-count)) {
 | 
						|
        printf "VA[%d]=>[%d]\n" i (va-get i)
 | 
						|
        set i (+ i 1)
 | 
						|
    }
 | 
						|
    fn-y "hello" "world" (va-context)
 | 
						|
 | 
						|
    return
 | 
						|
}
 | 
						|
 | 
						|
printf "--------------------------\n"
 | 
						|
printf "[%O]\n" (x 10 20 30)
 | 
						|
printf "--------------------------\n"
 | 
						|
set q (set-r a b c (x 10 20 30 40 50))
 | 
						|
printf "--------------------------\n"
 | 
						|
```
 | 
						|
 | 
						|
## HAK Exchange Protocol
 | 
						|
 | 
						|
The HAK library contains a simple server/client libraries that can exchange
 | 
						|
HAK scripts and results over network. The following describes the protocol
 | 
						|
briefly.
 | 
						|
 | 
						|
### Request message
 | 
						|
TODO: fill here
 | 
						|
 | 
						|
.BEGIN
 | 
						|
.SCRIPT
 | 
						|
.END
 | 
						|
.EXIT
 | 
						|
.KILL-WORKER
 | 
						|
.SHOW-WORKERS
 | 
						|
 | 
						|
 | 
						|
You can send a single-line script with a .SCRIPT command.
 | 
						|
 | 
						|
 .SCRIPT (printf "hello, world\n")
 | 
						|
 | 
						|
If the script is long and contains line-breaks, enclose multiple .SCRIPT commands 
 | 
						|
with the .BEGIN and .END command.
 | 
						|
 | 
						|
  .BEGIN
 | 
						|
  .SCRIPT (printf "hello ")
 | 
						|
  .SCRIPT (printf "world\n")
 | 
						|
  .END
 | 
						|
 | 
						|
### Reponse message
 | 
						|
 | 
						|
There are two types of response messages.
 | 
						|
 - Short-form response
 | 
						|
 - Long-form response
 | 
						|
 | 
						|
A short-form response is useful when you reply with a single unit of data.
 | 
						|
A long-form response is useful when the actual data to return is more complex.
 | 
						|
 | 
						|
#### Short-form response
 | 
						|
A short-form response is composed of a status line. The status line may span 
 | 
						|
across multiple line if the single response data item can span across multiple
 | 
						|
lines without ambiguity. A short-form response begins with a status word. 
 | 
						|
The status word gets followed by an single data item.
 | 
						|
 | 
						|
There are 2 status word defined.
 | 
						|
 - .OK
 | 
						|
 - .ERROR
 | 
						|
 | 
						|
The data must begin on the same line as the status word and there should be 
 | 
						|
as least 1 whitespace characters between the status word and the beginning of
 | 
						|
the data. The optional data must be processible as a single unit of data. The
 | 
						|
followings are accepted:
 | 
						|
 | 
						|
 * unquoted text line
 | 
						|
   ** The end of the data is denoted by a newline character. The newline
 | 
						|
      character also terminates the status line.
 | 
						|
   ** Leading and trailing spaces must be trimmed off
 | 
						|
 * quoted text
 | 
						|
   ** If the first meaningful character of the option data is a double quote,
 | 
						|
      the option data ends when another ordinary double quote is encounted.
 | 
						|
   ** If a double quote is preceded by a backslash(\"), the double quote becomes
 | 
						|
      part of the data and doesn't end the data.
 | 
						|
   ** Not only the double quote, any character character escaped by a preceding
 | 
						|
      backslash is treated literally. (e.g. \\ -> a single back slash, \n -> n)
 | 
						|
   ** Trailing spaces after the ending quote must be ignored until a newline
 | 
						|
      character is encounted. The newline character terminates the status line.
 | 
						|
    
 | 
						|
Take note of the followings when parsing a short-form response message
 | 
						|
 * Whitespace characters before the status word shall get ignored.
 | 
						|
 | 
						|
See the following samples.
 | 
						|
 | 
						|
  .OK authentication success
 | 
						|
 | 
						|
  .ERROR double login attempt
 | 
						|
 | 
						|
  .OK "authentication\twas\tsuccessful"
 | 
						|
 | 
						|
  .OK "this is a multi-line
 | 
						|
    string message"
 | 
						|
 | 
						|
 | 
						|
#### Long-form response
 | 
						|
 | 
						|
A long-form response begins with the status word line. The status line 
 | 
						|
should be composed of the status word and a new line. The status line must
 | 
						|
get followed by data format line and the actual response data. Optional 
 | 
						|
attribute lines may get inserted between the status line and the data format
 | 
						|
line.
 | 
						|
 | 
						|
The data format line begins with .DATA and it can get followed by a data length
 | 
						|
or the word 'chunked'.
 | 
						|
 | 
						|
 * .DATA <NNN>
 | 
						|
 * .DATA chunked
 | 
						|
 
 | 
						|
Use .DATA <NNN> where <NNN> indicates the length of data in bytes if the
 | 
						|
response data is length-bounded. For instance, .DATA 1234 indicates that
 | 
						|
the following data is 1234 bytes long.
 | 
						|
 | 
						|
Use .DATA chunked if you don't know the length of response data in advance.
 | 
						|
 | 
						|
The actual data begins at the next line to .DATA.
 | 
						|
 | 
						|
The length-bounded response message looks like this. The response message 
 | 
						|
handler must consume exactly the number of bytes specifed on the .LENGTH line
 | 
						|
starting from the beginning of the next line to .DATA without ignoring any 
 | 
						|
characters.
 | 
						|
 | 
						|
```
 | 
						|
 .OK
 | 
						|
 .DATA 10
 | 
						|
 aaaaaaaaaa
 | 
						|
```
 | 
						|
 | 
						|
The chunked data looks like this. Each chunk begins with the length and a colon.
 | 
						|
The 0 sized chunk indicates the end of data. A chunk size is in decimal and is
 | 
						|
followed by a colon. The actual data chunk starts immediately after the colon.
 | 
						|
The response processor must consume exactly the number of bytes specified in
 | 
						|
the chunk size part and attempt to read the size of the next chunk. 
 | 
						|
 | 
						|
The whitespaces between the end of the previous chunk data and the next chunk
 | 
						|
size, if any, should get ignored.
 | 
						|
 | 
						|
```
 | 
						|
 .OK
 | 
						|
 .DATA chunked
 | 
						|
 4:xxxx10:abcdef
 | 
						|
 ghi
 | 
						|
 0:
 | 
						|
```
 | 
						|
 | 
						|
With the chunked data transfer format, you can revoke the ongoing response data
 | 
						|
and start a new response.
 | 
						|
 | 
						|
```
 | 
						|
 .OK
 | 
						|
 .DATA chunked
 | 
						|
 4:xxxx-1:.ERROR "error has occurred"
 | 
						|
```
 | 
						|
 | 
						|
An optional attribute line is composed of the attribute name and the attribute
 | 
						|
value delimited by a whitespace. There are no defined attributes but the attribute
 | 
						|
name must not be one of .OK, ERROR, .DATA. The attribute value follows the same
 | 
						|
format as the status data of the short-form response.
 | 
						|
 | 
						|
```
 | 
						|
 .OK
 | 
						|
 .TYPE json/utf8
 | 
						|
 .DATA chunked
 | 
						|
 ....
 | 
						|
```
 |