Lines
92.98 %
Functions
75 %
Branches
50 %
// examples from the book Forth Primer..
// http://ficl.sourceforge.net/pdf/Forth_Primer.pdf
#[cfg(test)]
mod tests {
//use super::*;
use forth::forth_compiler::ForthCompiler;
use forth::stack_machine::GasLimit;
use forth::ForthError;
macro_rules! clean_stack (
{$fc: ident, $expr: expr, $result: expr} => {
$fc.sm.st.data_stack.clear();
$fc.execute_string($expr, GasLimit::Limited(100)).unwrap();
assert_eq!($fc.sm.st.data_stack, $result);
}
);
macro_rules! output (
assert_eq!($fc.execute_string($expr, GasLimit::Limited(500)).unwrap(), $result);
macro_rules! error (
assert_eq!($fc.execute_string($expr, GasLimit::Limited(100)).unwrap_err(), $result);
macro_rules! run (
{$fc: ident, $expr: expr} => {
$fc.execute_string($expr, GasLimit::Limited(100)).unwrap()
#[test]
fn chapter2() {
let mut fc = ForthCompiler::new();
// page 9
clean_stack!(fc, "1 2 +", vec![3]);
clean_stack!(fc, "2 3 4 + *", vec![14]);
// page 10
clean_stack!(fc, "7 2 -", vec![5]);
clean_stack!(fc, "2 7 -", vec![-5]);
clean_stack!(fc, "12 3 /", vec![4]);
clean_stack!(fc, "-12 3 /", vec![-4]);
clean_stack!(fc, "4 5 + 2 *", vec![18]);
clean_stack!(fc, "4 5 2 + *", vec![28]);
clean_stack!(fc, "4 5 2 * -", vec![-6]);
output!(fc, "2 3 . . CR", "3 2 \n");
output!(fc, "2 3 swap . . CR", "2 3 \n");
error!(fc, "2 . . cr", ForthError::DROPOfEmptyStack); // this doesn't really throw an error
//output!(fc, "2 . . cr", "2");
output!(fc, "2 dup . . cr", "2 2 \n");
output!(fc, "2 3 dup . . . cr", "3 3 2 \n");
// page 11
output!(fc, "2 3 over . . . cr", "2 3 2 \n");
output!(fc, "2 3 drop .", "2 ");
output!(fc, "1 2 3 . . . cr", "3 2 1 \n");
output!(fc, "1 2 3 rot . . . cr", "1 3 2 \n");
// page 12/13
run!(
fc,
r#": *. * . ; \ this will multiple and print two numbers."#
output!(fc, "2 3 *.", "6 ");
// page 14
output!(fc, r#".( Hello World!)"#, "Hello World!");
output!(fc, r#"." Hello World!""#, "Hello World!");
run!(fc, "variable one");
run!(fc, "6 one !");
output!(fc, "one @ .", "6 ");
output!(fc, "one ?", "6 ");
//page 15
run!(fc, "5 constant five");
output!(fc, "five spaces", " ");
run!(fc, "variable var");
run!(fc, "4 var !");
output!(fc, "var @ 5 > .", "0 ");
// page 16
output!(
r#"
: test
var @ 5 >
if ." Greater" cr
else ." Less or equal" cr
then
;
test"#,
"Less or equal\n"
11 1 do i . cr loop
"1 \n2 \n3 \n4 \n5 \n6 \n7 \n8 \n9 \n10 \n"
0 0 ?do i . cr loop
""
: test \ this is a comment too!
11 1 do i . cr 2 +loop \ this is a comment
"1 \n3 \n5 \n7 \n9 \n"
// page 17
-11 -1 do i . cr -1 +loop
"-1 \n-2 \n-3 \n-4 \n-5 \n-6 \n-7 \n-8 \n-9 \n-10 \n"
": -TwoByTwo 0 10 DO I . -2 +LOOP ; -TwoByTwo",
"10 8 6 4 2 "
16384 1 do i . i +loop
"1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 "
/*
// unknown token "leave"
10 0 do dup 5 = if drop leave else . cr then loop
"0 \n1 \n2 \n3 \n4 "
*/
: fib 0 1
begin
dup >r rot dup r> > \ condition
while
rot rot dup rot + dup . \ body
repeat
drop drop drop ; \ after loop has executed"
20 fib "#,
"1 2 3 5 8 13 21 "
// page 18
// problems with comments \
r"
: lcd
swap over mod \ body
dup 0= \ condition
until drop . ;
27 21 lcd",
"3 "
// page 19
output!(fc, r#"
: number ( a -- n)
0. Rot dup 1+ c@ [char] - = >r count r@ if 1 /string then >number nip
0= if d>s r> if negate then else r> drop 2drop (error) then ;
: input# ( -- n)
refill drop bl word number ( n)
dup (error) <> ( n f)
dup 0= ( n f -f)
if swap drop then ( f | n f)
until ;")
output!(fc, "140 . cr", "140 \n");
output!(fc, "150 5 .r cr", " 150\n");
#[should_panic]
fn chapter2_panic1() {
// this will produce an infinite loop..
begin ." Diamonds are forever" cr 0 until
test"#
fn chapter2_panic2() {
begin ." Diamonds are forever" cr again
fn chapter3() {
//let mut fc = ForthCompiler::new();
// page 21
// create an array called sixteen with 16 cells
run!(fc, "create sixteen 16 cells allot");
run!(fc, "5 sixteen 0 cells + !"); // puts the value of 5 in the 0th cell
run!(fc, "7 sixteen 8 cells + !"); // puts the value of 5 in the 0th cell
output!(fc "sixteen 0 cells + @", "5 ");
output!(fc "sixteen 8 cells + @", "7 ");
// create an array of contants..
run!(fc, "create sizes 18 , 21 , 24 , 27 , 30 , 255 ,");
// page 22
output!(fc, "sixteen 0 cells + @ .", "5 ");
output!(fc, "sizes 0 cells + @ .", "18 ");
// allocates (creates an arrya of chars)
run!(fc, "create name 10 chars allot");
run!(fc, "create hello 7 chars allot");
run!(fc, "hello");
run!(fc, "dup");
run!(fc, "drop drop");
run!(fc, ": place over over >r >r char+ swap chars cmove r> r> c! ;")
run!(fc, "create name 16 chars allot");
run!(fc, r"$" Hello! " name place");
run!(fc, ": place over over >r >r char+ swap chars cmove r> r> c! ;");
run!(fc, "create greeting 32 chars allot \ define string greeting");
//run!(fc, r"S" Hello!" greeting place \ set string to 'Hello!'");
run!(fc, "greeting count \ get string length");
run!(fc, ".( String length: ) . cr \ print the length");
run!(fc, "drop \ discard the address");
run!(fc, ": length$ count swap drop ;")
run!(fc, "create greeting 32 cells allot \ define string greeting");
run!(fc, r"s" Hello!"" greeting place \ set string to 'Hello!'");
run!(fc, "greeting legnth$ \ get string length");
run!(fc, "greeting count type cr \ print the string", "Hello!");
// page 24