Skip to content

Commit 86ed358

Browse files
committedJun 29, 2015
Add JSON representation to those emitted by InstructionParser.
This is intended to be a machine-readable description of all VM instructions to be used to produce arbitrary forms of documentation and tooling for the VM without requiring integration into InstructionParser itself.
1 parent 291c7c7 commit 86ed358

File tree

2 files changed

+92
-12
lines changed

2 files changed

+92
-12
lines changed
 

‎rakelib/instruction_parser.rb

+88-12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require 'json'
2+
13
# A simple parser to transform a description of the VM instructions into
24
# various implementation files.
35
#
@@ -480,11 +482,36 @@ def produced
480482
@produced || @instruction.produced + ["..."]
481483
end
482484

483-
def format(file)
485+
def description
486+
@description.join.gsub(/\n +/, " ").gsub(/\n +/, "\n").strip
487+
end
488+
489+
def notes
490+
@notes.join.gsub(/\n +/, " ").gsub(/\n +/, "\n").strip
491+
end
492+
493+
def see_also
494+
@see_also.map(&:strip)
495+
end
496+
497+
def example
498+
indent = @example.map { |str| str[/\A\s*/].size }.sort.first
499+
@example.map { |str| str[indent..-1] }.join
500+
end
501+
502+
def stack_before
503+
@consumed && @consumed.map(&:strip)
504+
end
505+
506+
def stack_after
507+
@produced && @produced.map(&:strip)
508+
end
509+
510+
def render_format(file)
484511
file.puts %[<h3><a class="instruction" name="#{name}">#{name}(#{arguments})</a></h3>]
485512
end
486513

487-
def stack_effect(file)
514+
def render_stack_effect(file)
488515
c = consumed
489516
p = produced
490517
n = c.size > p.size ? c.size : p.size
@@ -501,13 +528,13 @@ def stack_effect(file)
501528
file.puts "</table>"
502529
end
503530

504-
def description(file)
531+
def render_description(file)
505532
file.puts ""
506533
file.puts @description
507534
file.puts ""
508535
end
509536

510-
def example(file)
537+
def render_example(file)
511538
return if @example.empty?
512539

513540
file.puts ""
@@ -516,7 +543,7 @@ def example(file)
516543
file.puts ""
517544
end
518545

519-
def see_also(file)
546+
def render_see_also(file)
520547
return if @see_also.empty?
521548

522549
file.puts "\n<h4>See Also</h4>"
@@ -528,7 +555,7 @@ def see_also(file)
528555
file.puts "</ul>"
529556
end
530557

531-
def notes(file)
558+
def render_notes(file)
532559
return if @notes.empty?
533560

534561
file.puts ""
@@ -546,12 +573,12 @@ def arguments
546573
end
547574

548575
def render(file)
549-
format file
550-
description file
551-
stack_effect file
552-
example file
553-
notes file
554-
see_also file
576+
render_format file
577+
render_description file
578+
render_stack_effect file
579+
render_example file
580+
render_notes file
581+
render_see_also file
555582
end
556583
end
557584

@@ -577,10 +604,39 @@ def initialize(parser, header, doc)
577604
@doc = InstructionDocumentation.new(self).parse(doc)
578605
@extra = nil
579606
@produced_extra = nil
607+
@produced_times = nil
580608
@bytecode = self.class.bytecode
581609
@control_flow = :next
582610
end
583611

612+
def representation(section)
613+
doc = { section: section, description: @doc.description }
614+
doc[:stack_before] = @doc.stack_before if @doc.stack_before
615+
doc[:stack_after] = @doc.stack_after if @doc.stack_after
616+
doc[:notes] = @doc.notes if @doc.notes && !@doc.notes.empty?
617+
doc[:see_also] = @doc.see_also if @doc.see_also && !@doc.see_also.empty?
618+
doc[:example] = @doc.example if @doc.example && !@doc.example.empty?
619+
620+
consume = { static: static_read_effect }
621+
consume[:extra] = @extra if @extra && @extra != 0
622+
623+
produce = { static: static_write_effect }
624+
produce[:extra] = @produced_extra if @produced_extra && @produced_extra != 0
625+
produce[:times] = @produced_times if @produced_times && @produced_times != 0
626+
627+
spec = {}
628+
spec[:arguments] = @arguments if @arguments.any?
629+
spec[:stack_effect] = { consume: consume, produce: produce }
630+
spec[:control_flow] = @control_flow
631+
632+
{
633+
opcode: bytecode,
634+
name: name,
635+
doc: doc,
636+
spec: spec,
637+
}
638+
end
639+
584640
def parse
585641
parse_header
586642
parse_body
@@ -994,4 +1050,24 @@ def generate_documentation(filename)
9941050
end
9951051
end
9961052
end
1053+
1054+
def generate_json(filename)
1055+
File.open filename, "wb" do |file|
1056+
result = { defines: {}, instructions: [] }
1057+
current_section = nil
1058+
1059+
objects.each do |obj|
1060+
case obj
1061+
when Define
1062+
result[:defines][obj.name] = obj.value
1063+
when Section
1064+
current_section = obj.heading
1065+
when Instruction
1066+
result[:instructions] << obj.representation(current_section)
1067+
end
1068+
end
1069+
1070+
file.puts JSON.pretty_generate result
1071+
end
1072+
end
9971073
end

‎rakelib/vm.rake

+4
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,10 @@ file "vm/gen/instruction_effects.hpp" => insn_deps do |t|
312312
generate_instruction_file iparser, :generate_stack_effects, t.name
313313
end
314314

315+
file "vm/gen/instructions.json" => insn_deps do |t|
316+
generate_instruction_file iparser, :generate_json, t.name
317+
end
318+
315319
namespace :vm do
316320
desc 'Run all VM tests. Uses its argument as a filter of tests to run.'
317321
task :test, :filter do |task, args|

0 commit comments

Comments
 (0)