Форточка - передовая форт-машина
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src
.gitignore
LICENSE
Makefile
Readme
rebuild.sh
start.sh
stdlib.frt
test1.frt
test2.frt
testing.sh

Readme

This is forto4ka - hand-made forth machine written in x86 assemly language

Type 'make' or 'chmod +x ./start.sh && ./start.sh' to run the machine

************************************
Scripts:
./start.sh: build machine and start it using stdlib
./rebuild.sh: rebuild machine
./testing.sh: rebuild and test it

***********************************
There is:
~ Interpeter
~ Compiler: you can define your own word like this : sq dup * ;
~ Also you can define words using ones you had defined earlier: sq3 dup sq * ;
~ Compiler supports immediate-words
~ Stdlib.frt with words like 'IMMEDIATE', 'if', 'then'. It uses Metaprogramming.

***********************************
Features:
~ Interptet loop and compiler loop are orginized separatly
~ Using for_each function in assemly
~ There's no 0branch but branch_if instead


***********************************
Lacks and bugs:
~ There's no for-endfor
~ There's no full compatibility with forthress machine
~ " word doesn't work in compile-time. You can't use it in your words
~ here works strange 

**********************************
Author:
Oshepkov Artem

vk.com/oshepkovtemka
github.com/semitro

inspired by Igor Jirkov:
github.com/sayon

( IFMO System Level Programming course 2018 )

**************************
List of implemented words:
**************************
* to enter a colon word
native "docol", docol
* to exit a colon word
native "leave", leave

* exit from the promgram
native "bye", bye
*INIT
native "init", init

* COMPILE THINGS 
colon  ":", switch_to_compiler
native ":to_compiler", to_compiler

* pushes xt to colon word being built at the moment 
* ( xt )
native ":push_word", push_word

* if value is on the tos during compile-time
* but we want it to be there on each invoking of the function
* this word will help us:
* ( value -- ) - lit value
colon "pull_tos_with_literal", pull_tos_with_literal

* ( char* name )
* creates name of new word (doesn't check if word exists yet )
* we will find word by this name in future
* it creates just a header of the colon word being created
native ":create_word", create_word, _IMMEDIATE

* stop compiling 
native ";", switch_to_enterpr, _IMMEDIATE

* COMPILER LOOP 
* compiler and interpeter loops are organazied
* separately because I think it's more finicky
colon "compiler", compiler

* MAIN_THING 
colon "interpret", interpret

* THINGS PRINTING THINGS
colon "print_welcome", print_welcome
colon "print_no_word", print_no_word

native "ls", list_all_words

* BRANCHES 
* ( bool tos - )
* run next word if tos != 0
* DANGEROUS: DON'T use macro "branch" after!
* 'cause it stores addr as word after itself 
native "run_if", run_if

* ( bool value - )
* Does branch if tos != 0
native "branch_if", branch_if
native "go_to_tos", go_to_tos
native "go_to_tos_if", go_to_tos_if

* jmp to label right after word
* only in precompile
native "branch", branch 
* execute word by it's xt

* ( void* xt - )
native 'execute', execute

* (char* str - )
* prints string
native 'print', print
* (char c - )
* prints single character to stdout
native 'emit', emit

* prints \n character
native 'cr', cr

* HARDCODED ADDRS THINGS 
native 'get_no_such_word_buffer', get_no_such_word_buffer
native 'get_input_buffer', get_input_buffer

* ( char* - )
* read a word from stdin and store it into the addr
native 'read_word', read_word

* (char* -- )
* read a char and store it
native 'readc@', readc@

* (char* - )	
native 'count', count

* ( char* str - n, n.lenght )
* ( if it's not a number, n.lenght=0, n itself is undef )	
native 'parse_int', parse_int
colon 'is_num', is_num

* ( char* buff - void* word_hdr)
native 'find_word_hdr', find_word_hdr

* ( char* buff - void* word_exec_code )
native 'find_word_xt', find_word_xt

* ( word hdr - immediate?: boolean ) 
native 'is_word_immediate', is_immediate

* it's helpful for debug
native '42', 42, 
native '43', 43

* MEMORY THINGS 
* fetch dq from memory
* ( addr - value )
native '@', @

* fetch byte from memory
* ( addr - byte )
native 'c@', c@

* store dq value by addres
* ( value, addr -- )
native '!', store_dq

* store byte value by addres
* ( byte, addr -- )
native 'c!', store_byte

* from data stack into return stack
native '>r', r_to 
* from return stack into data stack
native 'r>', r_from
native 'r@', r_fetch

* take the address of the end of the heap''
native 'dp', heap_end

* push input buffer addres
native 'inbuf', inbuf

* push next dq thing onto the stack
native 'lit', lit

* pushes an adrres of an adress of the header of the last word
native 'last_word', last_word

* points to the last word currently being defined 
native 'here', here

* add x to the word-ceil currentl being built 
* ( x -- )
colon ',', comma
colon "'", give_me_xt_of_the_next_word, _IMMEDIATE

* read a word in compile and place its xt here
colon "'to_lit", next_and_to_lit, _IMMEDIATE
native 'nop', nothing
native 'exit', exit

* convert header to xt
* ( hdr* - xt )
native 'cfa', cfa

* STACK THINGS 
native 'dup', dup
native 'drop', drop
native '.', .
native '.S', show_stack 

* ( a b - b a ) 
native 'swap', swap
* ( a b c - b c a )
native 'rot', rot

* STRINGS 
* ( char* s1, char* s2 - equals? )
native 'string_equals', string_equals

* LOGIC 
native '<', less
native 'not', not
native '=', equals

native 'and', bit_and
* ( a,b - a & b )
native 'land', logical_and
native 'or', bit_bor
native 'lor', logical_or

* ARIFMETIC 
native '+', plus
native '-', substract
native '*', mul
native '/', div
native '%', mod