cleanup
This commit is contained in:
parent
eba80177ae
commit
b81c8e69b7
1
Gemfile
1
Gemfile
@ -18,6 +18,7 @@ gem 'uglifier', '>= 2.4.0', require: false
|
|||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
# Testing dependencies
|
# Testing dependencies
|
||||||
|
gem "minitest"
|
||||||
gem 'rspec', '~> 3.2.0'
|
gem 'rspec', '~> 3.2.0'
|
||||||
gem 'opal-rspec', '~> 0.4.2'
|
gem 'opal-rspec', '~> 0.4.2'
|
||||||
gem 'capybara', '~> 2.4.2'
|
gem 'capybara', '~> 2.4.2'
|
||||||
|
@ -68,6 +68,7 @@ GEM
|
|||||||
method_source (0.8.2)
|
method_source (0.8.2)
|
||||||
mime-types (2.6.1)
|
mime-types (2.6.1)
|
||||||
mini_portile (0.6.2)
|
mini_portile (0.6.2)
|
||||||
|
minitest (5.7.0)
|
||||||
mongo (1.9.2)
|
mongo (1.9.2)
|
||||||
bson (~> 1.9.2)
|
bson (~> 1.9.2)
|
||||||
multi_json (1.11.2)
|
multi_json (1.11.2)
|
||||||
@ -161,6 +162,7 @@ DEPENDENCIES
|
|||||||
chromedriver2-helper (~> 0.0.8)
|
chromedriver2-helper (~> 0.0.8)
|
||||||
concurrent-ruby-ext (~> 0.8.0)
|
concurrent-ruby-ext (~> 0.8.0)
|
||||||
csso-rails (~> 0.3.4)
|
csso-rails (~> 0.3.4)
|
||||||
|
minitest
|
||||||
opal-rspec (~> 0.4.2)
|
opal-rspec (~> 0.4.2)
|
||||||
parslet!
|
parslet!
|
||||||
poltergeist (~> 1.5.0)
|
poltergeist (~> 1.5.0)
|
||||||
|
21
README.md
21
README.md
@ -1,9 +1,22 @@
|
|||||||
### statement of intent
|
|
||||||
|
|
||||||
just starting and not quite sure, but here is the direction
|
|
||||||
|
|
||||||
# Debugger
|
# Debugger
|
||||||
|
|
||||||
|
After some tryouts it ended up being an Opal application. That is ruby as javascript in the browser.
|
||||||
|
|
||||||
|
![Debugger](https://raw.githubusercontent.com/salama/salama-debugger/master/static/debugger.png)
|
||||||
|
|
||||||
|
- On the left are the classes of the system. Next idea is to have hover info about them.
|
||||||
|
- Next a source code view (not implemented)
|
||||||
|
- next a view of the Virtual Instructions
|
||||||
|
- last section, current block with current Register Instruction highlighted
|
||||||
|
- step (next) button for single stepping
|
||||||
|
- status: starting , running , exited
|
||||||
|
- bottom row are the registers. If the register hold an object the variables are shown.
|
||||||
|
(also should have hover info) , the first letter indicates the class, the number is the address
|
||||||
|
|
||||||
|
So lots to do, but a good start.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
I don't want to use gdb anymore, and it would be easier without using the qemu setup, so:
|
I don't want to use gdb anymore, and it would be easier without using the qemu setup, so:
|
||||||
|
|
||||||
- single step debugging of the register machine level (as close to arm as need be)
|
- single step debugging of the register machine level (as close to arm as need be)
|
||||||
|
16
app/main.rb
16
app/main.rb
@ -1,16 +0,0 @@
|
|||||||
require 'opal'
|
|
||||||
require "opal/parser"
|
|
||||||
|
|
||||||
require "salama"
|
|
||||||
require "interpreter"
|
|
||||||
|
|
||||||
require 'opal-react'
|
|
||||||
|
|
||||||
require "debugger"
|
|
||||||
|
|
||||||
require 'opal-jquery'
|
|
||||||
|
|
||||||
Document.ready? do # Document.ready? is a opal-jquery method.
|
|
||||||
machine = Virtual.machine.boot
|
|
||||||
React.render( React.create_element( Debugger , :machine => machine ), Element['#content'] )
|
|
||||||
end
|
|
@ -1,7 +0,0 @@
|
|||||||
<:Title>
|
|
||||||
About
|
|
||||||
|
|
||||||
<:Body>
|
|
||||||
<h1>About</h1>
|
|
||||||
|
|
||||||
<p>About page...</p>
|
|
@ -1,40 +0,0 @@
|
|||||||
@import "susy" ;
|
|
||||||
|
|
||||||
$susy: (
|
|
||||||
columns: 24 ,
|
|
||||||
gutter-position: split ,
|
|
||||||
);
|
|
||||||
|
|
||||||
.debugger-view { @include container(90%); }
|
|
||||||
|
|
||||||
.classes { @include span(3); }
|
|
||||||
|
|
||||||
.file-view {
|
|
||||||
@include span(4);
|
|
||||||
margin: span(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.source-view { @include span(6); }
|
|
||||||
|
|
||||||
.block-view {
|
|
||||||
@include span(4);
|
|
||||||
margin-right: span(3);
|
|
||||||
height: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-view {
|
|
||||||
@include span(2 at 22);
|
|
||||||
}
|
|
||||||
|
|
||||||
.registers-view {
|
|
||||||
@include span(20 at 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.register-view {
|
|
||||||
@include gallery(3);
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bright {
|
|
||||||
background-color: orange ;
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 237 B |
@ -1,69 +0,0 @@
|
|||||||
|
|
||||||
require "opal/parser" # to get eval to work
|
|
||||||
|
|
||||||
$LOAD_PATH.unshift("/Users/raisa/salama/salama-debugger/app/main/lib")
|
|
||||||
|
|
||||||
require "salama"
|
|
||||||
|
|
||||||
Virtual::Machine.boot
|
|
||||||
|
|
||||||
module Main
|
|
||||||
class MainController < Volt::ModelController
|
|
||||||
|
|
||||||
def index
|
|
||||||
page._registers!.clear
|
|
||||||
page._classes!.clear
|
|
||||||
page._objects!.clear
|
|
||||||
page._source = InstructionModel.new nil
|
|
||||||
page._block = BlockModel.new nil
|
|
||||||
fill_regs
|
|
||||||
parse_and_fill
|
|
||||||
end
|
|
||||||
|
|
||||||
def about
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def parse_and_fill
|
|
||||||
ParseTask.parse(1).then do |result|
|
|
||||||
is = Ast::Expression.from_basic(result)
|
|
||||||
Virtual::Compiler.compile( is , Virtual.machine.space.get_main )
|
|
||||||
Virtual.machine.run_before "Register::CallImplementation"
|
|
||||||
fill_classes
|
|
||||||
end.fail do |error|
|
|
||||||
raise "Error: #{error}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
def fill_classes
|
|
||||||
Virtual.machine.space.classes.each do |name , claz|
|
|
||||||
next if [:Kernel,:Module,:MetaClass,:BinaryCode].index name
|
|
||||||
c = Volt::Model.new :name => name
|
|
||||||
page._classes << c
|
|
||||||
end
|
|
||||||
b = Virtual.machine.init
|
|
||||||
page._block = BlockModel.new b
|
|
||||||
page._source = InstructionModel.new b.codes.first.source
|
|
||||||
end
|
|
||||||
def fill_regs
|
|
||||||
register_names = (0..8).collect {|i| "r#{i}"}
|
|
||||||
register_names.each do |reg_name|
|
|
||||||
reg = Volt::Model.new :name => reg_name
|
|
||||||
page._registers << reg
|
|
||||||
end
|
|
||||||
end
|
|
||||||
# The main template contains a #template binding that shows another
|
|
||||||
# template. This is the path to that template. It may change based
|
|
||||||
# on the params._component, params._controller, and params._action values.
|
|
||||||
def main_path
|
|
||||||
"#{params._component || 'main'}/#{params._controller || 'main'}/#{params._action || 'index'}"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Determine if the current nav component is the active one by looking
|
|
||||||
# at the first part of the url against the href attribute.
|
|
||||||
def active_tab?
|
|
||||||
url.path.split('/')[1] == attrs.href.split('/')[1]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,12 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Salama Debugger</title>
|
|
||||||
<link rel="stylesheet" href="/assets/styles.css">
|
|
||||||
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
|
|
||||||
<script src="/assets/react-with-addons.js"></script>
|
|
||||||
<%= javascript_include_tag 'main' %>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="content"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,29 +0,0 @@
|
|||||||
|
|
||||||
class ObjectView
|
|
||||||
|
|
||||||
attr_accessor :text , :object , :attributes
|
|
||||||
|
|
||||||
def initialize o
|
|
||||||
super()
|
|
||||||
puts "NO O " unless o
|
|
||||||
self.object = o
|
|
||||||
self.text = short
|
|
||||||
@attributes = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
def short
|
|
||||||
object.class.name.split("::").last[0 .. 3]
|
|
||||||
end
|
|
||||||
|
|
||||||
def is_parfait
|
|
||||||
object.class.name.split("::").first == "Parfait"
|
|
||||||
end
|
|
||||||
def set name , val
|
|
||||||
@attributes[name] = val
|
|
||||||
self.text.text = short + @attributes.length.to_s
|
|
||||||
end
|
|
||||||
def get(name)
|
|
||||||
@attributes[name]
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,99 +0,0 @@
|
|||||||
|
|
||||||
class SpaceView
|
|
||||||
include Sof::Util
|
|
||||||
|
|
||||||
def initialize max
|
|
||||||
super()
|
|
||||||
|
|
||||||
space = Virtual.machine.space
|
|
||||||
# just a way to get the space into a list. objects is an id => occurence mapping.
|
|
||||||
# occurence.object is the object
|
|
||||||
objects = Sof::Members.new(space).objects
|
|
||||||
@objects = objects
|
|
||||||
puts "Objects #{objects.length}"
|
|
||||||
# create a mapping from id to volt models
|
|
||||||
@view_objects = {}
|
|
||||||
|
|
||||||
@objects.each do |i , o|
|
|
||||||
ob = o.object
|
|
||||||
next unless ob
|
|
||||||
next if basic?(ob)
|
|
||||||
next if ob.class.name.include? "Binary"
|
|
||||||
next if ob.class.name.include? "Array"
|
|
||||||
puts "object #{ob.class.name}"
|
|
||||||
|
|
||||||
view = ObjectView.new ob
|
|
||||||
@view_objects[i] = view
|
|
||||||
add_child view.text
|
|
||||||
end
|
|
||||||
fill_attributes
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def fill_attributes
|
|
||||||
@view_objects.each do |i , view|
|
|
||||||
ob = view.object
|
|
||||||
next if is_value?(ob)
|
|
||||||
case ob.class.name
|
|
||||||
when "Array" , "Parfait::List"
|
|
||||||
fill_array view
|
|
||||||
when "Hash" , "Parfait::Dictionary"
|
|
||||||
fill_hash view
|
|
||||||
else
|
|
||||||
# next if basic?(ob)
|
|
||||||
|
|
||||||
attributes = attributes_for(ob)
|
|
||||||
attributes.each do |a|
|
|
||||||
next if a == "html_safe"
|
|
||||||
next if a == "constructor"
|
|
||||||
next if a == "toString"
|
|
||||||
next if a == "position"
|
|
||||||
val = get_value( ob , a)
|
|
||||||
if( @view_objects[val.object_id])
|
|
||||||
val = @view_objects[val.object_id]
|
|
||||||
end
|
|
||||||
#puts "set #{a}"
|
|
||||||
view.set(a , val )
|
|
||||||
end
|
|
||||||
superclasses = [ob.class.superclass.name]
|
|
||||||
if superclasses.include?( "Array") or superclasses.include?( "Parfait::List")
|
|
||||||
fill_array view
|
|
||||||
end
|
|
||||||
if superclasses.include?( "Hash") or superclasses.include?( "Parfait::Dictionary")
|
|
||||||
fill_hash view
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def basic? ob
|
|
||||||
return true if ob.class.name.include?("::") and !ob.class.name.include?("Parfait")
|
|
||||||
return true if ob.class.name == "Proc"
|
|
||||||
return true if ob.class.name == "String"
|
|
||||||
return true if ob.class.name == "Numeric"
|
|
||||||
return true if ob.class.name == "Class"
|
|
||||||
false
|
|
||||||
end
|
|
||||||
# and hash keys/values
|
|
||||||
def fill_hash view_hash
|
|
||||||
view_hash.object.each do |k , val|
|
|
||||||
if( @view_objects[val.object_id])
|
|
||||||
val = @view_objects[val.object_id]
|
|
||||||
end
|
|
||||||
view_hash.set(k , val )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
# and array values
|
|
||||||
def fill_array view_array
|
|
||||||
index = 0
|
|
||||||
view_array.object.each do |val|
|
|
||||||
if( @view_objects[val.object_id])
|
|
||||||
val = @view_objects[val.object_id]
|
|
||||||
end
|
|
||||||
view_array.set("#{index}" , val )
|
|
||||||
index += 1
|
|
||||||
end
|
|
||||||
#puts "set #{a}"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,13 +0,0 @@
|
|||||||
|
|
||||||
# represent an instruction and hold the actual instance (as transient)
|
|
||||||
|
|
||||||
class InstructionModel < Volt::Model
|
|
||||||
field :name
|
|
||||||
attr_accessor :instruction
|
|
||||||
|
|
||||||
def initialize(i)
|
|
||||||
super()
|
|
||||||
@instruction = i
|
|
||||||
self.name = i.class.name
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,7 +1,8 @@
|
|||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
require 'bundler'
|
require 'bundler'
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Bundler.setup(:default, :development)
|
Bundler.setup(:default, :test)
|
||||||
rescue Bundler::BundlerError => e
|
rescue Bundler::BundlerError => e
|
||||||
$stderr.puts e.message
|
$stderr.puts e.message
|
||||||
$stderr.puts "Run `bundle install` to install missing gems"
|
$stderr.puts "Run `bundle install` to install missing gems"
|
||||||
@ -14,7 +15,7 @@ end
|
|||||||
|
|
||||||
require "minitest/autorun"
|
require "minitest/autorun"
|
||||||
|
|
||||||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', "app" , "main",'lib'))
|
||||||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
|
||||||
|
|
||||||
require "salama"
|
require "salama"
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
<:Title>
|
|
||||||
About
|
|
||||||
|
|
||||||
<:Body>
|
|
||||||
<h1>About</h1>
|
|
||||||
|
|
||||||
<p>About page...</p>
|
|
@ -1,43 +0,0 @@
|
|||||||
<:Title>
|
|
||||||
Debugger
|
|
||||||
|
|
||||||
<:Body>
|
|
||||||
<div class="row">
|
|
||||||
{{ page._classes.each do |c| }}
|
|
||||||
<div class="col-md-1">
|
|
||||||
{{ c._name }} <br/>
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3">
|
|
||||||
Messages
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
Source Code
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="row">
|
|
||||||
Virtual Machine Instruction : {{ page._source._name}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="row">
|
|
||||||
Current block: {{ page._block._name}}
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
{{ if page._block.block }}
|
|
||||||
{{ page._block.block.codes.each do |c| }}
|
|
||||||
{{ c.to_s }}
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
{{ page._registers.each do |r| }}
|
|
||||||
<div class="col-md-1">
|
|
||||||
{{ r._name }} : {{ r._content }}
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
@ -1,27 +0,0 @@
|
|||||||
<:Title>
|
|
||||||
{{ view main_path, "title", {controller_group: 'main'} }}
|
|
||||||
|
|
||||||
<:Body>
|
|
||||||
<div class="container">
|
|
||||||
<div class="header">
|
|
||||||
<ul class="nav nav-pills pull-right">
|
|
||||||
<:nav href="/">Home</:nav>
|
|
||||||
<:nav href="/about">About</:nav>
|
|
||||||
</ul>
|
|
||||||
<h3 class="text-muted">Salama Debugger</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<:volt:notices />
|
|
||||||
|
|
||||||
{{ view main_path, 'body', {controller_group: 'main'} }}
|
|
||||||
|
|
||||||
<div class="footer">
|
|
||||||
<p> <a href="http://salama-vm.org/" >Salama</a> {{ Time.now.year }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<:Nav>
|
|
||||||
<li class="{{ if active_tab? }}active{{ end }}">
|
|
||||||
<a href="{{ attrs.href }}">{{ yield }}</a>
|
|
||||||
</li>
|
|
@ -1,49 +0,0 @@
|
|||||||
|
|
||||||
require "instruction_view"
|
|
||||||
|
|
||||||
class BlockView
|
|
||||||
|
|
||||||
include React::Component
|
|
||||||
required_param :interpreter
|
|
||||||
|
|
||||||
define_state :block => []
|
|
||||||
define_state :block_name => ""
|
|
||||||
|
|
||||||
before_mount do
|
|
||||||
interpreter.register_event(:instruction_changed, self)
|
|
||||||
update_block
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_block
|
|
||||||
return unless interpreter.instruction
|
|
||||||
block_name! interpreter.block.name
|
|
||||||
codes = interpreter.block.codes.dup
|
|
||||||
slice = codes.index(interpreter.instruction) #- 1
|
|
||||||
codes.shift( slice ) if slice >= 0
|
|
||||||
codes.pop while(codes.length > 4)
|
|
||||||
block! codes
|
|
||||||
end
|
|
||||||
|
|
||||||
def instruction_changed
|
|
||||||
update_block
|
|
||||||
end
|
|
||||||
|
|
||||||
def render
|
|
||||||
return unless block
|
|
||||||
div.block_view do
|
|
||||||
div do
|
|
||||||
h4 { method_name}
|
|
||||||
h4 {"Block: #{block_name}"}
|
|
||||||
end
|
|
||||||
block.each do |code|
|
|
||||||
InstructionView :interpreter => interpreter , :instruction => code
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def method_name
|
|
||||||
bl = interpreter.block
|
|
||||||
return bl.method if bl.method.is_a? String
|
|
||||||
"#{bl.method.for_class.name}.#{bl.method.name}"
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,16 +0,0 @@
|
|||||||
class ClassView
|
|
||||||
include React::Component
|
|
||||||
|
|
||||||
required_param :classes, type: {}
|
|
||||||
|
|
||||||
def render
|
|
||||||
div.classes do
|
|
||||||
h4 { "Classes" }
|
|
||||||
classes.each do |name , clas|
|
|
||||||
div.one_class do
|
|
||||||
clas.name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,37 +0,0 @@
|
|||||||
|
|
||||||
require "register_view"
|
|
||||||
require "class_view"
|
|
||||||
require "source_view"
|
|
||||||
require "block_view"
|
|
||||||
require "status_view"
|
|
||||||
|
|
||||||
class Debugger
|
|
||||||
|
|
||||||
include React::Component
|
|
||||||
required_param :machine , :type => Virtual::Machine
|
|
||||||
define_state :interpreter => Interpreter.new
|
|
||||||
|
|
||||||
before_mount do
|
|
||||||
code = Ast::ExpressionList.new( [Ast::CallSiteExpression.new(:putstring, [] ,Ast::StringExpression.new("Hello again"))])
|
|
||||||
Virtual::Compiler.compile( code , machine.space.get_main )
|
|
||||||
machine.run_before "Register::CallImplementation"
|
|
||||||
interpreter.start machine.init
|
|
||||||
end
|
|
||||||
def render
|
|
||||||
div.debugger_view do
|
|
||||||
ClassView classes: machine.space.classes
|
|
||||||
div.file_view do
|
|
||||||
"Future Source code view"
|
|
||||||
end
|
|
||||||
SourceView :interpreter => interpreter
|
|
||||||
BlockView :interpreter => interpreter
|
|
||||||
StatusView :interpreter => interpreter
|
|
||||||
div.registers_view do
|
|
||||||
interpreter.registers.each do |r , oid|
|
|
||||||
RegisterView interpreter: interpreter , register: r
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,28 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
class InstructionView
|
|
||||||
|
|
||||||
include React::Component
|
|
||||||
required_param :interpreter
|
|
||||||
required_param :instruction
|
|
||||||
|
|
||||||
define_state :active => ""
|
|
||||||
|
|
||||||
before_mount do
|
|
||||||
check_active interpreter.instruction
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_active i
|
|
||||||
active! instruction == i ? "bright" : ""
|
|
||||||
|
|
||||||
end
|
|
||||||
def instruction_changed old , ins
|
|
||||||
check_active ins
|
|
||||||
end
|
|
||||||
|
|
||||||
def render
|
|
||||||
div :class => active do
|
|
||||||
instruction.to_s if instruction
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
16
volt/main.rb
16
volt/main.rb
@ -1,16 +0,0 @@
|
|||||||
require 'opal'
|
|
||||||
require "opal/parser"
|
|
||||||
|
|
||||||
require "salama"
|
|
||||||
require "interpreter"
|
|
||||||
|
|
||||||
require 'opal-react'
|
|
||||||
|
|
||||||
require "debugger"
|
|
||||||
|
|
||||||
require 'opal-jquery'
|
|
||||||
|
|
||||||
Document.ready? do # Document.ready? is a opal-jquery method.
|
|
||||||
machine = Virtual.machine.boot
|
|
||||||
React.render( React.create_element( Debugger , :machine => machine ), Element['#content'] )
|
|
||||||
end
|
|
@ -1,64 +0,0 @@
|
|||||||
|
|
||||||
class RegisterView
|
|
||||||
|
|
||||||
include React::Component
|
|
||||||
required_param :interpreter
|
|
||||||
required_param :register
|
|
||||||
|
|
||||||
define_state :objects_id
|
|
||||||
define_state :fields => []
|
|
||||||
|
|
||||||
before_mount do
|
|
||||||
interpreter.register_event(:register_changed, self)
|
|
||||||
interpreter.register_event(:object_changed, self)
|
|
||||||
register_changed( register , nil , interpreter.registers[register])
|
|
||||||
end
|
|
||||||
|
|
||||||
def register_changed reg , old , value
|
|
||||||
reg = reg.symbol unless reg.is_a? Symbol
|
|
||||||
return unless reg == register
|
|
||||||
objects_id! value
|
|
||||||
calc_fields
|
|
||||||
end
|
|
||||||
|
|
||||||
def object_changed reg
|
|
||||||
reg = reg.symbol unless reg.is_a? Symbol
|
|
||||||
return unless reg == register
|
|
||||||
#puts "Object changed in #{reg}"
|
|
||||||
calc_fields
|
|
||||||
end
|
|
||||||
|
|
||||||
def calc_fields
|
|
||||||
#puts "My id #{objects_id} , #{objects_id.class}"
|
|
||||||
object = Virtual.machine.objects[objects_id]
|
|
||||||
if object and ! object.is_a?(String)
|
|
||||||
has_fields = []
|
|
||||||
clazz = object.class.name.split("::").last
|
|
||||||
#puts "found #{clazz}"
|
|
||||||
has_fields << clazz
|
|
||||||
object.get_instance_variables.each do |variable|
|
|
||||||
f = object.get_instance_variable(variable)
|
|
||||||
has_fields << f
|
|
||||||
end
|
|
||||||
fields! has_fields
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def render
|
|
||||||
div.register_view do
|
|
||||||
div do
|
|
||||||
objects_id.to_s
|
|
||||||
end
|
|
||||||
fields.each do |attribute|
|
|
||||||
div.col_md_12 do
|
|
||||||
"#{marker(attribute)} - #{attribute.object_id}".span
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def marker var
|
|
||||||
return "W" if var.is_a? String
|
|
||||||
var.class.name.split("::").last[0]
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,38 +0,0 @@
|
|||||||
class SourceView
|
|
||||||
|
|
||||||
include React::Component
|
|
||||||
|
|
||||||
required_param :interpreter
|
|
||||||
|
|
||||||
define_state :sources => []
|
|
||||||
|
|
||||||
before_mount do
|
|
||||||
interpreter.register_event(:instruction_changed, self)
|
|
||||||
instruction_changed nil , interpreter.instruction
|
|
||||||
end
|
|
||||||
|
|
||||||
def instruction_changed old , ins
|
|
||||||
text = ins ? source_text(ins.source) : "exit"
|
|
||||||
return if sources.last == text
|
|
||||||
sources << text
|
|
||||||
sources.shift if sources.length > 5
|
|
||||||
sources! sources
|
|
||||||
end
|
|
||||||
|
|
||||||
def render
|
|
||||||
div.source_view do
|
|
||||||
h4 {"Virtual Machine Instruction"}
|
|
||||||
sources.each do |s|
|
|
||||||
s.br
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def source_text source
|
|
||||||
if source.is_a? Virtual::Instruction
|
|
||||||
return source.class.name
|
|
||||||
else
|
|
||||||
return "Method: #{source.name}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,41 +0,0 @@
|
|||||||
|
|
||||||
class StatusView
|
|
||||||
|
|
||||||
include React::Component
|
|
||||||
required_param :interpreter
|
|
||||||
|
|
||||||
define_state :state => "starting"
|
|
||||||
define_state :stdout
|
|
||||||
|
|
||||||
before_mount do
|
|
||||||
interpreter.register_event(:instruction_changed, self)
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_state
|
|
||||||
state! interpreter.state
|
|
||||||
stdout! interpreter.stdout
|
|
||||||
end
|
|
||||||
|
|
||||||
def instruction_changed old , nex
|
|
||||||
update_state
|
|
||||||
end
|
|
||||||
|
|
||||||
def render
|
|
||||||
div.status_view do
|
|
||||||
div do
|
|
||||||
button.bright { "next" }.on(:click) { interpreter.tick }
|
|
||||||
" ".br
|
|
||||||
end
|
|
||||||
div do
|
|
||||||
h4 {"Status:"}
|
|
||||||
state.to_s.br
|
|
||||||
end
|
|
||||||
div do
|
|
||||||
h4 {"Stdout:"}
|
|
||||||
end
|
|
||||||
div do
|
|
||||||
interpreter.stdout.br
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in New Issue
Block a user