-
-
Save fogus/1680793 to your computer and use it in GitHub Desktop.
Revisions
-
deadprogram revised this gist
Jan 26, 2012 . 1 changed file with 14 additions and 45 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,27 +1,17 @@ #!/usr/bin/env ruby def pop; $stack.pop || raise(StackUnderflow); end def push(expression); $stack << expression; end def unary; -> { push(yield pop) }; end def binary; -> { push(yield pop, pop) }; end def unary_boolean; -> { push(if yield pop then 1 else 0 end) }; end def binary_boolean; -> { push(if yield pop, pop then 1 else 0 end) }; end def swap; $stack[-2,2] = $stack[-2,2].reverse; end $stack = [] def new_word raise EmptyWord if $word.size < 1 raise NestedDefinition if $word.include? ':' name, expression = $word.shift, $word.join(' ') $dictionary[name] = -> { parse(expression) } $word = nil @@ -32,29 +22,17 @@ def parse(expression) begin expression.split.each do |statement| case when !$skip.nil? && statement != 'fi'; next when !$word.nil? && statement != ';'; $word << statement when $dictionary.has_key?(statement); $dictionary[statement].call else push statement.to_i end end rescue puts "Error: #{$!}" end end $dictionary = { '+' => binary { |a, b| a + b }, '-' => binary { |a, b| a - b }, @@ -81,15 +59,6 @@ def parse(expression) 'swap' => -> { begin swap rescue raise(StackUnderflow) end } } puts "Ruby Forth interpreter: enter commands at the prompt" while ARGV.size > 0; open(ARGV.shift).each { |line| parse(line) }; end while true; print "> "; break unless gets; parse $_; end -
deadprogram revised this gist
Jan 15, 2012 . 1 changed file with 0 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,11 +1,9 @@ #!/usr/bin/env ruby def pop $stack.pop || raise(StackUnderflow) end def push(expression) $stack << expression end -
deadprogram revised this gist
Jan 15, 2012 . 1 changed file with 9 additions and 33 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -11,63 +11,44 @@ def push(expression) end # Word helpers def unary; -> { push(yield pop) } end def binary; -> { push(yield pop, pop) } end def unary_boolean; -> { push(if yield pop then 1 else 0 end) } end def binary_boolean; -> { push(if yield pop, pop then 1 else 0 end) } end def swap $stack[-2,2] = $stack[-2,2].reverse end def new_word raise EmptyWord if $word.size < 1 raise NestedDefinition if $word.include? ':' name, expression = $word.shift, $word.join(' ') $dictionary[name] = -> { parse(expression) } $word = nil end def parse(expression) puts "=> #{expression}" begin expression.split.each do |statement| case when !$skip.nil? && statement != 'fi' next when !$word.nil? && statement != ';' $word << statement when $dictionary.has_key?(statement) $dictionary[statement].call else push statement.to_i end end rescue puts "Error: #{$!}" end end @@ -89,16 +70,16 @@ def parse(expression) '|' => binary_boolean { |a, b| a || b }, 'not' => binary_boolean { |a, b| a == 0 }, 'neg' => binary { |a| -a }, '.' => -> { puts(pop) }, '..' => -> { puts($stack) }, ':' => -> { $word = [] }, ';' => -> { new_word }, 'pop' => -> { pop }, 'fi' => -> { $skip = nil }, 'words' => -> { p $dictionary.keys.sort }, 'if' => -> { $skip = true if pop == 0 }, 'dup' => -> { push($stack.last || raise(StackUnderflow)) }, 'over' => -> { push($stack.last(2).first || raise(StackUnderflow)) }, 'swap' => -> { begin swap rescue raise(StackUnderflow) end } } @@ -110,12 +91,7 @@ def parse(expression) # Here's the REPL while true print "> " break unless gets parse $_ end -
Kurtis Rainbolt-Greene revised this gist
Jan 15, 2012 . 1 changed file with 108 additions and 61 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,74 +1,121 @@ #!/usr/bin/env ruby # Return and remove the last value of the stack array def pop $stack.pop || raise(StackUnderflow) end # Add a expression to the stack def push(expression) $stack << expression end # Word helpers def unary -> { push yield pop } end def binary -> { push yield pop, pop } end def unary_boolean -> { push(if yield pop then 1 else 0 end) } end def binary_boolean -> { push(if yield pop, pop then 1 else 0 end) } end def swap $stack[-2,2] = $stack[-2,2].reverse end # Create a new word from the expressions given def new_word # If there was no word, raise with an EmptyWord error raise EmptyWord if $word.size < 1 # If the definition of the word has a definition, raise NestedDefintion raise NestedDefinition if $word.include? ':' # Extract the name and expression from the word array name, expression = $word.shift, $word.join(' ') # Create a new word on the dictionary $dictionary[name] = -> { parse expression } # Reset the word variable $word = nil end # Parse the expression given def parse(expression) # Output the return of the expression puts "=> #{expression}" begin # Attempt to split up the expression and go over each statement expression.split.each do |statement| case # When skip is not nil, and the statement is not 'fi' then go # to next statement when !$skip.nil? && statement != 'fi' next # When word is not nil and statement is not ';' then add # the statement to the word array when !$word.nil? && statement != ';' $word << statement # When the statement is a word, call that associated function when $dictionary.has_key?(statement) $dictionary[statement].call # Otherwise push it onto the stack as an integer else push statement.to_i end end rescue # If something goes wrong, print out the error puts "Error: #{$!}" end end # Empty the stack $stack = [] # Setup the initial dictionary $dictionary = { '+' => binary { |a, b| a + b }, '-' => binary { |a, b| a - b }, '*' => binary { |a, b| a * b }, '/' => binary { |a, b| a * b }, '%' => binary { |a, b| a * b }, '<' => binary_boolean { |a, b| a < b }, '>' => binary_boolean { |a, b| a > b }, '=' => binary_boolean { |a, b| a == b }, '&' => binary_boolean { |a, b| a && b }, '|' => binary_boolean { |a, b| a || b }, 'not' => binary_boolean { |a, b| a == 0 }, 'neg' => binary { |a| -a }, '.' => -> { puts pop }, '..' => -> { puts $stack }, ':' => -> { $word = [] }, ';' => -> { new_word }, 'pop' => -> { pop }, 'fi' => -> { $skip = nil }, 'words' => -> { p $dictionary.keys.sort }, 'if' => -> { $skip = true if pop == 0 }, 'dup' => -> { push $stack.last || raise(StackUnderflow) }, 'over' => -> { push $stack.last(2).first || raise(StackUnderflow) }, 'swap' => -> { begin swap rescue raise(StackUnderflow) end } } # Load all files given in the command line puts "Ruby Forth interpreter: enter commands at the prompt" while ARGV.size > 0 open(ARGV.shift).each { |line| parse(line) } end # Here's the REPL while true # Print out the prompt token for the user print "> " # If nothing is given, break out of the loop break unless gets # Parse the given text parse $_ end -
perimosocordiae created this gist
Feb 10, 2010 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,74 @@ #!/usr/bin/env ruby # the stack $stack = [] def pop() $stack.pop || ufe end def push(f) $stack<<f end # poor man's Exception class def ufe() raise("Stack underflow") end # lambda constructor helpers def mkUnary(&fn) lambda{push(fn.call(pop))} end def mkBinary(&fn) lambda{push(fn.call(pop,pop))} end def mkBool1(&b) lambda{push(b.call(pop)?1:0)} end def mkBool2(&b) lambda{push(b.call(pop,pop)?1:0)} end # the dictionary of Forth words (String => Proc) $dict = {'+' =>mkBinary{|a,b|a+b}, '-' =>mkBinary{|a,b|a-b}, '*' =>mkBinary{|a,b|a*b}, '/' =>mkBinary{|a,b|a/b}, '%' =>mkBinary{|a,b|a%b}, '=' =>mkBool2 {|a,b|a==b}, '<' =>mkBool2 {|a,b|a<b}, '>' =>mkBool2 {|a,b|a>b}, '&' =>mkBool2 {|a,b|a&b}, '|' =>mkBool2 {|a,b|a|b}, 'not' =>mkBool1 {|a| a==0}, 'neg' =>mkUnary {|a|-a}, '.' =>lambda {puts pop}, '..' =>lambda {p $stack}, ':' =>lambda {$word=[]}, ';' =>lambda {makeword}, 'pop' =>lambda {pop}, 'fi' =>lambda {$skip=nil}, 'words'=>lambda {p $dict.keys.sort}, 'if' =>lambda {$skip=true if pop==0}, 'dup' =>lambda {push $stack[-1] || ufe}, 'over' =>lambda {push $stack[-2] || ufe}, 'swap' =>lambda {begin swap rescue ufe end}, } def swap $stack[-2,2] = $stack[-2,2].reverse end # adds user-defined word to the dictionary def makeword ($word=nil;raise("Empty word definition")) unless $word && $word.size > 1 ($word=nil;raise("Nested word definition")) if $word.include? ':' name, code = $word.shift, $word.join(' ') $dict[name] = lambda{parse(code)} $word = nil end # meat and potatoes def parse(str) begin str.split.each do |w| if $skip and w != 'fi' next # skipping over conditional elsif $word and w != ';' $word << w # reading word definition elsif $dict.has_key? w $dict[w].call # calling pre-defined word else push w.to_i # pushing int literal end end rescue puts "Error: #{$!}" end end puts "Ruby Forth interpreter: enter commands at the prompt" # read definitions files while ARGV.size > 0 File.open(ARGV.shift).each{|line| parse(line)} end # REPL loop do ">> ".display break unless gets parse($_) end