Skip to content

Commit

Permalink
Add some readme and a bit of output
Browse files Browse the repository at this point in the history
  • Loading branch information
Josep M. Bach committed Jun 17, 2011
1 parent e81b4c9 commit 2466c7d
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
source "http://rubygems.org"

# Specify your gem's dependencies in replx.gemspec
# Specify your gem's dependencies in rexpl.gemspec
gemspec
49 changes: 49 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,2 +1,51 @@
require 'bundler'
Bundler::GemHelper.install_tasks

require 'rake/testtask'
desc "Run Rexpl tests"
Rake::TestTask.new do |t|
t.libs << "test"
t.test_files = FileList['test/**/*_test.rb']
t.verbose = true
end

require 'yard'
YARD::Rake::YardocTask.new(:docs) do |t|
t.files = ['lib/**/*.rb']
t.options = ['-m', 'markdown', '--no-private', '-r', 'Readme.md', '--title', 'Rexpl documentation']
end

site = 'doc'
source_branch = 'master'
deploy_branch = 'gh-pages'

desc "generate and deploy documentation website to github pages"
multitask :pages do
puts ">>> Deploying #{deploy_branch} branch to Github Pages <<<"
require 'git'
repo = Git.open('.')
puts "\n>>> Checking out #{deploy_branch} branch <<<\n"
repo.branch("#{deploy_branch}").checkout
(Dir["*"] - [site]).each { |f| rm_rf(f) }
Dir["#{site}/*"].each {|f| mv(f, "./")}
rm_rf(site)
puts "\n>>> Moving generated site files <<<\n"
Dir["**/*"].each {|f| repo.add(f) }
repo.status.deleted.each {|f, s| repo.remove(f)}
puts "\n>>> Commiting: Site updated at #{Time.now.utc} <<<\n"
message = ENV["MESSAGE"] || "Site updated at #{Time.now.utc}"
repo.commit(message)
puts "\n>>> Pushing generated site to #{deploy_branch} branch <<<\n"
repo.push
puts "\n>>> Github Pages deploy complete <<<\n"
repo.branch("#{source_branch}").checkout
end

task :doc => [:docs]

desc "Generate and open class diagram (needs Graphviz installed)"
task :graph do |t|
`bundle exec yard graph -d --full --no-private | dot -Tpng -o graph.png && open graph.png`
end

task :default => [:test]
42 changes: 42 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# rexpl

**rexpl** is a sandbox to experiment and play with the [Rubinius](http:://rubini.us)
Virtual Machine and its bytecode instructions. It comes wrapped in a REPL
(Read-Eval-Print Loop) à la IRB, so that anytime you can open a terminal,
fire up **rexpl**, and start playing with instant feedback.

Its main feature is **stack introspection**, which means you can inspect
what the stack looks like after each step of your instruction set.

## How to use it?

Needless to say, **rexpl** runs only on Rubinius. Thus, your first step is to
install it. Go to the [rubinius website](http://rubini.us) to find how, or if
you are using RVM, just follow [this instructions](http://beginrescueend.com/interpreters/rbx/).

$ gem install rexpl
$ rexpl

Now you should see a welcome banner and an IRB-like prompt, and you're good to
go! Just start typing some [VM instructions](http://rubini.us/doc/en/virtual-machine/instructions/)
and see what happens!

There are three extra commands to take advantage of the stack introspection:

* `list` lists the instruction set of the current program.
* `reset` empties the instruction set and starts a new program.
* `draw` prints a visual representation of the stack after each instruction of
your program.

## When to use it?

Imagine you are bootstrapping a new language targeting the Rubinius VM and you
just implemented a particular AST node, but when you try to run the tests, you
keep getting nasty stack validation errors. Net stack underflow? What the heck
does this even mean? Where the hell is that extra `pop`? Did this or that
instruction consume stack? Or maybe produce it? Oh fuck it, let's go fishing.

Don't panic. You always have your friends pen and paper ready to help you out,
Read through the source code, and knowing what each instruction does, try to
follow along and draw what the stack looks like at each step (does that sound
familiar to you?). Or just fire up **rexpl**.
2 changes: 2 additions & 0 deletions lib/rexpl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
module Rexpl
end

require 'rexpl/version'
require 'rexpl/generator_proxy'
require 'rexpl/generator_methods'
require 'rexpl/output'
require 'rexpl/environment'
31 changes: 16 additions & 15 deletions lib/rexpl/environment.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
module Rexpl
class Environment
@@generator = Rexpl::GeneratorProxy.new
@@generator = GeneratorProxy.new

def self.run
puts "\nRbx bytecode REPL. Kind of."
puts "---------------------------\n"
puts "\nJust enter generator instructions.\n'reset' to reset, 'list' to list the current program instructions, 'draw' to print.\n"
while (print '> '; input = gets)
@@generator.instance_eval input.chomp
class << self
# Rexpl's main entry point. Starts the REPL.
def run
Output.print_banner
while (Output.print_prompt; input = gets)
@@generator.instance_eval input.chomp

dynamic_method(:run) do |g|
@@generator.visit(g)
if @@generator.instructions.any?
g.show_stack
else
g.push_nil
dynamic_method(:run) do |g|
@@generator.visit(g)
if g.size == 0
g.push_nil
else
g.show_stack
end
g.ret
end
g.ret
new.run
end
new.run
end
end
end
Expand Down
41 changes: 41 additions & 0 deletions lib/rexpl/output.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require 'ansi'

module Rexpl
# Utility module to abstract output-related stuff, like printing banners or
# graphically representing stacks.
class Output
extend ANSI::Code

class << self
# Prints the welcome banner and a bit of instructions on how to use the
# interactive console.
def print_banner
puts
puts bold { red { "rexpl" } } + bold { " v#{Rexpl::VERSION}" } + " - interactive bytecode console for Rubinius"
puts bold { "--------------------------------------------------------" }
puts
print_rationale
end

def print_prompt
print bold { '> ' }
end

private

def print_rationale
puts "To start playing, just start typing some Rubinius VM instructions."
puts "You can find a complete list with documentation here:"
puts
puts "\thttp://rubini.us/doc/en/virtual-machine/instructions/"
puts
puts "To introspect the program you are writing, use the following commands:"
puts
puts " " + bold { "list" } + " lists the instruction set of the current program."
puts " " + bold { "reset" } + " empties the instruction set and starts a new program."
puts " " + bold { "draw" } + " prints a visual representation of the stack after each instruction."
puts
end
end
end
end
5 changes: 5 additions & 0 deletions rexpl.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ Gem::Specification.new do |s|

s.rubyforge_project = "rexpl"

s.add_runtime_dependency "ansi"
s.add_development_dependency "minitest"
s.add_development_dependency 'yard'
s.add_development_dependency 'bluecloth'

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
Expand Down
2 changes: 2 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
gem 'minitest'
require 'minitest/autorun'

0 comments on commit 2466c7d

Please sign in to comment.