yanked diy branch to master

This commit is contained in:
Torsten Ruger 2015-08-25 12:37:29 +02:00
commit 3ca4f29ed1
28 changed files with 750 additions and 413 deletions

36
Gemfile
View File

@ -1,23 +1,17 @@
source 'https://rubygems.org'
gem 'volt', '0.9.5.pre4'
gem "opal" , :github => "opal/opal"
gem 'opal-browser'
# volt uses mongo as the default data store.
gem 'volt-mongo', '~> 0.1.0'
#gem "salama" , "0.2" , :path => "../salama"
gem "parslet" , git: "https://github.com/salama/parslet.git"
#gem "salama" , git: "https://github.com/salama/salama.git"
gem "salama" , path: "../salama"
gem "salama-reader" , git: "https://github.com/salama/salama-reader.git"
gem "salama-arm" , git: "https://github.com/salama/salama-arm.git"
gem "salama-object-file" , git: "https://github.com/salama/salama-object-file.git"
gem "susy" , "2.2.5"
# Asset compilation gems, they will be required when needed.
gem 'csso-rails', '~> 0.3.4', require: false
gem 'uglifier', '>= 2.4.0', require: false
#gem "foundation" , :github => "zurb/foundation"
gem "parslet" , github: "salama/parslet"
gem "salama" , github: "salama/salama"
gem "salama-reader" , github: "salama/salama-reader"
gem "salama-arm" , github: "salama/salama-arm"
gem "salama-object-file" , github: "salama/salama-object-file"
gem "sass"
gem "susy"
group :test do
# Testing dependencies
@ -29,13 +23,3 @@ group :test do
gem 'chromedriver2-helper', '~> 0.0.8'
gem 'poltergeist', '~> 1.5.0'
end
# Server for MRI
platform :mri, :mingw do
# The implementation of ReadWriteLock in Volt uses concurrent ruby and ext helps performance.
gem 'concurrent-ruby-ext', '~> 0.8.0'
# Thin is the default volt server, Puma is also supported
gem 'thin', '~> 1.6.0'
gem 'bson_ext', '~> 1.9.0'
end

View File

@ -1,30 +1,41 @@
GIT
remote: https://github.com/salama/parslet.git
revision: beeb9b441a9ade1504f7f0e848d805e36a02c544
remote: git://github.com/opal/opal.git
revision: c604685071f8560d3357044683a99b80b210a99b
specs:
opal (0.9.0.dev)
hike (~> 1.2)
sourcemap (~> 0.1.0)
sprockets (~> 3.1)
tilt (>= 1.4)
GIT
remote: git://github.com/salama/parslet.git
revision: b8bf8db20a242eb6bd8fec88027e3b2ae19276e8
specs:
parslet (1.7.0)
GIT
remote: https://github.com/salama/salama-arm.git
remote: git://github.com/salama/salama-arm.git
revision: 0bd5091e3f284ecf040e0086a41d2449cd5afb7a
specs:
salama-arm (0.0.1)
GIT
remote: https://github.com/salama/salama-object-file.git
remote: git://github.com/salama/salama-object-file.git
revision: fbae6a02764dbe97e01e4833f9ffffe09879b100
specs:
salama-object-file (0.2.0)
GIT
remote: https://github.com/salama/salama-reader.git
remote: git://github.com/salama/salama-reader.git
revision: 841592c667acea1e796f950851262e6938b231bc
specs:
salama-reader (0.2.0)
parslet (~> 1.7.0)
PATH
remote: ../salama
GIT
remote: git://github.com/salama/salama.git
revision: df95b8b54de103523743cbfd5c46d87af84c6b09
specs:
salama (0.2.0)
salama-object-file (~> 0.2)
@ -33,10 +44,6 @@ PATH
GEM
remote: https://rubygems.org/
specs:
bcrypt (3.1.10)
bson (1.9.2)
bson_ext (1.9.2)
bson (~> 1.9.2)
capybara (2.4.4)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
@ -48,59 +55,28 @@ GEM
chromedriver2-helper (0.0.8)
nokogiri
cliver (0.3.2)
coderay (1.1.0)
concurrent-ruby (0.8.0)
ref (~> 1.0, >= 1.0.5)
concurrent-ruby-ext (0.8.0)
concurrent-ruby (~> 0.8.0)
configurations (2.0.0)
csso-rails (0.3.4)
execjs (>= 1)
daemons (1.2.3)
diff-lcs (1.2.5)
eventmachine (1.0.8)
execjs (2.5.2)
faye-websocket (0.10.0)
eventmachine (>= 0.12.0)
websocket-driver (>= 0.5.1)
ffi (1.9.10)
hike (1.2.3)
json (1.8.3)
listen (3.0.3)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
method_source (0.8.2)
mime-types (2.6.1)
mini_portile (0.6.2)
minitest (5.8.0)
mongo (1.9.2)
bson (~> 1.9.2)
multi_json (1.11.2)
nokogiri (1.6.6.2)
mini_portile (~> 0.6.0)
opal (0.8.0)
hike (~> 1.2)
sourcemap (~> 0.1.0)
sprockets (~> 3.1)
tilt (>= 1.4)
opal-browser (0.2.0)
opal
paggio
opal-rspec (0.4.3)
opal (>= 0.7.0, < 0.9)
paggio (0.2.4)
poltergeist (1.5.1)
capybara (~> 2.1)
cliver (~> 0.3.1)
multi_json (~> 1.0)
websocket-driver (>= 0.2.0)
pry (0.10.1)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
rack (1.5.5)
rack (1.6.4)
rack-test (0.6.3)
rack (>= 1.0)
rb-fsevent (0.9.5)
rb-inotify (0.9.5)
ffi (>= 0.5.0)
ref (1.0.5)
rspec (3.2.0)
rspec-core (~> 3.2.0)
rspec-expectations (~> 3.2.0)
@ -121,37 +97,14 @@ GEM
multi_json (~> 1.0)
rubyzip (~> 1.0)
websocket (~> 1.0)
slop (3.6.0)
sourcemap (0.1.1)
sprockets (3.2.0)
sprockets (3.3.2)
rack (~> 1.0)
susy (2.2.5)
sass (>= 3.3.0, < 3.5)
thin (1.6.3)
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0)
rack (~> 1.0)
thor (0.19.1)
tilt (2.0.1)
uglifier (2.7.1)
execjs (>= 0.3.0)
json (>= 1.8.0)
volt (0.9.5.pre4)
bcrypt (~> 3.1.9)
bundler (>= 1.5)
concurrent-ruby (= 0.8.0)
configurations (~> 2.0.0.pre)
faye-websocket (~> 0.10.0)
listen (~> 3.0.1)
opal (~> 0.8.0)
pry (~> 0.10.1)
rack (~> 1.5.0)
sass (~> 3.4.15)
thor (~> 0.19.0)
volt-mongo (0.1.1)
mongo (~> 1.9.0)
websocket (1.2.2)
websocket-driver (0.6.2)
websocket-driver (0.5.4)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
xpath (2.0.0)
@ -161,12 +114,10 @@ PLATFORMS
ruby
DEPENDENCIES
bson_ext (~> 1.9.0)
capybara (~> 2.4.2)
chromedriver2-helper (~> 0.0.8)
concurrent-ruby-ext (~> 0.8.0)
csso-rails (~> 0.3.4)
minitest
opal!
opal-browser
opal-rspec (~> 0.4.2)
parslet!
poltergeist (~> 1.5.0)
@ -175,12 +126,9 @@ DEPENDENCIES
salama-arm!
salama-object-file!
salama-reader!
sass
selenium-webdriver (~> 2.43.0)
susy (= 2.2.5)
thin (~> 1.6.0)
uglifier (>= 2.4.0)
volt (= 0.9.5.pre4)
volt-mongo (~> 0.1.0)
susy
BUNDLED WITH
1.10.5

View File

@ -1,59 +0,0 @@
// Place your apps css here
@import "susy";
$susy: (
columns: 24 ,
gutter-position: split ,
);
.debugger-view { @include container(90%); }
.classes {
@include span(3);
}
.one-class {
margin: 10px;
}
.file-view {
@include span(4);
margin: span(1);
}
.source-view { @include span(6); }
.block-view {
@include span(4);
margin-right: span(2);
height: 200px;
}
.status-view {
@include span(2 at 22);
}
.registers-view {
@include span(20 at 3);
}
.register-view {
@include gallery(4);
margin-top: 10px;
}
.field {
@include span(5)
}
.value {
@include span(18)
}
.value-head {
background-color: #C5FFD9;
}
.bright {
background-color: orange ;
}

View File

@ -1,2 +0,0 @@
# Specify which components you wish to include when
# the "home" component loads.

View File

@ -1,10 +0,0 @@
# Place any code you want to run when the component is included on the client
# or server.
# To include code only on the client use:
# if RUBY_PLATFORM == 'opal'
#
# To include code only on the server, use:
# unless RUBY_PLATFORM == 'opal'
# ^^ this will not send compile in code in the conditional to the client.
# ^^ this include code required in the conditional.

View File

@ -1,8 +0,0 @@
# See https://github.com/voltrb/volt#routes for more info on routes
client '/about', action: 'about'
# The main route, this should be last. It will match any params not
# previously matched.
client '/', {}

View File

@ -1,43 +0,0 @@
# By default Volt generates this controller for your Main component
require "salama"
require "interpreter/interpreter"
module Main
class MainController < Volt::ModelController
def initialize *args
super(*args)
@volt_app.class.attr_accessor :interpreter
@volt_app.interpreter = Interpreter::Interpreter.new
end
def index
init_machine
end
private
def init_machine
machine = Virtual.machine.boot
code = Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(2),Ast::IntegerExpression.new(5))
Virtual::Compiler.compile( code , machine.space.get_main )
machine.run_before "Register::CallImplementation"
page._interpreter = { }
@volt_app.interpreter.start machine.init
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

View File

@ -1,16 +0,0 @@
<:Title>
Home
<:Body>
<:classes />
<div class="file-view">
</div>
<:sources />
<:blocks />
<:status/>
<:registers/>

View File

@ -1,12 +0,0 @@
<:Title>
{{ view main_path, "title", {controller_group: 'main'} }}
<:Body>
<div class="debugger_view">
<:volt:notices />
{{ view main_path, 'body', {controller_group: 'main'} }}
</div>

71
assets/css/app.css.scss Normal file
View File

@ -0,0 +1,71 @@
// Place your apps css here
@import "susy";
$susy: (
columns: 24 ,
gutter-position: split ,
);
.debugger_view { @include container(90%); }
.classes {
@include span(3);
}
.one_class {
margin: 10px;
}
.file_view {
@include span(4);
margin-left: span(1);
}
.source_view { @include span(6); }
.block_view {
@include span(4);
margin-right: span(2);
height: 200px;
}
.status_view {
@include span(2 at 22);
line-height : 1.25em;
}
.registers_view {
@include span(20 at 3);
}
.register_view {
@include gallery(4);
margin-top: 10px;
}
.field {
@include span(5)
}
.value {
@include span(18)
}
.value_head {
background-color: #C5FFD9;
}
.act{
background-color: #00B3FF;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
font-size: 100%;
}
.bright {
padding-right: 6px;
padding-left: 6px;
background-color: #00E3FF ;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
}

60
assets/css/menu.css.scss Normal file
View File

@ -0,0 +1,60 @@
body {
font-family: arial, helvetica, serif;
}
#nav, #nav ul { /* all lists */
padding: 0;
margin: 0;
list-style: none;
float : left;
width : 10em;
/*border around submenu goes here*/
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
background:#fff;
border:1px solid #C3D46A
}
#nav li { /* all list items */
position : relative;
float : left;
line-height : 1.25em;
width: 9em;
}
#nav li ul { /* second-level lists */
position : absolute;
left: -999em;
margin-left : 10.0em;
margin-top : -2.7em;
}
#nav li ul ul { /* third-and-above-level lists */
left: -999em;
}
#nav li a , li span {
padding-left: 0.5em;
width : 9.5em;
display : block;
color : black;
font-weight : bold;
text-decoration : none;
background-color : white;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
}
#nav li a:hover {
color : white;
background-color : #98CC1F;
}
#nav li:hover ul ul, #nav li:hover ul ul ul , #nav li:hover ul ul ul ul , #nav li:hover ul ul ul ul ul{
left: -999em;
}
/* lists nested under hovered list items */
#nav li:hover ul, #nav li li:hover ul, #nav li li li:hover ul, #nav li li li li:hover ul , #nav li li li li li:hover ul {
left: auto;
}

View File

@ -1,4 +1,31 @@
# Run via rack server
require 'bundler/setup'
require 'volt/server'
run Volt::Server.new.app
require 'bundler'
Bundler.require
require 'tilt/erb'
require_relative "lib/parse_task"
require "opal"
require 'opal-browser'
Opal.use_gem("salama")
Opal.use_gem("salama-arm")
class DebugServer < Opal::Server
def call(env)
if( env["REQUEST_PATH"] == "/tasks.json")
[200, { 'Content-Type' => 'text/json' }, [ParseTask.new.parse(1).to_json]]
else
super(env)
end
end
end
run DebugServer.new { |s|
s.main = 'debugger'
s.append_path 'lib'
s.append_path 'assets'
# s.source_map = true
s.debug = !ENV["DEBUG"].nil?
s.index_path = "index.html.erb"
s.sprockets.cache = Sprockets::Cache::MemoryStore.new(5000)
}

View File

@ -1,136 +0,0 @@
# app.rb is used to configure your app. This code is only run on the server,
# then any config options in config.public are passed to the client as well.
#hint_path = Bundler.definition.specs["simptip"].first.full_gem_path
#ENV["SASS_PATH"] = ENV["SASS_PATH"] + File::PATH_SEPARATOR + hint_path
Volt.configure do |config|
# Setup your global app config here.
#######################################
# Basic App Info (stuff you should set)
#######################################
config.domain = 'salama-debugger.com'
config.app_name = 'Salama-debugger'
config.mailer.from = 'Salama-debugger <no-reply@salama-debugger.com>'
############
# App Secret
############
# Your app secret is used for signing things like the user cookie so it can't
# be tampered with. A random value is generated on new projects that will work
# without the need to customize. Make sure this value doesn't leave your server.
#
# For added security we recommend moving the app secret into an environment. You can
# setup that like so:
#
# config.app_secret = ENV['APP_SECRET']
#
config.app_secret = 'qwSEmWdixdHgwOgXiLdGJt87b9TxMq009gbJWn0fOTygfIk6fAIlgHO9tAPbA4vaKgY'
###############
# Log Filtering
###############
# Data updates from the client come in via Tasks. The task dispatcher logs all calls to tasks.
# By default hashes in the arguments can be filtered based on keys. So any hash with a key of
# password will be filtered. You can add more fields to filter below:
config.filter_keys = [:password]
##########
# Database
##########
# Database config all start with db_ and can be set either in the config
# file or with an environment variable (DB_NAME for example).
# config.db_driver = 'mongo'
# config.db_name = (config.app_name + '_' + Volt.env.to_s)
# config.db_host = 'localhost'
# config.db_port = 27017
#####################
# Compression options
#####################
# If you are not running behind something like nginx in production, you can
# have rack deflate all files.
# config.deflate = true
#######################
# Public configurations
#######################
# Anything under config.public will be sent to the client as well as the server,
# so be sure no private data ends up under public
# Use username instead of email as the login
# config.public.auth.use_username = true
#####################
# Compression Options
#####################
# Disable or enable css/js compression. Default is to only run in production.
# if Volt.env.production?
# config.compress_javascript = true
# config.compress_css = true
# end
################
# Mailer options
################
# The volt-mailer gem uses pony (https://github.com/benprew/pony) to deliver e-mail. Any
# options you would pass to pony can be setup below.
# NOTE: The from address is setup at the top
# Normally pony uses /usr/sbin/sendmail if one is installed. You can specify smtp below:
# config.mailer.via = :smtp
# config.mailer.via_options = {
# :address => 'smtp.yourserver.com',
# :port => '25',
# :user_name => 'user',
# :password => 'password',
# :authentication => :plain, # :plain, :login, :cram_md5, no auth by default
# :domain => "localhost.localdomain" # the HELO domain provided by the client to the server
# }
#############
# Message Bus
#############
# Volt provides a "Message Bus" out of the box. The message bus provides
# a pub/sub service between any volt instance (server, client, runner, etc..)
# that share the same database. The message bus can be used by app code. It
# is also used internally to push data to any listening clients.
#
# The default message bus (called "peer_to_peer") uses the database to sync
# socket ip's/ports.
# config.message_bus.bus_name = 'peer_to_peer'
#
# Encrypt message bus - messages on the message bus are encrypted by default
# using rbnacl.
# config.message_bus.disable_encryption = true
#
# ## MessageBus Server -- the message bus binds to a port and ip which the
# other volt instances need to be able to connect to. You can customize
# the server below:
#
# Port range - you can specify a range of ports that an instance can bind the
# message bus on. You can specify a range, an array of Integers, or an array
# of ranges.
# config.message_bus.bind_port_ranges = (58000..61000)
#
# Bind Ip - specifies the ip address the message bus server should bind on.
# config.message_bus.bind_ip = '127.0.0.1'
#############
# Concurrency
#############
# Volt provides a thread worker pool for incoming task requests (and all
# database requests, since those use tasks to do their work.) The following
# lets you control the size of the worker pool. Threads are only created as
# needed, and are removed after a certain amount of inactivity.
# config.min_worker_threads = 1
# config.max_worker_threads = 10
#
# You can also specify the amount of time a Task should run for before it
# timeout's. Setting this to short can cause unexpected results, currently
# we recomend it be at least 10 seconds.
# config.worker_timeout = 60
end

View File

@ -1,15 +0,0 @@
<!DOCTYPE html>
<html>
<%# IMPORTANT: Please read before changing! %>
<%# This file is rendered on the server using ERB, so it does NOT use Volt's %>
<%# normal template system. You can add to it, but keep in mind the template %>
<%# language difference. This file handles auto-loading all JS/Opal and CSS. %>
<head>
<meta charset="UTF-8" />
<%= javascript_tags %>
<%= css_tags %>
</head>
<body>
</body>
</html>

11
index.html.erb Normal file
View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Debugger</title>
<link rel="stylesheet" href="/assets/css/menu.css" type="text/css" charset="utf-8">
<link rel="stylesheet" href="/assets/css/app.css" type="text/css" charset="utf-8">
</head>
<body>
<%= javascript_include_tag "debugger" %>
</body>
</html>

14
lib/base/constant_view.rb Normal file
View File

@ -0,0 +1,14 @@
require_relative "element_view"
class ConstantView < ElementView
def initialize class_or_id , text = nil
@class_or_id = class_or_id
@text = text
end
def draw
@element = div(@class_or_id , @text)
end
end

81
lib/base/element_view.rb Normal file
View File

@ -0,0 +1,81 @@
class ElementView
def initialize
@element = nil
end
#abstract function that should return the single element that is being represented
# the element is also stored in @element
def draw
raise "implement me to return an Element"
end
# helper function to create an element with possible classes, id and text
# The first argument is a bit haml inspired, so "tagname.classname" is the format
# but if tagname is ommited it will default to div
# also several classnames may be given
# if one of the names ends in a ! (bang) it will be assigned as the id
# second argument is optional, but if given will be added as text (content) to the newly
# created Element
# return the new Element, which is not linked into the dom at that point (see << and add*)
def div name_class = "div" , text = nil
name , clazz = name_class.split(".")
name = "div" if name.empty?
element = $document.create_element(name)
element.text = text if text
return element unless clazz
if( clazz.is_a? Array )
clazz.each { |c| add_class_or_id( element , cl )}
else
add_class_or_id element , clazz
end
element
end
def add_class_or_id element , class_or_id
return element unless class_or_id
if class_or_id[-1] == "!"
element.id = class_or_id[0 ... -1]
else
element.add_class class_or_id
end
element
end
# wrap the @element variable with the given element
# so if wrapper == <h4/> the new @element will be <h4> old @element </h4>
# return the new @element, which is wrapper
def wrap_element wrapper
@element = wrap_node_with @element , wrapper
end
#wrap the given node with the wappper, so for a div wrapper and a button node
# the result will be <div> <button>hwatever was in there</button> <div>
def wrap_node_with node , wrapper
node.replace_with(wrapper) if node.parent
wrapper << node
end
# add the given element to the @element, at the end
# return the div that was passed in (use << to return the @element)
def append_element div
@element << div
div
end
# add the given element to the @element , at the front
# return the div that was passed in (use >> to return the @element)
def prepend_element div
@element >> div
div
end
# create a new element with class and possibly text
# add that new element to the @element
# return the newly created element
def add class_or_id , tex = nil
append_element div( class_or_id , tex)
end
end

56
lib/base/list_view.rb Normal file
View File

@ -0,0 +1,56 @@
require_relative "element_view"
class ListView < ElementView
def initialize children
@children = children
@elements = []
end
# create a root node acording to the tag given (default div)
# The tag name will be passed to the div function, so class and id may be set as well (see there)
# draw all children and keep the elements as @elements
# return (as per base class) the single root of the collection
def draw root = "div"
@element = div(root)
@elements = @children.collect do | c |
append_element c.draw
end
@element
end
# replace the child at index with the given one (second arg)
# The child must be an ElementView , which will be rendered and
# the old node will be replaces in the live dom
def replace_at index , with
old = @elements[index]
@children[index] = with
rendered = with.draw
@elements[index] = rendered
old.replace_with rendered
end
# remove the first child and element (from view)
def remove_first
remove_at 0
end
# remove both child and element at given position
def remove_at index
raise "insex out of bounds #{index} => #{@children.length}" if(index >= @children.length or index < 0)
@children.delete_at( index )
element = @elements.delete_at(index)
element.remove
end
# append a View instnace to the children array
# render it and append it to the html element
# and keep a copy in @elements
def append_view view
@children << view
rendered = view.draw
@elements << rendered # add to internal array
@element << rendered # add to html children
rendered
end
end

58
lib/blocks_view.rb Normal file
View File

@ -0,0 +1,58 @@
class BlocksView < ListView
def initialize interpreter
@interpreter = interpreter
@interpreter.register_event(:instruction_changed, self)
super([BlockView.new(@interpreter.block)])
@method_name = method_name
end
def draw
super()
wrap_element div("div.block_view") << div("h4" , "Method + Block " ) << div("h4.method" , @method_name)
return @element
end
def instruction_changed
new_name = method_name
unless new_name == @method_name
@method_name = new_name
@element.at_css(".method").text = method_name
end
return if @interpreter.block.object_id == @children.last.block.object_id
@elements.last.at_css(".bright").remove_class("bright")
append_view( BlockView.new(@interpreter.block) )
remove_first if( @elements.length > 6)
end
def method_name
bl = @interpreter.block
return "" unless bl
return bl.method if bl.method.is_a? String
"#{bl.method.for_class.name}.#{bl.method.name}"
end
end
class BlockView < ElementView
def initialize block
@block = block
end
attr_reader :block
def draw
@element = div("div") << div("span.bright" , block_name )
end
def method_name
return @block.method if @block.method.is_a? String
@block.method.name
end
def block_name
return @block if @block.is_a? String
"#{method_name}.#{@block.name}"
end
end

37
lib/classes_view.rb Normal file
View File

@ -0,0 +1,37 @@
class ClassesView < ListView
def initialize interpreter
@interpreter = interpreter
classes = []
Virtual.machine.space.classes.each do |name , claz|
next if [:Kernel,:Module,:MetaClass,:BinaryCode].index name
classes << claz
end
classes.sort! {|a,b| a.name <=> b.name }
super( classes.collect{|c| ClassView.new(c)})
end
def draw
super()
wrap_element div("ul.nav!")
wrap_element( div(".classes") << div("h4" , "Classes") )
return @element
end
end
class ClassView < ElementView
def initialize clazz
@clazz = clazz
end
def draw
@element = div("li") << div( "a" , @clazz.name ) << (ul = div("ul"))
@clazz.object_layout.object_instance_names.each do |name|
ul << (div("li") << div("a", name ))
end
@element.style["z-index"] = 20
@element
end
end

47
lib/debugger.rb Normal file
View File

@ -0,0 +1,47 @@
require "opal"
require "opal-parser"
require 'browser'
require 'native'
require "salama"
require "interpreter/interpreter"
require "base/list_view"
require_relative "classes_view"
require_relative "status_view"
require_relative "file_view"
require_relative "blocks_view"
require_relative "instruction_view"
require_relative "registers_view"
class MainView < ListView
def initialize
machine = Virtual.machine.boot
# compile_main includes the parse
# parsing generates an ast as seen below and then compiles it.
# machine.compile_main "2 + 5"
# so the code above is functionally equivalent to the one below, minus the parse
# When the ast expression is given all works, so pretty sure it is the parse that fails
code = Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(2),Ast::IntegerExpression.new(5))
Virtual::Compiler.compile( code , machine.space.get_main )
machine.run_before "Register::CallImplementation"
@interpreter = Interpreter::Interpreter.new
@interpreter.start machine.init
super( [ClassesView.new(@interpreter) ,
FileView.new ,
BlocksView.new(@interpreter) ,
InstructionView.new(@interpreter) ,
StatusView.new(@interpreter) ,
RegistersView.new(@interpreter) ] )
end
end
view = MainView.new()
view.draw.append_to($document.body)

8
lib/file_view.rb Normal file
View File

@ -0,0 +1,8 @@
class FileView < ElementView
def draw
@element = div(".file_view") << div("h4" ,"Future")
end
end

30
lib/instruction_view.rb Normal file
View File

@ -0,0 +1,30 @@
require "base/constant_view"
require "base/list_view"
class InstructionView < ListView
def initialize interpreter
@interpreter = interpreter
super([ConstantView.new( "span.bright" , "starting" )])
@interpreter.register_event(:instruction_changed, self)
end
def instruction_changed
@element.at_css(".bright").remove_class("bright")
instruction = append_view( ConstantView.new( "span.bright" , instruction_text ) )
wrap_node_with instruction , div
remove_first if( @elements.length > 6)
end
def draw
super()
wrap_node_with @elements.first , div
wrap_element div(".source_view") << div("h4" ,"Virtual Machine Instruction")
@element
end
def instruction_text
return "" unless @interpreter.instruction
@interpreter.instruction.to_s
end
end

54
lib/object_view.rb Normal file
View File

@ -0,0 +1,54 @@
require_relative "ref_view"
class ObjectView < ListView
def initialize object_id , interpreter = nil , z = nil
@object_id = object_id
@z = z
@interpreter = interpreter
@interpreter.register_event(:object_changed, self) if interpreter
super( content_elements )
end
def draw
@element = super(@interpreter ? "ul.nav!" : "ul")
prepend_element div("li" , "-------------------------")
prepend_element div( "li" ) << div("span" , class_header(@object_id) )
return @element
end
def object_changed reg , at
puts "Object changed in #{reg}"
for_object = @interpreter.get_register( reg )
return unless for_object == @object_id
puts "Object changed #{for_object} , at #{at}"
end
def class_header(id)
object = Virtual.machine.objects[id]
clazz = object.class.name.split("::").last
[clazz, id].join " : "
end
def content_elements
object = Virtual.machine.objects[@object_id]
fields = []
if object and ! object.is_a?(String)
fields << RefView.new( "layout" , object.get_layout.object_id , @z )
object.get_instance_variables.each do |variable|
f = object.get_instance_variable(variable)
fields << RefView.new( variable , f.object_id , @z )
end
if( object.is_a?(Parfait::List) )
index = 1
object.each do | o , i|
fields << RefView.new( index.to_s , o.object_id , @z )
index += 1
end
end
end
fields
end
end

View File

@ -1,6 +1,6 @@
require "salama-reader"
class ParseTask < Volt::Task
class ParseTask
def parse(num)
string_input = '"Hello again".putstring()'
parser = Parser::Salama.new

59
lib/ref_view.rb Normal file
View File

@ -0,0 +1,59 @@
class RefView < ListView
def initialize name , value , z = nil
@name = name
@value = value
@z = z
super []
end
attr_reader :value
def value= val
@value = val
add_hover
end
def draw
@element = div("li") << div("a" , "#{@name} : #{marker(@value)}" )
add_hover
@element.style["z-index"] = @z if @z
@element
end
def add_hover
return if is_string?
@element.on("hover"){ hover } if is_object?(@value)
end
def is_object?( )
Virtual.machine.objects[@value] != nil
end
def is_string?()
Virtual.machine.objects[@value].is_a? String
end
def is_nil?()
Virtual.machine.objects[@value].nil?
end
def hover
puts "hovering #{@name}"
append_view ObjectView.new(@value)
@element.off("hover")
end
def marker id
if is_string?
str = @value
elsif is_nil?
str = "nil"
else
var = Virtual.machine.objects[id]
str = var.class.name.split("::").last[0,2]
str + " : #{id.to_s}"
end
end
end

51
lib/registers_view.rb Normal file
View File

@ -0,0 +1,51 @@
require_relative "object_view"
class RegistersView < ListView
def initialize interpreter
@interpreter = interpreter
@interpreter.register_event(:register_changed, self)
kids = []
@interpreter.registers.each do |reg , val|
kids << ValueView.new( val )
end
super(kids)
end
def draw
super( "div.registers_view" )
@element.children.each_with_index do |reg, index|
elem = div("div.register_view")
wrap_node_with reg , elem
end
@element
end
def register_changed reg , old , value
reg = reg.symbol unless reg.is_a? Symbol
index = reg.to_s[1 .. -1 ].to_i
if( is_object? value )
swap = ObjectView.new( value , @interpreter , 16 - index )
else
swap = ValueView.new value
end
replace_at index , swap
# @elements[index].style["z-index"] = -index
end
def is_object?( id )
Virtual.machine.objects[id] != nil
end
end
class ValueView < ElementView
def initialize value
@value = value
end
def draw
@element = div("ul.nav!") << div("li") << div("span", @value)
end
end

42
lib/status_view.rb Normal file
View File

@ -0,0 +1,42 @@
class StatusView < ElementView
def initialize interpreter
@interpreter = interpreter
end
def draw
@element = div(".status_view") <<
div("h4" , "Interpreter" ) <<
div("button.act" , "Next") <<
div( "br") <<
div("span.clock" , clock_text) <<
div( "br") <<
div("span.state" , state_text) <<
div( "br") <<
div( "span.link" , link_text) <<
div( "br" , "Stdout") <<
div("span.stdout")
# set up event handler
@element.at_css(".act").on("click") { self.update }
return @element
end
def update
@interpreter.tick
@element.at_css(".clock").text = clock_text
@element.at_css(".link").text = link_text
@element.at_css(".stdout").text = @interpreter.stdout
end
def link_text
"Link #{@interpreter.link}"
end
def state_text
"State #{@interpreter.state}"
end
def clock_text
"Instruction #{@interpreter.clock}"
end
end