MiniForth is a typeless concatenative language, which can be compiled into bitcoin opcodes.
- have erlang and elixir installed in your machine, recommend using asdf to install
- Clone this repo, cd into the directory.
cd c
mix deps.get
MIX_ENV=prod mix escript.build
Create a new file hello.fth
, and write:
: main "hello" drop ;
Run ./mini_forth hello.fth
. Then the terminal will print:
[RAW SCRIPT]
"68656c6c6f OP_DROP"
[EVAL RESULT]
MainStack: []
AltStack: []
There're some code examples in /example
directory.
MiniForth code | Bitcoin Sciprt ( can be read by bsv.js ) | Description |
---|---|---|
0 1 2 3 | OP_0 OP_1 OP_2 OP_3 | Numbers |
0xFF 0xff 0x1234 | ff00 ff00 3412 | Hex Numbers |
-1 -2 -3 | OP_1NEGATE 82 83 | Negative Numbers |
"hello world" | 68656c6c6f20776f726c64 | ASCII String |
<<0, 1, 2, 3, 0x04>> | 0001020304 | Bytes |
MiniForth code | Bitcoin Sciprt ( can be read by bsv.js ) | Description |
---|---|---|
+ - * / % | OP_ADD OP_SUB OP_MUL OP_DIV OP_MOD | |
1- | OP_1SUB | |
num= | OP_NUMEQUAL | |
num=verify | OP_NUMEQUALVERIFY | |
and or not not0 | OP_BOOLAND OP_BOOLOR OP_NOT OP_0NOTEQUAL | |
>= <= > < | OP_GREATERTHANOREQUAL OP_LESSTHANOREQUAL OP_GREATERTHAN OP_LESSTHAN |
MiniForth code | Bitcoin Sciprt ( can be read by bsv.js ) | Description |
---|---|---|
= | OP_EQUAL | |
=verify | OP_EQUALVERIFY | |
& | ^ ~ | OP_AND OP_OR OP_XOR OP_INVERT |
- OP_CHECKSIG
- OP_CHECKSIGVERIFY
- OP_CHECKMULTISIG
- OP_CHECKMULTISIGVERIFY
Other opcodes are expressed with downcase words, for example: drop swap
stands for OP_DROP OP_SWAP
.
MiniForth code | Bitcoin Sciprt ( can be read by bsv.js ) | Description |
---|---|---|
. | ignore | Print the top element |
cr | ignore | Print a new line |
print_stack | ignore | Print two stacks |
The syntax is basically a simplified version of Forth language.
: 3sub 3 - ;
\ a line starts with '\' is comment
\ we use ( a -- b ) to comment the arguments and returns of a word
: left ( str n -- left_str )
split drop ;
: import
"./example/binary"
;
: main
"abcde" 1 2 binary:substr
"bc" =verify
;
\ the loop will be unroll at compile time
: dup3times ( -- )
3 0 do dup loop ;
\ will be compile into `OP_DUP OP_DUP OP_DUP`
\ can use the +loop to specify the step
: countdown
0 10 do cr i . -1 +loop ;
\ the code inside a `[ ]` is a quote
\ when the compiler see `literal`, it will execute nearest quote
\ and place the result at the position of `literal`
\ this code equal to `: two 2 ;`
: two [ 1 1 + ] literal ;
MiniForth Code | Example | Description |
---|---|---|
eval | [ 1 1 + ] eval ---> 2 | Execute the quote |
curry | 1 [ 1 + ] curry ---> [ 1 1 + ] | Merge the second element into the quote |
call | [ 1 1 + ] call ---> 1 1 + | Unquote |
The code between macro_start
and macro_end
will be executed at compile time.
\ we can define such a function
\ which takes 2 args, one is compile
\ time arg, and another is runtime arg
: simple_macro ( compile_time_arg runtime_arg -- a b )
[ 3 + ]
macro_start
swap tas curry eval fas
macro_end
+
;
\ compiled code: 4 2 + ;
: main 1 2 simple_macro ;
These functions are borrowed from the Factor language.
\ equal to `1 1 + 1 2 *`
: main 1 [ 1 + ] [ 2 * ] bi ;
\ equal to `1 1 + 1 2 + 1 3 +`
: main 1 [ 1 + ] [ 2 + ] [ 3 + ] tri ;
If you have any questions or errors during the use, please raise an issue or ask questions on the Bitcoin Script channel of Powping.