secret
Last active

NotReallyFORTH

  • Download Gist
forth.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
class Proc
def prim_call(stack)
forth_arity = self.arity - 1
if stack.size < forth_arity
puts "Buffer underrun"
stack.clear
return
end
forth_arity > 0 ? self.call(stack, *stack.pop(forth_arity)) : self.call(stack)
end
end
 
stack = []
dictionary = {}
primitives = {
":" => lambda { |stack, s| dictionary[s[1]] = s[2..-2] },
"+" => lambda { |stack, x, y| stack << (x + y) },
"-" => lambda { |stack, x, y| stack << (x - y) },
"*" => lambda { |stack, x, y| stack << (x * y) },
"/" => lambda { |stack, x, y| stack << (x / y) },
"." => lambda { |stack, x| puts "#{x} " },
"dup" => lambda { |stack| stack << stack.last },
"rot" => lambda { |stack| (stack << stack.pop(2).reverse).flatten! },
"clearstack" => lambda { |stack| stack.clear },
".S" => lambda { |stack| puts "<#{stack.size}> #{stack.join(' ')} " },
}
 
parse = lambda do |s, main=true|
tokens = s.split
return primitives[":"].call(stack, tokens) if tokens.first == ":"
tokens.each do |token|
if primitives.has_key?(token)
primitives[token].prim_call(stack)
elsif dictionary.has_key?(token)
dictionary[token].map { |t| parse.call(t, false) }
else
begin
stack << Integer(token)
rescue ArgumentError
puts "Undefined word <<<#{token}>>>"
stack.clear
end
end
end
puts " ok" if main
end
 
puts <<EOF
NotReallyFORTH 0.1
Type 'bye' to exit
EOF
until (s = gets.chomp) == 'bye'
exit unless s
parse.call(s)
end
gistfile1.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
NotReallyFORTH 0.1
Type 'bye' to exit
4 5
ok
.S
<2> 4 5
ok
+
ok
.S
<1> 9
ok
dup + .
18
ok
1 2 3 rot .S
<3> 1 3 2
ok
clearstack
ok
: square dup * ;
5 square .
25
ok
bye

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.