Compare commits

..

205 Commits

Author SHA1 Message Date
Torsten Ruger
14297baeeb update for rubyx integer and api changes 2019-02-09 13:14:01 +02:00
Torsten Ruger
dbb400ac08 fix left view updates 2018-11-06 10:45:15 -08:00
Torsten Ruger
2159c86a5b small fix, works again
update to compiler api changes
some gemfile updates
2018-11-05 18:09:32 -08:00
Torsten Ruger
bba8f787d5 update for yielding
wip
2018-07-30 17:17:27 +03:00
Torsten Ruger
11cdb5872a adjust to rubyx layers
no global machine and positions
also small layout changes
2018-07-03 19:16:12 +03:00
Torsten Ruger
24961e2e10 removed logger (now in util) 2018-06-22 21:48:10 +03:00
Torsten Ruger
3451b546c3 update to work with positions 2018-06-22 19:44:50 +03:00
Torsten Ruger
9832c8730b still +1 errors
also bigger risc view
2018-05-15 12:07:52 +03:00
Torsten Ruger
89e221c748 a larger while example
need a way to see the code
2018-04-20 19:40:17 +03:00
Torsten Ruger
315be69851 fix vool method updating
a start, should do code too
2018-04-18 20:09:22 +03:00
Torsten Ruger
e90597c332 remove fixed height 2018-04-18 17:58:28 +03:00
Torsten Ruger
c379d0f09f also make menu use percentages
somewhat responsive now
even it wont look good small
2018-04-18 17:54:58 +03:00
Torsten Ruger
6c597bea69 remove susy and just use percentage for layout 2018-04-18 17:54:18 +03:00
Torsten Ruger
07edd4ba60 fix mom view update logic 2018-04-17 20:25:56 +03:00
Torsten Ruger
e193d50efd fix classes, status wasn't updating 2018-04-17 19:20:31 +03:00
Torsten Ruger
ce0bdc46a9 introducing mom view
rename source to vool
and instruction to risc
2018-04-17 19:08:10 +03:00
Torsten Ruger
88e49afb60 puts status in header 2018-04-17 18:49:00 +03:00
Torsten Ruger
ff3990841b update space when on re init 2018-04-17 16:43:25 +03:00
Torsten Ruger
0ff418a98c fix startup 2018-04-17 16:35:42 +03:00
Torsten Ruger
7a8e308665 dump dead code
some volt stuff still lying around
2018-04-17 16:35:32 +03:00
Torsten Ruger
2e3475e040 style to fit into site 2018-04-16 21:23:29 +03:00
Torsten Ruger
4ce6aab51c fix spaces z index 2018-04-09 15:10:17 +03:00
Torsten Ruger
17a49348db hack exception
but hey, it can do maths!
2018-04-09 15:08:56 +03:00
Torsten Ruger
73643e4882 add space to left view
show integer and word values
2018-04-07 19:44:47 +03:00
Torsten Ruger
509aff9552 show source better
still wip
2018-04-06 13:03:39 +03:00
Torsten Ruger
4c342d064d make status smaller, source bigger
and value bold
2018-04-04 17:14:33 +03:00
Torsten Ruger
7a9e10fb5f 5 registers per row for better view 2018-04-04 13:16:59 +03:00
Torsten Ruger
c2d69c767c hello world runs through
slower it seems
and source view doesn’t work yet
2018-04-03 19:35:25 +03:00
Torsten Ruger
2feb287b50 slow first steps, 6 before exceptions 2018-04-03 18:24:57 +03:00
Torsten Ruger
0c2738cdef still sputters, but starts again after all that renaming 2018-04-03 16:48:45 +03:00
Torsten Ruger
7be8e040bb add code options
this time inline (not server generated) into the switch view
2016-12-27 20:31:41 +02:00
Torsten Ruger
a6c63f4e57 small layout changes 2016-12-27 18:37:18 +02:00
Torsten Ruger
cc6a050250 getting basics to work 2016-12-25 17:49:09 +02:00
Torsten Ruger
0aafeeeb22 update to use s-tree, not soml 2016-12-22 21:18:51 +02:00
Torsten Ruger
ba34c510c3 update gems, remove older unused stuff 2016-12-22 21:18:10 +02:00
Torsten Ruger
daa75719cc update salaam and fix 2015-11-24 16:26:49 +02:00
Torsten Ruger
5aebc464e2 salaam update and minors 2015-11-10 19:46:21 +02:00
Torsten Ruger
66e989f066 update salama
with word fixes mostly
2015-11-10 11:50:56 +02:00
Torsten Ruger
0a67fc38e4 add missing fie_access to html converter 2015-11-10 11:50:28 +02:00
Torsten Ruger
dee9eb4dca a version of code points
strings and encodings are definitely not the same for mir and opal
the code point version works for me with utf16 encoding (on my machine?)
utf16 is sensible choice though may go with it
2015-11-09 00:04:31 +02:00
Torsten Ruger
7c18ab3e36 update salaam and boot parfait codes too 2015-11-09 00:02:23 +02:00
Torsten Ruger
10664ef090 start on puti 2015-11-09 00:02:02 +02:00
Torsten Ruger
3681b4b5d7 load parfait code over the net too
some very painful promise debugging solved weird string issue
2015-11-09 00:01:44 +02:00
Torsten Ruger
0f7fb9e70f update salaam, fake bignum
Since the interpreter is fixed and uses lignum, some solution
for opal is needed.  Currently hacked
2015-11-08 15:46:25 +02:00
Torsten Ruger
6812b7503b salaam update and small fixes because if that 2015-11-07 22:27:27 +02:00
Torsten Ruger
1b887c0186 fix (slash) logger 2015-11-07 22:26:59 +02:00
Torsten Ruger
969fa758a1 some renames, make space for new layout test 2015-11-07 22:26:39 +02:00
Torsten Ruger
cad3deab3a add working fibonacci examples, while and recursive
for fibo(10) the difference is 270 vs 6500 instructions, a lot
apparently there are as many calls as the fibs result, i.e. 55, for
recursive
2015-11-05 13:58:59 +02:00
Torsten Ruger
453f7d5b4a update salama
updates opal to beta it seems
2015-11-05 13:56:58 +02:00
Torsten Ruger
919b31ed3d remove rescues, better stracktraces
which is funny, because i added the rescues because i wasn’t getting
traces
something changed, possibly opal
2015-11-05 11:43:23 +02:00
Torsten Ruger
30eed9274e fix to use objects instead of ids 2015-11-04 20:29:09 +02:00
Torsten Ruger
cfc5163fb6 more debugging 2015-11-04 20:28:37 +02:00
Torsten Ruger
9c637243ff add flags to status (to debug branches) 2015-11-04 16:45:33 +02:00
Torsten Ruger
9fbf58bf0f lifted logger
don’t really need it in the debugger, but since it’s now used in salama
the require fails ….
2015-11-04 16:30:54 +02:00
Torsten Ruger
7a86f60c2d while code 2015-11-04 16:13:08 +02:00
Torsten Ruger
f7981dcce5 update salaam for int fix
remove  those half indexes
2015-11-04 16:12:57 +02:00
Torsten Ruger
65e5f39420 move to soml ending, new while example 2015-11-04 16:12:37 +02:00
Torsten Ruger
04c7ab7fee update readme and screenshot 2015-11-04 13:12:14 +02:00
Torsten Ruger
04da6af347 fix converter
field_def name has been upgraded, needs processing
2015-11-04 12:31:27 +02:00
Torsten Ruger
7f6f7ee4fd remove link as it doesn't exist anymore 2015-11-04 12:21:03 +02:00
Torsten Ruger
6bbbef235c show labels correctly 2015-11-04 12:20:44 +02:00
Torsten Ruger
ccf3a37003 go to github version 2015-11-04 12:20:20 +02:00
Torsten Ruger
a167a87b1f extract the converter into own file
and small cleanups
2015-11-01 19:14:31 +02:00
Torsten Ruger
d19e89567f updating on changed method 2015-11-01 18:11:38 +02:00
Torsten Ruger
752310ab0a different speed buttons 2015-11-01 18:11:00 +02:00
Torsten Ruger
f2b14c743d dic an spanifying output 2015-11-01 13:36:00 +02:00
Torsten Ruger
09bfae1a5f turning out complete function as html 2015-11-01 13:03:03 +02:00
Torsten Ruger
feeedf973d show all classes, reduce delay 2015-11-01 00:06:03 +02:00
Torsten Ruger
88aa296356 make class view use ref view
so one can drill into a class like any old object
some work refreshing them (as they change on reboot)
2015-10-29 23:36:04 +02:00
Torsten Ruger
e8b0a38478 remove blocks view (superseded by source) 2015-10-29 23:06:24 +02:00
Torsten Ruger
be76a57fde to html processor for code 2015-10-29 19:10:02 +02:00
Torsten Ruger
1fd78bf602 update salaam 2015-10-29 19:09:39 +02:00
Torsten Ruger
10d21614a9 make it faster 2015-10-29 19:09:13 +02:00
Torsten Ruger
a18bbeebdf add run button , while pressed runs the program 2015-10-29 18:36:42 +02:00
Torsten Ruger
b76fe1645e separate ticker for internal codes 2015-10-29 16:53:46 +02:00
Torsten Ruger
4bf8ac5345 raw source int the source view 2015-10-29 16:49:14 +02:00
Torsten Ruger
3477de8c81 salaam update
fixes (last?) index bug
2015-10-27 20:08:23 +02:00
Torsten Ruger
18cb04240d showing integers correctly 2015-10-27 18:09:50 +02:00
Torsten Ruger
a8a233705d change to same file ending 2015-10-27 18:09:24 +02:00
Torsten Ruger
17fb7fbf74 opal scope problems
opal eval is in object scope it seems
2015-10-27 12:47:17 +02:00
Torsten Ruger
922ec10f93 no more blocks, replace with labels 2015-10-27 12:46:53 +02:00
Torsten Ruger
76a698f028 update salaam 2015-10-27 12:46:39 +02:00
Torsten Ruger
b6bfddf536 remove dead code (no going back anyway) 2015-10-27 12:46:15 +02:00
Torsten Ruger
9cb4a787b2 virtual - register update 2015-10-27 12:44:02 +02:00
Torsten Ruger
8cde7011ef update salaam, catch errors on tick
otherwise those errors were silently ignored,
i guess because they were on a ui thread
2015-10-22 17:09:05 +03:00
Torsten Ruger
feca6cfbee fix argument view 2015-10-22 14:44:37 +03:00
Torsten Ruger
75b358f2bb fix status update 2015-10-22 14:44:12 +03:00
Torsten Ruger
88935db881 update salaam 2015-10-22 14:44:00 +03:00
Torsten Ruger
9fc354d30f new example 2015-10-22 14:43:11 +03:00
Torsten Ruger
91e3a8fc03 bit more space for instructions 2015-10-21 18:37:04 +03:00
Torsten Ruger
b4630fb501 add some simple programs
both failing, finally get some work done here
2015-10-21 15:22:56 +03:00
Torsten Ruger
b4fcf6a711 remove local dependency again 2015-10-21 14:08:44 +03:00
Torsten Ruger
94292bf1ca allow for empty view
and reset view when interpreter restarts
2015-10-21 14:05:18 +03:00
Torsten Ruger
906017d1eb let the user switch the program that runs
simply grab one of a presets
clear views and start interpreter with the parse from server
2015-10-21 14:04:42 +03:00
Torsten Ruger
b8e309b701 don't pre-start interpreter anymore, but allow for switching source 2015-10-21 14:03:56 +03:00
Torsten Ruger
4752732bf8 helper to clear the view 2015-10-21 14:03:23 +03:00
Torsten Ruger
45a2c707da simple server api to return possible programs and their parses
Parsley doesn’t work on opal (though it is pure ruby)
thus have to jump through  (client server) hoops
2015-10-21 14:03:02 +03:00
Torsten Ruger
8eade695a4 start of a code repository 2015-10-21 14:01:46 +03:00
Torsten Ruger
82b78b8825 create view directory for views 2015-10-19 19:56:35 +03:00
Torsten Ruger
37e24cd02a update to new syntax 2015-10-19 19:56:10 +03:00
Torsten Ruger
0db8d87c09 putstring 2015-10-17 10:29:04 +03:00
Torsten Ruger
b8dd2b257c update salama 2015-10-17 10:10:33 +03:00
Torsten Ruger
c87b1f615e updating gems 2015-10-07 15:27:34 +03:00
Torsten Ruger
e48b7f5c7a better documentation 2015-10-07 12:24:02 +03:00
Torsten Ruger
ed5b946a70 fix ast for opal 2015-10-07 12:23:46 +03:00
Torsten Ruger
36e3a8d4cc object in register change fixed 2015-10-04 22:39:02 +03:00
Torsten Ruger
d23a9846e3 switch to sat and load code from file 2015-10-02 20:25:54 +03:00
Torsten Ruger
ab55f64cdf minitest adds itself 2015-08-26 12:23:11 +03:00
Torsten Ruger
3ca4f29ed1 yanked diy branch to master 2015-08-25 12:37:29 +02:00
Torsten Ruger
c0bdfe149c fix list and string views 2015-08-25 11:54:44 +02:00
Torsten Ruger
5ec7ea6d56 small fix 2015-08-25 09:57:22 +02:00
Torsten Ruger
ee788b3507 add layout to object view 2015-08-25 09:57:08 +02:00
Torsten Ruger
85e099382d fix method update 2015-08-24 02:19:41 +02:00
Torsten Ruger
7d214e7013 finish off instruction view (+small rename) 2015-08-24 02:04:07 +02:00
Torsten Ruger
c5a07be6ac inlined mini clases 2015-08-24 01:49:41 +02:00
Torsten Ruger
b3de7c9b5e implement instruction view , almost complete 2015-08-24 01:45:33 +02:00
Torsten Ruger
516b041bed small improvements 2015-08-24 01:44:50 +02:00
Torsten Ruger
a25d292e1f improve style a bit 2015-08-24 01:44:04 +02:00
Torsten Ruger
167353fdf3 update method name 2015-08-23 02:28:31 +02:00
Torsten Ruger
95c4d656b3 last DOM cleaning 2015-08-23 02:20:36 +02:00
Torsten Ruger
3319b0cd98 fix the z index 2015-08-23 02:16:32 +02:00
Torsten Ruger
7820c5eff0 clean of DOM 2015-08-23 02:16:13 +02:00
Torsten Ruger
a56e811699 small fix and expansion to 5 level 2015-08-23 02:15:34 +02:00
Torsten Ruger
83e0c8a925 now very simple to get expanding objects 2015-08-22 21:17:32 +02:00
Torsten Ruger
7885ae93c4 redo object view as list, introduce ref view 2015-08-22 20:11:33 +02:00
Torsten Ruger
caa1da342c remove the root function (pass to super now) 2015-08-22 19:28:09 +02:00
Torsten Ruger
b8a0e5f8a3 fix blocks to change 2015-08-22 18:37:42 +02:00
Torsten Ruger
b43bffc940 remove DOM usage from blocks, make it list view 2015-08-22 17:30:27 +02:00
Torsten Ruger
1ad5681827 remove DOM usage from object 2015-08-22 17:19:07 +02:00
Torsten Ruger
cf1d32e520 objects back on screen, not updating yet 2015-08-22 02:40:19 +02:00
Torsten Ruger
68f67eda54 registers ticking, but objects not showing 2015-08-22 02:23:53 +02:00
Torsten Ruger
ed2a054ca6 starting interpreter and getting ticks going (slowly) 2015-08-22 01:59:29 +02:00
Torsten Ruger
3fa685a0bb assign @element explicitly (remove create_element) 2015-08-22 01:37:15 +02:00
Torsten Ruger
0d4813df13 added separate class view and made classes view a listview 2015-08-22 01:36:11 +02:00
Torsten Ruger
5f2f35cbcf debug by environment (stop endless editing) 2015-08-22 01:35:21 +02:00
Torsten Ruger
15fd4ea7c6 remove some DOM usage 2015-08-22 01:06:48 +02:00
Torsten Ruger
b21ca406c8 rename create_element to div and create to create_element 2015-08-22 01:05:35 +02:00
Torsten Ruger
6925a3fefa bit of organizing 2015-08-21 20:05:49 +02:00
Torsten Ruger
c49c73bb3d starting on register view, next up events 2015-08-21 19:07:27 +02:00
Torsten Ruger
8b743fbcd5 moving functionality in the base classes for all to share 2015-08-21 19:07:02 +02:00
Torsten Ruger
977156ba51 start on block view 2015-08-21 00:37:41 +02:00
Torsten Ruger
287277ef59 basic status view (without updates) 2015-08-20 20:03:00 +02:00
Torsten Ruger
0e430e8b00 cleanup of class view 2015-08-20 20:02:40 +02:00
Torsten Ruger
a6c22cf6e0 change to underscore in class names, for paggio 2015-08-20 20:02:25 +02:00
Torsten Ruger
5c60f29fbf and the class instances. nice to use objects 2015-08-20 19:46:43 +02:00
Torsten Ruger
87c649c622 put the classes back on the screen 2015-08-20 19:40:47 +02:00
Torsten Ruger
1f7c06d626 add some explanation and use github gem versions 2015-08-20 16:13:57 +02:00
Torsten Ruger
ef1235d3e8 small preparations 2015-08-20 16:07:44 +02:00
Torsten Ruger
ef60cbdc45 introduce base classes 2015-08-20 14:48:45 +02:00
Torsten Ruger
e7e85b8d73 revived the styles 2015-08-20 02:14:33 +02:00
Torsten Ruger
bb5caa9bf1 speed up by 50 using men cache 2015-08-20 00:53:39 +02:00
Torsten Ruger
3c959fecb2 initial steps 2015-08-20 00:53:20 +02:00
Torsten Ruger
4257bc446f fix, was outdated 2015-08-19 22:34:39 +02:00
Torsten Ruger
83b9511df3 small ui changes 2015-08-19 22:24:37 +02:00
Torsten Ruger
719f026d0f reduce object to list and register to show that list
also remove duplication in registercontroller
ready for events
2015-08-19 00:22:08 +02:00
Torsten Ruger
d7e0cd665f working more with id only 2015-08-19 00:08:28 +02:00
Torsten Ruger
ef321dab26 start to unify and test listeners 2015-08-18 23:08:12 +02:00
Torsten Ruger
f942ed719a try to get object recursion going 2015-08-16 10:01:12 +03:00
Torsten Ruger
a779daf205 flatten object args and test level 2015-08-15 11:50:44 +03:00
Torsten Ruger
9837461a86 pull out a section for an object 2015-08-14 22:57:37 +03:00
Torsten Ruger
08fba7129b second and third levels for register view 2015-08-14 20:27:06 +03:00
Torsten Ruger
5583a7a56c getting the levels right in registers 2015-08-14 20:14:00 +03:00
Torsten Ruger
3d2dadbd62 show variables for classes, small layout fix 2015-08-13 19:54:45 +03:00
Torsten Ruger
c6d5824dff make suckerfish look nice 2015-08-13 19:32:03 +03:00
Torsten Ruger
a1f1d9d6a4 back to suckerfish 2015-08-13 18:49:22 +03:00
Torsten Ruger
2b9f16dad4 another level for try out 2015-08-13 17:49:12 +03:00
Torsten Ruger
33ee57e605 menumatic instead of tooltips 2015-08-12 21:09:46 +03:00
Torsten Ruger
7b82ff31dd more and meaningful tooltips 2015-08-10 22:29:49 +03:00
Torsten Ruger
8ed2a03ea9 better multiline tooltip code 2015-08-09 12:57:32 +03:00
Torsten Ruger
0926f1f85f more info 2015-08-09 12:15:22 +03:00
Torsten Ruger
72a2d22215 add simtip, remove css hint 2015-08-09 12:15:05 +03:00
Torsten Ruger
abb22f524b better register contents view 2015-08-08 17:52:24 +03:00
Torsten Ruger
b91fabdd90 testing addition 2015-08-04 21:45:49 +03:00
Torsten Ruger
878ec9aecc forgot parslet 2015-07-31 21:41:11 +03:00
Torsten Ruger
50367abcbb try 2015-07-31 20:42:25 +03:00
Torsten Ruger
64078cc331 update to http git 2015-07-31 20:36:35 +03:00
Torsten Ruger
65d95de885 block and source views seperated 2015-07-31 19:42:34 +03:00
Torsten Ruger
bdfafd17c8 classes view separated out 2015-07-31 19:35:06 +03:00
Torsten Ruger
ab08fcc7c1 cleaning, upgrade last pre 2015-07-31 19:31:02 +03:00
Torsten Ruger
cfc6f09ec1 move the interpreter to the app
too ugly to drag it around everywhere
2015-07-31 18:32:36 +03:00
Torsten Ruger
1728cc1b25 made status into own view 2015-07-31 14:10:55 +03:00
Torsten Ruger
5bd6b3517d made view component out of register view 2015-07-31 11:42:26 +03:00
Torsten Ruger
69e51a1037 update gemfile to github versions 2015-07-30 20:07:27 +03:00
Torsten Ruger
ba8768e374 moved interpreter in salama 2015-07-30 19:23:25 +03:00
Torsten Ruger
33b0260bfb move interpretr to salama 2015-07-30 16:03:59 +03:00
Torsten Ruger
b81c8e69b7 cleanup 2015-07-30 15:18:19 +03:00
Torsten Ruger
eba80177ae minor fixes 2015-07-30 15:05:57 +03:00
Torsten Ruger
9afaeba302 add sources 2015-07-30 15:05:44 +03:00
Torsten Ruger
4c4d90385f add clock and method name 2015-07-30 15:05:22 +03:00
Torsten Ruger
e8a5a20db1 fix register update 2015-07-30 14:00:49 +03:00
Torsten Ruger
08beaa2d93 formatting 2015-07-30 11:26:48 +03:00
Torsten Ruger
bb24a6cae5 adds button and blocks tick over 2015-07-30 10:27:27 +03:00
Torsten Ruger
d8a3657365 some real models 2015-07-30 10:09:04 +03:00
Torsten Ruger
a2f3daa828 registers back (non updating) 2015-07-29 21:05:02 +03:00
Torsten Ruger
9383f0d75e salaam boots and classes are shown 2015-07-29 20:50:39 +03:00
Torsten Ruger
264a52c184 basic view up with styles 2015-07-29 18:50:03 +03:00
Torsten Ruger
3bad4cc570 first steps (nothing works) 2015-07-29 18:19:26 +03:00
Torsten Ruger
56521fd5ed new versions 2015-07-29 17:34:15 +03:00
Torsten Ruger
a0b37977a9 volt new overlay 2015-07-29 17:26:04 +03:00
Torsten Ruger
9c7a333127 move code here 2015-07-29 17:17:37 +03:00
Torsten Ruger
485f3134dd revieve volt scaffold 2015-07-29 17:13:04 +03:00
Torsten Ruger
a49ef347ff more opal changes 2015-07-14 16:03:06 +03:00
Torsten Ruger
71ed4f60d7 more transition 2015-07-14 14:21:33 +03:00
Torsten Ruger
7d2120fdd5 removing more volt 2015-07-14 14:10:11 +03:00
Torsten Ruger
9af1937a71 first step of switch to opal 2015-07-14 14:08:28 +03:00
47 changed files with 1433 additions and 1118 deletions

47
.gitignore vendored
View File

@ -1,42 +1,9 @@
# database
db
# rdoc generated
rdoc
# yard generated
doc
.yardoc
# bundler
.bundle .bundle
*.gem .config
.yardoc
# jeweler generated tmp
pkg .idea
.yardoc
# .sass-cache
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
#
# For MacOS:
#
.DS_Store .DS_Store
compiled
# For TextMate
#*.tmproj
#tmtags
# For emacs:
#*~
#\#*
#.\#*
# For vim:
#*.swp
# Object files
*.o
log
tmp/

26
Gemfile
View File

@ -1,17 +1,21 @@
source 'https://rubygems.org' source 'https://rubygems.org'
gem 'opal-react', :path => '../react.rb' gem "opal"
gem 'opal-jquery' gem 'opal-sprockets'
gem 'react-source' gem 'opal-browser'
gem "parslet" , github: "salama/parslet" gem "rubyx" , "0.6" , path: "../rubyx"
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 "susy"
group :development do gem "rx-file" , :git => "https://github.com/ruby-x/rx-file"
gem "sass"
group :test do
# Testing dependencies
gem "minitest" gem "minitest"
gem "rubygems-tasks" gem 'rspec'
gem 'capybara'
gem 'selenium-webdriver'
gem 'chromedriver2-helper'
gem 'poltergeist'
end end

View File

@ -1,83 +1,120 @@
GIT GIT
remote: git://github.com/salama/parslet.git remote: https://github.com/ruby-x/rx-file
revision: beeb9b441a9ade1504f7f0e848d805e36a02c544 revision: 7c4a5546136d1bad065803da91778b209c18cb4d
specs: specs:
parslet (1.7.0) rx-file (0.3.0)
GIT
remote: git://github.com/salama/salama-arm.git
revision: 0bd5091e3f284ecf040e0086a41d2449cd5afb7a
specs:
salama-arm (0.0.1)
GIT
remote: git://github.com/salama/salama-object-file.git
revision: fbae6a02764dbe97e01e4833f9ffffe09879b100
specs:
salama-object-file (0.2.0)
GIT
remote: git://github.com/salama/salama-reader.git
revision: 841592c667acea1e796f950851262e6938b231bc
specs:
salama-reader (0.2.0)
parslet (~> 1.7.0)
GIT
remote: git://github.com/salama/salama.git
revision: 3fb08acf3f83aa403b095aa60be1702419d8a66d
specs:
salama (0.2.0)
salama-object-file (~> 0.2)
salama-reader (~> 0.2)
PATH PATH
remote: ../react.rb remote: ../rubyx
specs: specs:
opal-react (0.2.2) rubyx (0.6.0)
opal parser (~> 2.3.0)
opal-activesupport rx-file (~> 0.3)
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0)
ast (2.4.0)
capybara (3.13.2)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (~> 1.2)
xpath (~> 3.2)
childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
chromedriver2-helper (0.0.10)
nokogiri
cliver (0.3.2)
concurrent-ruby (1.1.4)
diff-lcs (1.3)
ffi (1.10.0)
hike (1.2.3) hike (1.2.3)
minitest (5.7.0) mini_mime (1.0.1)
opal (0.8.0) mini_portile2 (2.4.0)
minitest (5.11.3)
nokogiri (1.10.1)
mini_portile2 (~> 2.4.0)
opal (0.11.4)
ast (>= 2.3.0)
hike (~> 1.2) hike (~> 1.2)
parser (= 2.3.3.1)
sourcemap (~> 0.1.0) sourcemap (~> 0.1.0)
opal-browser (0.2.0)
opal
paggio
opal-sprockets (0.4.2.0.11.0.3.1)
opal (~> 0.11.0)
sprockets (~> 3.1) sprockets (~> 3.1)
tilt (>= 1.4) tilt (>= 1.4)
opal-activesupport (0.1.0) paggio (0.2.6)
opal (>= 0.5.0, < 1.0.0) parser (2.3.3.1)
opal-jquery (0.4.0) ast (~> 2.2)
opal (>= 0.7.0, < 0.9.0) poltergeist (1.18.1)
rack (1.6.4) capybara (>= 2.1, < 4)
react-source (0.13.3) cliver (~> 0.3.1)
rubygems-tasks (0.2.4) websocket-driver (>= 0.2.0)
sass (3.4.16) public_suffix (3.0.3)
rack (2.0.6)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
regexp_parser (1.3.0)
rspec (3.8.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-core (3.8.0)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.0)
rubyzip (1.2.2)
sass (3.7.3)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
selenium-webdriver (3.141.0)
childprocess (~> 0.5)
rubyzip (~> 1.2, >= 1.2.2)
sourcemap (0.1.1) sourcemap (0.1.1)
sprockets (3.2.0) sprockets (3.7.2)
rack (~> 1.0) concurrent-ruby (~> 1.0)
susy (2.2.5) rack (> 1, < 3)
sass (>= 3.3.0, < 3.5) tilt (2.0.9)
tilt (2.0.1) websocket-driver (0.7.0)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3)
xpath (3.2.0)
nokogiri (~> 1.8)
PLATFORMS PLATFORMS
ruby ruby
DEPENDENCIES DEPENDENCIES
capybara
chromedriver2-helper
minitest minitest
opal-jquery opal
opal-react! opal-browser
parslet! opal-sprockets
react-source poltergeist
rubygems-tasks rspec
salama! rubyx (= 0.6)!
salama-arm! rx-file!
salama-object-file! sass
salama-reader! selenium-webdriver
susy
BUNDLED WITH BUNDLED WITH
1.10.5 1.17.2

127
README.md
View File

@ -1,36 +1,117 @@
# Debugger # Debugger
After some tryouts it ended up being an Opal application. That is ruby as javascript in the browser. After some tryouts it ended up being an Opal application. That is ruby as javascript in the browser.
Below is a screenshot.
![Debugger](https://raw.githubusercontent.com/salama/salama-debugger/master/static/debugger.png) ![Debugger](https://raw.githubusercontent.com/rubyx/rubyx-debugger/master/static/debugger.png)
- On the left are the classes of the system. Next idea is to have hover info about them. ## Views
- 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. From left to right there are several views showing different data and controls.
All of the green boxes are in fact pop-up menus and can show more information.
Most of these are implemented as a single class with the name reflecting what part.
I wrote 2 base classes that handle element generation (ie there is hardly any html involved, just elements)
### Switch view
Top left at the top is a little control to switch files.
The files need to be in the repository, but at least one can have several and switch between
them without stopping the debugger.
Parsing is the only thing that opal chokes on, so the files are parsed by a server script and the
ast is sent to the browser.
### Classes View
The first column on the left is a list of classes in the system. Like on all boxes one can hover
over a name to look at the class and it's instance variables (recursively)
### Source View
I don't want to use gdb anymore, and it would be easier without using the qemu setup, so: Next is a view of the Soml source. The Source is reconstructed from the ast as html.
Soml (Salama object machine language) is is a statically typed language,
maybe in spirit close to c++ (without the c). In the future Salama will compile ruby to soml.
- single step debugging of the register machine level (as close to arm as need be) While stepping through the code, those parts of the code that are active get highlighted in blue.
- visual transitions for steps
- visualisation of data in registers (some kind of link to the object) Currently stepping is done only in register instructions, which means that depending on the source
- show the current instruction and a few around constructs it may take many steps for the cursor to move on.
- show vm object (message etc)
- show effect of register transitions on vm objects Each step will show progress on the register level though (next view)
- visualize vm object content (again some links)
# Space ### Register Instruction view
- Visualise the object space in some way Salama defines a register machine level which is quite close to the arm machine, but with more
- Visualise single object, bit like atoms sensible names. It has 16 registers (below) and an instruction set that is useful for Soml.
- values immediate
- objects as link Data movement related instruction implement an indexed get and set. There is also Constant load and
integer operators and off course branches.
Instructions print their name and used registers r0-r15.
The next instruction to be executed is highlighted in blue. A list of previous instructions is shown.
One can follow the effect of instruction in the register view below.
### Status View
The last view at the top right show the status of the machine (interpreter to be precise), the
instruction count and any stdout
Current controls include stepping and three speeds of running the program.
- Next (green button) will execute exactly one instruction when clicked. Mostly useful when
debugging the compiler, ie inspecting the generated code.
- Crawl (first blue button) will execute at a moderate speed. One can still follow the
logic at the register level
- Run (second blue button) runs the program at a higher speed where register instruction just
whizz by, but one can still follow the source view. Mainly used to verify that the source executes
as expected and also to get to a specific place in the program (in the absence of breakpoints)
- Wizz (third blue button) makes the program run so fast that it's only useful function is to
fast forward in the code (while debugging)
### Register view
The bottom part of the screen is taken up by the 16 register. As we execute an object oriented
language, we show the object contents if it is an object (not an integer) in a register.
The (virtual) machine only uses objects, and specifically a linked list of Message objects to
make calls. The current message is always in register 0 (analgous to a stack pointer).
All other registers are scratch for statement use.
In Soml expressions compile to the register that holds the expressions value and statements may use
all registers and may not rely on anything other than the message in register 0.
The Register view is now greatly improved, especially in it's dynamic features:
- when the contents update the register obviously updates
- when the object that the register holds updates, the new value is shown immediately
- hovering over a variable will **expand that variable** .
- the hovering works recursively, so it is possible to drill down into objects for several levels
The last feature of inspecting objects is show in the screenshot. This makes it possible
to very quickly verify the programs behaviour. As it is a pure object system , all data is in
objects, and all objects can be inspected.
### Debugging the debugger
Opal is pre 1.0 and is a wip. While current source map support is quite good, one only gets
real lines when switching debug on. Debug make it load every single file seperately, slooows it
down in other words. Set DEBUG environment to switch it on.
I set the sprockets cache to mem-cache and that increase load time from 12s to 1 , so it's quite
usable and restarting a debug is fine.
## Todos
Breakpoints would be nice at some point. Both in step count and variable value.
## Trying it out
Clone
Bundle
bundle exec rackup

View File

@ -1,50 +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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ;
}

98
assets/css/app.css.sass Normal file
View File

@ -0,0 +1,98 @@
body
background-color: #1a1a1a
color: white
.one_class, .classes, .vool_view ,.mom_view , .risc_view, .status_view ,.vool_view
position: relative
float: left
.mom_view , .risc_view , .status_view , .registers_view, .register_view
position: relative
float: left
.one_class
margin: 10px
.classes
width: 16%
margin-left: 1%
.vool_view
width: 12%
margin-left: 1%
.mom_view
width: 16%
margin-left: 1%
overflow-x: hidden
.risc_view
width: 34%
margin-left: 1%
overflow-x: hidden
.status_view
width: 14%
margin-left: 1%
line-height : 1.25em
.header_state
color: #53a5ff
.labels_view
width: 18%
margin-right: 2%
height: 200px
.registers_view
width: 79%
margin-left: 1%
.register_view
width: 19%
margin-right: 1%
margin-top: 10px
&:nth-child(5n + 1)
clear: left
.field
width: 80%
.value
width: 80%
.value_head
background-color: #C5FFD9
.statement
margin-left: 10px
.ticker
text-align: right
.next , .run , .wizz
border-radius: 7px
font-size: 1em
.next
background-color: #00FF66
.run
background-color: #00CC33
.wizz
background-color: #009900
.risc_bright , .mom_bright
background-color: black
color: #53a5ff
border-radius: 7px
.fade_in
transition: background-color 100ms linear
padding-right: 6px
padding-left: 6px
background-color: #00E3FF
border-radius: 7px
h4.select
z-index: 20

45
assets/css/menu.css.sass Normal file
View File

@ -0,0 +1,45 @@
body
font-family: arial, helvetica, serif
#nav , #nav ul
padding: 0
margin: 0
list-style: none
float: left
width: 100%
border-radius: 8px
background: black
border: 2px solid #C3D46A
#nav
li
position: relative
float: left
line-height: 1.25em
width: 99%
a , span
width: 99%
display: block
text-decoration: none
background-color: black
border-radius: 7px
ul
position: absolute
left: -999em
margin-left: 99%
margin-top: -2.7em
ul
left: -999em
#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

5
codes/a_puti.soml Normal file
View File

@ -0,0 +1,5 @@
class Object
int main()
return 55.puti()
end
end

22
codes/fibo_recur.soml Normal file
View File

@ -0,0 +1,22 @@
class Object
int fibonaccir( int n )
if_plus( n - 1 )
int tmp
tmp = n - 1
int a = fibonaccir( tmp )
tmp = n - 2
int b = fibonaccir( tmp )
return a + b
else
return n
end
end
int fib_print(int n)
int fib = fibonaccir( n )
fib.putint()
return fib
end
int main()
return fib_print(7)
end
end

20
codes/fibo_while.soml Normal file
View File

@ -0,0 +1,20 @@
class Object
int fibonaccit(int n)
int a = 0
int b = 1
n = n - 1
while_plus( n )
int tmp = a
a = b
b = tmp + b
n = n - 1
end
b.putint()
return b
end
int main()
int f = fibonaccit( 10 )
return f.puti()
end
end

6
codes/hello_world.soml Normal file
View File

@ -0,0 +1,6 @@
class Object
int main()
"Hello World".putstring()
return 1
end
end

13
codes/if_called.soml Normal file
View File

@ -0,0 +1,13 @@
class Object
int itest(int n)
if_zero( n - 12)
"then".putstring()
else
"else".putstring()
end
end
int main()
itest(20)
end
end

10
codes/if_else.soml Normal file
View File

@ -0,0 +1,10 @@
class Object
int main()
int n = 14
if_plus( n - 12)
"then".putstring()
else
"else".putstring()
end
end
end

23
codes/layout.soml Normal file
View File

@ -0,0 +1,23 @@
class Layout < Object
Class object_class()
return get_internal_word(2)
end
end
class Object
Layout get_layout()
return get_internal_word(1)
end
Class get_class()
Layout l = get_layout()
return l.object_class()
end
int main()
return get_class()
end
end

8
codes/offset_check.soml Normal file
View File

@ -0,0 +1,8 @@
class Object
int puts(Word str)
return str
end
int main()
puts("Hello")
end
end

23
codes/times.soml Normal file
View File

@ -0,0 +1,23 @@
class Object
int times(int a, int b)
if_zero( b )
a = 0
else
int m = b - 1
int t = times(a, m)
a = a + t
end
return a
end
int t_seven()
int tim = times(5,3)
tim.putint()
return tim
end
int main()
return t_seven()
end
end

12
codes/while.soml Normal file
View File

@ -0,0 +1,12 @@
class Object
int main()
int i = 5
while_plus(i)
"out ".putstring()
i = i - 1
end
return i
end
end

View File

@ -1,42 +1,16 @@
# config.ru
require 'bundler' require 'bundler'
Bundler.require Bundler.require
require 'tilt/erb'
require "opal"
require 'opal-sprockets'
Opal.use_gem "salama" Opal.use_gem("rubyx")
Opal.use_gem "salama-arm"
require "tilt/erb" run Opal::Sprockets::Server.new { |s|
require "susy" s.main = 'debugger.js.rb'
require "json"
require "react/source"
class DebugServer < Opal::Server
def parse(num)
string_input = '"Hello again".putstring()'
parser = Parser::Salama.new
out = parser.parse(string_input)
parts = Parser::Transform.new.apply(out)
parts.to_basic
end
def call(env)
if env['PATH_INFO'].include? "/parse.json"
parse_out = parse(1).to_s
[200, { 'Content-Type' => 'text/json' }, [parse_out]]
else
super
end
end
end
run DebugServer.new {|s|
s.append_path 'app'
s.append_path 'lib' s.append_path 'lib'
s.append_path File.dirname(::React::Source.bundled_path_for("react-with-addons.js")) s.append_path 'assets'
s.main = 'main' s.debug = !ENV["DEBUG"].nil?
s.debug = false
s.source_map = true
s.index_path = "index.html.erb" s.index_path = "index.html.erb"
s.sprockets.cache = Sprockets::Cache::MemoryStore.new(50000)
} }

View File

@ -1,12 +1,12 @@
<!DOCTYPE html>
<html> <html>
<head> <head>
<title>Salama Debugger</title> <title>Debugger</title>
<link rel="stylesheet" href="/assets/styles.css"> <meta charset="utf-8"/>
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script> <link rel="stylesheet" href="/assets/css/menu.css" type="text/css" charset="utf-8">
<script src="/assets/react-with-addons.js"></script> <link rel="stylesheet" href="/assets/css/app.css" type="text/css" charset="utf-8">
<%= javascript_include_tag 'main' %>
</head> </head>
<body> <body>
<div id="content"></div> <%= javascript_include_tag "debugger" %>
</body> </body>
</html> </html>

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

@ -0,0 +1,19 @@
require_relative "element_view"
# A very simple ElementView with constant text and class. It uses the ElementView.div function
# to generate the html, see there for details
#
class ConstantView < ElementView
# store the class and text
def initialize class_or_id , text = nil
@class_or_id = class_or_id
@text = text
end
# use ElementView.div to create html from the class and text
def draw
@element = div(@class_or_id , @text)
end
end

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

@ -0,0 +1,90 @@
# The basic idea is somewhat that of a shadow dom.
#
# ElementView wraps a single div with whatever content you want (derive to implement the view)
#
# It must have an element, which is drawn. Draw returns the div or whatever. An ElementView
# does not draw itself, but rather is drawn.
#
# Listviews provide structure
#
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>whatever 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

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

@ -0,0 +1,74 @@
require_relative "element_view"
# Listviews hold an array of elements and are responsible for drawing (and re-drawing them)
#
# A ListView hold the elements, but also the drawn html divs. You can change the element
# structure by adding/removing/replacing and the ListView will take care of redrawing the html
#
# A ListView is itself an ElementView so one can build recursive structures.
#
# Also one can easily change the root html element, or by deriving wrap or edit the resulting html
#
class ListView < ElementView
def initialize children
@children = children
@elements = []
end
def length
@children.length
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 replaced in the live dom
def replace_at( index , node)
old = @elements[index]
@children[index] = node
rendered = node.draw
@elements[index] = rendered
old.replace_with(rendered) if old
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 "index out of bounds #{index} => #{@children.length}" if(index >= @children.length or index < 0)
@children.delete_at( index )
element = @elements.delete_at(index)
element.remove if element
end
# remove all elements and views, basically resetting the list to empty
def clear_view
remove_first while( ! @children.empty? )
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

62
lib/debugger.js.rb Normal file
View File

@ -0,0 +1,62 @@
require "opal"
require "opal-parser"
require 'opal/compiler'
require 'browser'
require 'browser/http'
require 'native'
require "rubyx"
require "ast"
require "util/eventable"
require "risc/interpreter"
# the base, our own mini framework, allows for child and parent views and handles updates
require "base/list_view"
# each seperate view is in it's own class.
require "views/left_view"
require "views/status_view"
require "views/vool_view"
require "views/mom_view"
require "views/risc_view"
require "views/registers_view"
class Bignum
end
class String
def codepoints
arr = []
one = nil
self.each_byte do |c|
if( one )
arr << (one + c * 256)
one = nil
else
one = c
end
end
arr
end
end
module RubyX
def self.debugger_options
{ parfait: {factory: 50} }
end
end
class MainView < ListView
def initialize
compiler = RubyX::RubyXCompiler.new(RubyX.debugger_options)
input = "class Space;def main(arg); return 1; end; end"
linker = compiler.ruby_to_binary(input , :interpreter)
@interpreter = Risc::Interpreter.new(linker)
super( [LeftView.new(@interpreter) ,
VoolView.new(@interpreter) ,
MomView.new(@interpreter) ,
RiscView.new(@interpreter) ,
StatusView.new(@interpreter) ,
RegistersView.new(@interpreter) ] )
end
end
view = MainView.new()
view.draw.append_to($document.body)

View File

@ -1,37 +0,0 @@
# A simple event registering/triggering module to mix into classes.
# Events are stored in the `@events` ivar.
module Eventable
# Register a handler for the given event name.
# The event name is the method name called on the handler object
#
# obj.on(:foo , some_object_that_implements foo( whateverargs)
#
# @param [String, Symbol] name event name
# @param [Object] object handling the event, ie implement the function name
# @return handler
def register_event(name, handler)
event_table[name] << handler
handler
end
def unregister_event(name, handler)
event_table[name].delete handler
end
def event_table
return @event_table if @event_table
@event_table = Hash.new { |hash, key| hash[key] = [] }
end
# Trigger the given event name and passes all args to each handler
# for this event.
#
# obj.trigger(:foo)
# obj.trigger(:foo, 1, 2, 3)
#
# @param [String, Symbol] name event name to trigger
def trigger(name, *args)
event_table[name].each { |handler| handler.send( name.to_sym , *args) }
end
end

View File

@ -1,166 +0,0 @@
require "eventable"
class Interpreter
# fire events for changed pc and register contents
include Eventable
# current instruction or pc
attr_reader :instruction
# an (arm style) link register. store the return address to return to
attr_reader :link
# current executing block. since this is not a hardware simulator this is luxury
attr_reader :block
# the registers, 12
attr_reader :registers
# collect the output
attr_reader :stdout
attr_reader :state
def initialize
@state = "runnnig"
@stdout = ""
@registers = {}
(0...16).each do |r|
set_register "r#{r}".to_sym , "r#{r}:unknown"
end
end
def start bl
set_block bl
end
def set_block bl
return if @block == bl
raise "Error, nil block" unless bl
old = @block
@block = bl
trigger(:block_changed , old , bl)
set_instruction bl.codes.first
end
def set_instruction i
@state = "exited" unless i
return if @instruction == i
old = @instruction
@instruction = i
trigger(:instruction_changed, old , i)
end
def get_register( reg )
reg = reg.symbol if reg.is_a? Register::RegisterReference
raise "Not a register #{reg}" unless Register::RegisterReference.look_like_reg(reg)
@registers[reg]
end
def set_register reg , val
old = get_register( reg ) # also ensures format
return if old === val
reg = reg.symbol if reg.is_a? Register::RegisterReference
@registers[reg] = val
trigger(:register_changed, reg , old , val)
end
def tick
return unless @instruction
name = @instruction.class.name.split("::").last
fetch = send "execute_#{name}"
return unless fetch
fetch_next_intruction
end
def fetch_next_intruction
if(@instruction != @block.codes.last)
set_instruction @block.codes[ @block.codes.index(@instruction) + 1]
else
next_b = @block.method.source.blocks.index(@block) + 1
set_block @block.method.source.blocks[next_b]
end
end
def object_for reg
id = get_register(reg)
Virtual.machine.objects[id]
end
# Instruction interpretation starts here
def execute_Branch
target = @instruction.block
set_block target
false
end
def execute_LoadConstant
to = @instruction.register
value = @instruction.constant.object_id
set_register( to , value )
true
end
def execute_GetSlot
object = object_for( @instruction.array )
value = object.internal_object_get( @instruction.index )
value = value.object_id unless value.is_a? Integer
set_register( @instruction.register , value )
true
end
def execute_SetSlot
value = object_for( @instruction.register )
object = object_for( @instruction.array )
object.internal_object_set( @instruction.index , value )
trigger(:object_changed, @instruction.register )
true
end
def execute_RegisterTransfer
value = get_register @instruction.from
set_register @instruction.to , value
true
end
def execute_FunctionCall
@link = [@block , @instruction]
next_block = @instruction.method.source.blocks.first
set_block next_block
false
end
def execute_SaveReturn
object = object_for @instruction.register
raise "save return has nothing to save" unless @link
trigger(:object_changed, @instruction.register )
object.internal_object_set @instruction.index , @link
true
end
def execute_Syscall
name = @instruction.name
case name
when :putstring
str = object_for( :r1 ) # should test length, ie r2
raise "NO string for putstring #{str}" unless str.is_a? Symbol
@stdout += str.to_s
when :exit
set_instruction(nil)
return false
else
raise "un-implemented syscall #{name}"
end
true
end
def execute_FunctionReturn
object = object_for( @instruction.register )
#wouldn't need to assign to link, but makes tsting easier
@link = object.internal_object_get( @instruction.index )
@block , @instruction = @link
# we jump back to the call instruction. so it is as if the call never happened and we continue
true
end
end

44
lib/views/classes_view.rb Normal file
View File

@ -0,0 +1,44 @@
require_relative "ref_view"
class ClassesView < ListView
def initialize interpreter
@interpreter = interpreter
@interpreter.register_event(:state_changed, self)
super( class_views )
end
def class_views
classes = []
Parfait.object_space.classes.each do |name , claz|
classes << claz
end
classes.sort! {|a,b| a.name <=> b.name }
classes.collect{|c| ClassView.new(c)}
end
def state_changed old , new_s
return unless new_s == :running
class_views.each_with_index do |v, i|
replace_at i , v
end
end
def draw
super()
wrap_element div("ul.nav!")
wrap_element( div("h4" , "Classes") )
return @element
end
end
class ClassView < RefView
def initialize clazz
super(clazz.name , clazz , 20 )
end
def ref_text
@name
end
end

120
lib/views/html_converter.rb Normal file
View File

@ -0,0 +1,120 @@
class HtmlConverter < AST::Processor
alias :old_process :process
def process s
return "" unless s
#puts s.type
old_process(s)
end
def handler_missing s
puts "Missing: " + s.type
"Missing #{s.type}"
end
def div( statement , html)
"<div class='statement' id='i#{statement.object_id.to_s(16)}'>" + html + "</div>"
end
def span( statement , html)
"<span class='expression' id='i#{statement.object_id.to_s(16)}'>" + html + "</span>"
end
def on_function( statement)
return_type , name , parameters, kids , receiver = *statement
str = return_type + " "
str += receiver + "." if receiver
str += name.to_a.first + "("
str += process(parameters) + ")<br>"
str += process(kids) + "end<br>"
div(statement,str)
end
def on_parameters statement
process_all(statement.children).join(",")
end
def on_parameter p
type , name = *p
span(type,type) + " " + span(name,name)
end
def on_string s
span(s, "'" + s.first + "'")
end
def on_receiver expression
span expression , process(expression.first)
end
def on_field expression
span expression , process(expression.first)
end
def on_field_access statement
receiver_ast , field_ast = *statement
receiver = process(receiver_ast)
field = process(field_ast)
span( statement , receiver + "." + field)
end
def on_field_def statement
type , name , value = *statement
str = span(type, type) + " " + process(name)
str += " = #{process(value)}" if value
div(statement,str)
end
def on_return statement
str = "return " + process(statement.first )
div(statement,str)
end
def on_false_statements s
on_statements s
end
def on_true_statements s
on_statements s
end
def on_statements s
str = ""
s.children.each do |c|
str += process(c).to_s
end
div(s,str)
end
def on_while_statement statement
branch_type , condition , statements = *statement
condition = condition.first
ret = "while_#{branch_type}(" + process(condition) + ")<br>"
ret += process(statements)
ret += "end"
div(statement,ret)
end
def on_if_statement statement
branch_type , condition , if_true , if_false = *statement
condition = condition.first
ret = "if_#{branch_type}(" + process(condition) + ")<br>" + process(if_true)
ret += "else" + "<br>" + process(if_false) if if_false
ret += "end"
div(statement,ret)
end
def on_assignment statement
name , value = *statement
name = process(name)
v = process(value)
str = name + " = " + v
div(statement,str)
end
def on_call c
name , arguments , receiver = *c
ret = process(name)
ret = process(receiver.first) + "." + ret if receiver
ret += "("
ret += process(arguments).join(",")
ret += ")"
span(c,ret)
end
def on_operator_value statement
operator , left_e , right_e = *statement
left_reg = process(left_e)
right_reg = process(right_e)
span(statement , left_reg + " " + operator + " " + right_reg )
end
def on_arguments args
args.children.collect{|c| process(c)}
end
def on_name name
span(name,name.first)
end
def on_int i
span(i , i.first.to_s)
end
end

89
lib/views/left_view.rb Normal file
View File

@ -0,0 +1,89 @@
require_relative "classes_view"
# the whole of the left, ie selection, space and classes
class LeftView < ListView
def initialize( interpreter )
@interpreter = interpreter
super([ SelectView.new(interpreter) ,
ObjectView.new( Parfait.object_space , @interpreter , 26),
ClassesView.new(interpreter) ])
interpreter.register_event(:state_changed, self)
end
# need to re-init when we go to running, as the objects (and the actual space) change
# we replace space and class view with new instances
def state_changed( old , new_s )
return unless new_s == :running
space = ObjectView.new( Parfait.object_space , @interpreter , 26)
replace_at( 1 , space )
replace_at( 2 , ClassesView.new(@interpreter) )
end
def draw
super(".classes")
end
end
# view for the little code select, implemented as a normal expandable menu
#
# on click calls select method
#
# derive from element, meaning we draw
# # TODO: make into listview, so code can be the next level expansion
class SelectView < ElementView
def initialize( interpreter )
super
@interpreter = interpreter
@codes = nil
end
def draw
@element = div("h4.select", "Code") << (list = div("ul.nav!"))
list << (div("li.code_list") << div("a.selected" , "none selected"))
selection_codes unless @codes
@element << div("br")
@element << div("br")
end
def selection_codes
@codes = get_codes.keys
list = div "ul"
@codes.each do |c|
code = div("li") << div("a" , c )
code.style["z-index"] = 10
code.on("click"){ select(c) }
list << code
end
@element.at_css(".code_list") << list
end
# select method set up as click handler for the codes
# restart the interpreter after compiling
def select( code )
puts "selecting #{code}"
@interpreter.set_state :stopped
@element.at_css(".selected").text = code
ruby = as_main(get_codes[code])
compiler = RubyX::RubyXCompiler.new(RubyX.debugger_options)
linker = compiler.ruby_to_binary(ruby, :interpreter)
@interpreter.start_program(linker)
end
def as_main(statements)
"class Space ;def yielder; return yield ; end;def main(arg) ; #{statements}; end; end"
end
def get_codes
{ while_with_calls: 'a = 2; while( 0 < a); a = a - 1;end;return a',
set_internal_byte: "return 'Hello'.set_internal_byte(1,75)" ,
basic_if: 'if( 10 ); return "then";else;return "else";end' ,
plus: 'return 5 + 7' ,
yield: "a = yielder {return 15} ; return a" ,
return: 'return 5' ,
hello_world: "h = 'Hello World'.putstring;return h",
dynamic_call: "a = 150 ; return a.div10",
}
end
end

43
lib/views/mom_view.rb Normal file
View File

@ -0,0 +1,43 @@
require "base/constant_view"
require "base/list_view"
class MomView < ListView
def initialize interpreter
@interpreter = interpreter
@current = nil
super([start_view])
@interpreter.register_event(:instruction_changed, self)
@interpreter.register_event(:state_changed, self)
end
def start_view
ConstantView.new( "span.mom_bright" , "starting" )
end
def instruction_changed
i = @interpreter.instruction
return unless i && i.source.is_a?(Mom::Instruction)
return if i.source == @current
@current = i.source
@element.at_css(".mom_bright").remove_class("mom_bright")
instruction = append_view( ConstantView.new( "span.mom_bright" , @current.to_s ) )
wrap_node_with( instruction , div )
remove_first if( @elements.length > 6)
end
def draw
super()
wrap_node_with @elements.first , div
wrap_element div(".mom_view") << div("h4" ,"Mom::Instruction")
@element
end
def state_changed(old , new_s)
return unless new_s == :running
clear_view
@current = nil
append_view start_view
end
end

73
lib/views/object_view.rb Normal file
View File

@ -0,0 +1,73 @@
require_relative "ref_view"
class ObjectView < ListView
# z is the z-index
def initialize object , interpreter = nil , z = nil
@object = object
@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" ) << div("span" , class_header )
return @element
end
def object_changed( reg , at)
#puts "Object changed in #{reg} , at #{at}"
for_object = @interpreter.get_register( reg )
return unless for_object == @object
#puts "Object changed #{for_object} , at #{at}"
variable = @object.get_instance_variables.get(at)
if(variable)
f = @object.get_instance_variable(variable)
else
variable = at.to_s
f = @object.get_internal_word(at)
end
#puts "got var name #{variable}#{variable.class} for #{at}, #{f}"
view = RefView.new( variable , f , @z )
if( @children[at + 1] )
replace_at(at + 1, view)
else
append_view(view)
end
end
def class_header
str = Risc::Position.set?(@object).to_s
clazz = @object.class.name.split("::").last
[clazz, str].join " : "
end
def content_elements
fields = [ConstantView.new("li" , "------------------------------")]
object = @object
if object and ! object.is_a?(String)
object.get_instance_variables.each do |variable|
f = object.get_instance_variable(variable)
fields << RefView.new( variable , f , @z )
end
if( object.is_a?(Parfait::List) )
index = 0
object.each do | o|
fields << RefView.new( index.to_s , o , @z )
index += 1
end
end
if( object.is_a?(Parfait::Integer) )
fields << RefView.new( 3.to_s , object.value , @z )
end
if( object.is_a?(Parfait::Word) )
fields << RefView.new( 3.to_s , object.to_string , @z )
end
end
fields
end
end

69
lib/views/ref_view.rb Normal file
View File

@ -0,0 +1,69 @@
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" , ref_text )
add_hover
@element.style["z-index"] = @z if @z
@element
end
def ref_text
"#{@name} : #{marker()}"
end
def add_hover
return if is_string?
@element.on("hover"){ hover } if is_object?(@value)
end
def is_object?( )
return false if @value.is_a?(Fixnum)
return false unless @value
! is_label?
end
def is_string?()
@value.is_a? String
end
def is_label?
@value.is_a?(Risc::Label)
end
def is_nil?()
@value.nil?
end
def hover
#puts "hovering #{@name}"
append_view ObjectView.new(@value)
@element.off("hover")
end
def marker
if is_string?
str = @value
elsif is_object?
str = Risc::Position.get(@value).to_s
elsif is_label?
str = "Label"
else
str = @value.to_s
end
end
end

View File

@ -0,0 +1,54 @@
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
has = Risc::Position.set?(value)
if( has )
if has.object.is_a?(Risc::Label)
swap = ValueView.new "Label: #{has.object.name}"
else
swap = ObjectView.new( value , @interpreter , 16 - index )
end
else
swap = ValueView.new value
end
replace_at index , swap
# @elements[index].style["z-index"] = -index
end
end
class ValueView < ElementView
def initialize value
@value = value
end
def draw
li = div("li")
li << div("span", @value)
@element = div("ul.nav!") << li
end
end

42
lib/views/risc_view.rb Normal file
View File

@ -0,0 +1,42 @@
require "base/constant_view"
require "base/list_view"
class RiscView < ListView
def initialize interpreter
@interpreter = interpreter
super([start_view])
@interpreter.register_event(:instruction_changed, self)
@interpreter.register_event(:state_changed, self)
end
def start_view
ConstantView.new( "span.risc_bright" , "starting" )
end
def instruction_changed
@element.at_css(".risc_bright").remove_class("risc_bright")
instruction = append_view( ConstantView.new( "span.risc_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(".risc_view") << div("h4" ,"Register Machine Instruction")
@element
end
def state_changed old , new_s
return unless new_s == :running
clear_view
append_view start_view
end
def instruction_text
return "" unless @interpreter.instruction
@interpreter.instruction.to_s
end
end

85
lib/views/status_view.rb Normal file
View File

@ -0,0 +1,85 @@
require "browser/delay"
class StatusView < ElementView
def initialize interpreter
@interpreter = interpreter
@running = false
end
def draw
header = div("h4" , "Interpreter" )
header << div("span.header_state" , state_text)
@element = div(".status_view") <<
header <<
div("button.next" , "Next") <<
div("button.run" , "Run") <<
div("button.wizz" , "Wizz") <<
div( "br") <<
div("span.clock" , clock_text) <<
div( "br") <<
div("span.flags" , flags_text) <<
div( "br") <<
div( "span.stdout" , "Stdout") <<
div( "br") <<
div( "span.status" , "Status")
# set up event handler
@element.at_css(".next").on("click") { self.update }
@element.at_css(".run").on("mousedown") { self.start( 0.1 ) }
@element.at_css(".wizz").on("mousedown") { self.start( 0.0 ) }
@element.at_css(".run").on("mouseup") { self.stop }
@element.at_css(".wizz").on("mouseup") { self.stop }
return @element
end
def start(speed)
@running = speed
run
end
def stop
@running = false
end
def run
return unless @running
proc = Proc.new do
self.update
self.run
end
proc.after( @running )
end
def update
@interpreter.tick
@element.at_css(".clock").text = clock_text
@element.at_css(".header_state").text = state_text
@element.at_css(".flags").text = flags_text
@element.at_css(".stdout").text = @interpreter.stdout
@element.at_css(".status").text = status_text
end
def status_text
return unless @interpreter.instruction
return "#{@interpreter.instruction.to_s}" unless @interpreter.instruction.source
source = @interpreter.instruction.source
s = "#{source.to_s}"
if( source.respond_to?(:source) and source.source )
s += @interpreter.instruction.source.source.to_s
end
s
end
def state_text
" (#{@interpreter.state})"
end
def flags_text
flags = []
@interpreter.flags.each do |name,value|
flags << name if value
end
"Flags #{flags.join(':')}"
end
def clock_text
"Instruction #{@interpreter.clock}-0x#{@interpreter.pc.to_s(16)}"
end
end

46
lib/views/vool_view.rb Normal file
View File

@ -0,0 +1,46 @@
require_relative "html_converter"
class VoolView < ElementView
def initialize interpreter
@interpreter = interpreter
@interpreter.register_event(:instruction_changed, self)
end
def draw
@text = div(".text")
@ticker = div(".ticker")
@element = div(".vool_view") << div("h4.source" , "Class.Method") << @ticker << @text
@element
end
def instruction_changed
i = @interpreter.instruction
return "" unless i
if i.is_a?(Risc::FunctionReturn)
link = @interpreter.get_register( i.register )
puts "Link #{link}:#{link.class}"
raise "No link method" unless link
end
method = nil
case i.source
when Mom::Instruction
if(i.source.is_a?(Mom::SimpleCall))
method = i.source.method
end
#TODO, give mom a source
when Parfait::Callable
method = i.source
when String
return
else
raise "Unrecognized source #{i.source.class.name} for #{i}"
end
update_method(method) if method
end
def update_method(method)
@text.inner_html = method.name
end
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

After

Width:  |  Height:  |  Size: 375 KiB

View File

@ -1,307 +0,0 @@
/*! Hint.css - v1.3.5 - 2015-06-16
* http://kushagragour.in/lab/hint/
* Copyright (c) 2015 Kushagra Gour; Licensed MIT */
/*-------------------------------------*\
HINT.css - A CSS tooltip library
\*-------------------------------------*/
/**
* HINT.css is a tooltip library made in pure CSS.
*
* Source: https://github.com/chinchang/hint.css
* Demo: http://kushagragour.in/lab/hint/
*
* Release under The MIT License
*
*/
/**
* source: hint-core.scss
*
* Defines the basic styling for the tooltip.
* Each tooltip is made of 2 parts:
* 1) body (:after)
* 2) arrow (:before)
*
* Classes added:
* 1) hint
*/
.hint, [data-hint] {
position: relative;
display: inline-block;
/**
* tooltip arrow
*/
/**
* tooltip body
*/ }
.hint:before, .hint:after, [data-hint]:before, [data-hint]:after {
position: absolute;
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
visibility: hidden;
opacity: 0;
z-index: 1000000;
pointer-events: none;
-webkit-transition: 0.3s ease;
-moz-transition: 0.3s ease;
transition: 0.3s ease;
-webkit-transition-delay: 0ms;
-moz-transition-delay: 0ms;
transition-delay: 0ms; }
.hint:hover:before, .hint:hover:after, .hint:focus:before, .hint:focus:after, [data-hint]:hover:before, [data-hint]:hover:after, [data-hint]:focus:before, [data-hint]:focus:after {
visibility: visible;
opacity: 1; }
.hint:hover:before, .hint:hover:after, [data-hint]:hover:before, [data-hint]:hover:after {
-webkit-transition-delay: 100ms;
-moz-transition-delay: 100ms;
transition-delay: 100ms; }
.hint:before, [data-hint]:before {
content: '';
position: absolute;
background: transparent;
border: 6px solid transparent;
z-index: 1000001; }
.hint:after, [data-hint]:after {
content: attr(data-hint);
background: #383838;
color: white;
padding: 8px 10px;
font-size: 12px;
line-height: 12px;
white-space: nowrap; }
/**
* source: hint-position.scss
*
* Defines the positoning logic for the tooltips.
*
* Classes added:
* 1) hint--top
* 2) hint--bottom
* 3) hint--left
* 4) hint--right
*/
/**
* set default color for tooltip arrows
*/
.hint--top:before {
border-top-color: #383838; }
.hint--bottom:before {
border-bottom-color: #383838; }
.hint--left:before {
border-left-color: #383838; }
.hint--right:before {
border-right-color: #383838; }
/**
* top tooltip
*/
.hint--top:before {
margin-bottom: -12px; }
.hint--top:after {
margin-left: -18px; }
.hint--top:before, .hint--top:after {
bottom: 100%;
left: 50%; }
.hint--top:hover:after, .hint--top:hover:before, .hint--top:focus:after, .hint--top:focus:before {
-webkit-transform: translateY(-8px);
-moz-transform: translateY(-8px);
transform: translateY(-8px); }
/**
* bottom tooltip
*/
.hint--bottom:before {
margin-top: -12px; }
.hint--bottom:after {
margin-left: -18px; }
.hint--bottom:before, .hint--bottom:after {
top: 100%;
left: 50%; }
.hint--bottom:hover:after, .hint--bottom:hover:before, .hint--bottom:focus:after, .hint--bottom:focus:before {
-webkit-transform: translateY(8px);
-moz-transform: translateY(8px);
transform: translateY(8px); }
/**
* right tooltip
*/
.hint--right:before {
margin-left: -12px;
margin-bottom: -6px; }
.hint--right:after {
margin-bottom: -14px; }
.hint--right:before, .hint--right:after {
left: 100%;
bottom: 50%; }
.hint--right:hover:after, .hint--right:hover:before, .hint--right:focus:after, .hint--right:focus:before {
-webkit-transform: translateX(8px);
-moz-transform: translateX(8px);
transform: translateX(8px); }
/**
* left tooltip
*/
.hint--left:before {
margin-right: -12px;
margin-bottom: -6px; }
.hint--left:after {
margin-bottom: -14px; }
.hint--left:before, .hint--left:after {
right: 100%;
bottom: 50%; }
.hint--left:hover:after, .hint--left:hover:before, .hint--left:focus:after, .hint--left:focus:before {
-webkit-transform: translateX(-8px);
-moz-transform: translateX(-8px);
transform: translateX(-8px); }
/**
* source: hint-theme.scss
*
* Defines basic theme for tooltips.
*
*/
.hint, [data-hint] {
/**
* tooltip body
*/ }
.hint:after, [data-hint]:after {
text-shadow: 0 -1px 0px black;
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.3); }
/**
* source: hint-color-types.scss
*
* Contains tooltips of various types based on color differences.
*
* Classes added:
* 1) hint--error
* 2) hint--warning
* 3) hint--info
* 4) hint--success
*
*/
/**
* Error
*/
.hint--error:after {
background-color: #b34e4d;
text-shadow: 0 -1px 0px #592726; }
.hint--error.hint--top:before {
border-top-color: #b34e4d; }
.hint--error.hint--bottom:before {
border-bottom-color: #b34e4d; }
.hint--error.hint--left:before {
border-left-color: #b34e4d; }
.hint--error.hint--right:before {
border-right-color: #b34e4d; }
/**
* Warning
*/
.hint--warning:after {
background-color: #c09854;
text-shadow: 0 -1px 0px #6c5328; }
.hint--warning.hint--top:before {
border-top-color: #c09854; }
.hint--warning.hint--bottom:before {
border-bottom-color: #c09854; }
.hint--warning.hint--left:before {
border-left-color: #c09854; }
.hint--warning.hint--right:before {
border-right-color: #c09854; }
/**
* Info
*/
.hint--info:after {
background-color: #3986ac;
text-shadow: 0 -1px 0px #193b4d; }
.hint--info.hint--top:before {
border-top-color: #3986ac; }
.hint--info.hint--bottom:before {
border-bottom-color: #3986ac; }
.hint--info.hint--left:before {
border-left-color: #3986ac; }
.hint--info.hint--right:before {
border-right-color: #3986ac; }
/**
* Success
*/
.hint--success:after {
background-color: #458746;
text-shadow: 0 -1px 0px #1a321a; }
.hint--success.hint--top:before {
border-top-color: #458746; }
.hint--success.hint--bottom:before {
border-bottom-color: #458746; }
.hint--success.hint--left:before {
border-left-color: #458746; }
.hint--success.hint--right:before {
border-right-color: #458746; }
/**
* source: hint-always.scss
*
* Defines a persisted tooltip which shows always.
*
* Classes added:
* 1) hint--always
*
*/
.hint--always:after, .hint--always:before {
opacity: 1;
visibility: visible; }
.hint--always.hint--top:after, .hint--always.hint--top:before {
-webkit-transform: translateY(-8px);
-moz-transform: translateY(-8px);
transform: translateY(-8px); }
.hint--always.hint--bottom:after, .hint--always.hint--bottom:before {
-webkit-transform: translateY(8px);
-moz-transform: translateY(8px);
transform: translateY(8px); }
.hint--always.hint--left:after, .hint--always.hint--left:before {
-webkit-transform: translateX(-8px);
-moz-transform: translateX(-8px);
transform: translateX(-8px); }
.hint--always.hint--right:after, .hint--always.hint--right:before {
-webkit-transform: translateX(8px);
-moz-transform: translateX(8px);
transform: translateX(8px); }
/**
* source: hint-rounded.scss
*
* Defines rounded corner tooltips.
*
* Classes added:
* 1) hint--rounded
*
*/
.hint--rounded:after {
border-radius: 4px; }
/**
* source: hint-effects.scss
*
* Defines various transition effects for the tooltips.
*
* Classes added:
* 1) hint--no-animate
* 2) hint--bounce
*
*/
.hint--no-animate:before, .hint--no-animate:after {
-webkit-transition-duration: 0ms;
-moz-transition-duration: 0ms;
transition-duration: 0ms; }
.hint--bounce:before, .hint--bounce:after {
-webkit-transition: opacity 0.3s ease, visibility 0.3s ease, -webkit-transform 0.3s cubic-bezier(0.71, 1.7, 0.77, 1.24);
-moz-transition: opacity 0.3s ease, visibility 0.3s ease, -moz-transform 0.3s cubic-bezier(0.71, 1.7, 0.77, 1.24);
transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s cubic-bezier(0.71, 1.7, 0.77, 1.24); }

View File

@ -1,21 +0,0 @@
require 'rubygems'
require 'bundler'
begin
Bundler.setup(:default, :development)
rescue Bundler::BundlerError => e
$stderr.puts e.message
$stderr.puts "Run `bundle install` to install missing gems"
exit e.status_code
end
if ENV['CODECLIMATE_REPO_TOKEN']
require "codeclimate-test-reporter"
CodeClimate::TestReporter.start
end
require "minitest/autorun"
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
require "salama"
require "interpreter"

View File

@ -1,82 +0,0 @@
require_relative "helper"
class InterpreterTest < MiniTest::Test
def setup
Virtual.machine.boot
code = Ast::ExpressionList.new( [Ast::CallSiteExpression.new(:putstring, [] ,Ast::StringExpression.new("Hello again"))])
Virtual::Compiler.compile( code , Virtual.machine.space.get_main )
Virtual.machine.run_before "Register::CallImplementation"
@interpreter = Interpreter.new
@interpreter.start Virtual.machine.init
end
def ticks num
last = nil
num.times do
last = @interpreter.instruction
@interpreter.tick
end
return last
end
def test_branch
was = @interpreter.block
assert_equal Register::Branch , ticks(1).class
assert was != @interpreter.block
end
def test_load
assert_equal Register::LoadConstant , ticks(2).class
assert_equal Parfait::Space , Virtual.machine.objects[ @interpreter.get_register(:r1)].class
assert_equal :r1, @interpreter.instruction.array.symbol
end
def test_get
assert_equal Register::GetSlot , ticks(3).class
assert @interpreter.get_register( :r3 )
assert @interpreter.get_register( :r3 ).is_a? Integer
end
def test_transfer
transfer = ticks 5
assert_equal Register::RegisterTransfer , transfer.class
assert_equal @interpreter.get_register(transfer.to) , @interpreter.get_register(transfer.from)
end
def test_call
assert_equal Register::FunctionCall , ticks(7).class
assert @interpreter.link
end
def test_save
done = ticks(8)
assert_equal Register::SaveReturn , done.class
assert @interpreter.get_register done.register.symbol
end
def test_chain
["Branch" , "LoadConstant" , "GetSlot" , "SetSlot" , "RegisterTransfer" ,
"GetSlot" , "FunctionCall" , "SaveReturn" , "LoadConstant" , "SetSlot" ,
"GetSlot" , "GetSlot" , "SetSlot" , "LoadConstant" , "SetSlot" ,
"RegisterTransfer" , "GetSlot" , "FunctionCall" , "SaveReturn" , "RegisterTransfer" ,
"Syscall" , "RegisterTransfer" , "RegisterTransfer" , "SetSlot" , "GetSlot" ,
"GetSlot" , "RegisterTransfer" ,"GetSlot" , "GetSlot","GetSlot",
"FunctionReturn" , "RegisterTransfer" , "Syscall" , "NilClass"].each_with_index do |name , index|
got = ticks(1)
assert got.class.name.index(name) , "Wrong class for #{index+1}, expect #{name} , got #{got}"
end
end
def test_putstring
done = ticks(21)
assert_equal Register::Syscall , done.class
assert_equal "Hello again" , @interpreter.stdout
end
def test_return
done = ticks(31)
assert_equal Register::FunctionReturn , done.class
assert @interpreter.block.is_a?(Virtual::Block)
assert @interpreter.instruction.is_a?(Register::Instruction) , "not instruction #{@interpreter.instruction}"
end
def test_exit
done = ticks(34)
assert_equal NilClass , done.class
end
end