From 5e6299074846ff838590b8eeceb6b59862bce4c0 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 20 Nov 2022 21:58:13 +0900 Subject: [PATCH] Add task `rake doc:update-opcode.md` Allow to update `doc/internal/opcode.md` file mechanically from `include/mruby/ops.h` file. At the same time, the `doc/internal/opcode.md` file has been updated. Consecutive hyphens at the end of the table were removed as they would have created noise as markdown flavours. --- doc/internal/opcode.md | 16 ++++++++------ lib/mruby/doc.rb | 49 ++++++++++++++++++++++++++++++++++++++++++ tasks/doc.rake | 14 ++++++++++++ 3 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 lib/mruby/doc.rb diff --git a/doc/internal/opcode.md b/doc/internal/opcode.md index 41c1a542f..d93d018d4 100644 --- a/doc/internal/opcode.md +++ b/doc/internal/opcode.md @@ -59,6 +59,8 @@ sign) of operands. | `OP_SETMCNST` | `BB` | `R(a+1)::Syms(b) = R(a)` | | `OP_GETUPVAR` | `BBB` | `R(a) = uvget(b,c)` | | `OP_SETUPVAR` | `BBB` | `uvset(b,c,R(a))` | +| `OP_GETIDX` | `B` | `R(a) = R(a)[R(a+1)]` | +| `OP_SETIDX` | `B` | `R(a)[R(a+1)] = R(a+2)` | | `OP_JMP` | `S` | `pc+=a` | | `OP_JMPIF` | `BS` | `if R(a) pc+=b` | | `OP_JMPNOT` | `BS` | `if !R(a) pc+=b` | @@ -67,8 +69,10 @@ sign) of operands. | `OP_EXCEPT` | `B` | `R(a) = exc` | | `OP_RESCUE` | `BB` | `R(b) = R(a).isa?(R(b))` | | `OP_RAISEIF` | `B` | `raise(R(a)) if R(a)` | -| `OP_SEND` | `BBB` | `R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))` | -| `OP_SENDB` | `BBB` | `R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c),&R(a+c+1))` | +| `OP_SSEND` | `BBB` | `R(a) = self.send(Syms(b),R(a+1)..,R(a+n+1):R(a+n+2)..) (c=n|k<<4)` | +| `OP_SSENDB` | `BBB` | `R(a) = self.send(Syms(b),R(a+1)..,R(a+n+1):R(a+n+2)..,&R(a+n+2k+1))` | +| `OP_SEND` | `BBB` | `R(a) = R(a).send(Syms(b),R(a+1)..,R(a+n+1):R(a+n+2)..) (c=n|k<<4)` | +| `OP_SENDB` | `BBB` | `R(a) = R(a).send(Syms(b),R(a+1)..,R(a+n+1):R(a+n+2)..,&R(a+n+2k+1))` | | `OP_CALL` | `-` | `R(0) = self.call(frame.argc, frame.argv)` | | `OP_SUPER` | `BB` | `R(a) = super(R(a+1),... ,R(a+b+1))` | | `OP_ARGARY` | `BS` | `R(a) = argument array (16=m5:r1:m5:d1:lv4)` | @@ -100,6 +104,7 @@ sign) of operands. | `OP_ASET` | `BBB` | `R(b)[c] = R(a)` | | `OP_APOST` | `BBB` | `*R(a),R(a+1)..R(a+c) = R(a)[b..]` | | `OP_INTERN` | `B` | `R(a) = intern(R(a))` | +| `OP_SYMBOL` | `BB` | `R(a) = intern(Pool(b))` | | `OP_STRING` | `BB` | `R(a) = str_dup(Pool(b))` | | `OP_STRCAT` | `B` | `str_cat(R(a),R(a+1))` | | `OP_HASH` | `BB` | `R(a) = hash_new(R(a),R(a+1)..R(a+b*2-1))` | @@ -113,7 +118,7 @@ sign) of operands. | `OP_OCLASS` | `B` | `R(a) = ::Object` | | `OP_CLASS` | `BB` | `R(a) = newclass(R(a),Syms(b),R(a+1))` | | `OP_MODULE` | `BB` | `R(a) = newmodule(R(a),Syms(b))` | -| `OP_EXEC` | `BB` | `R(a) = blockexec(R(a),Irep[b])` | +| `OP_EXEC` | `BB` | `R(a) = blockexec(R(a),Irep(b))` | | `OP_DEF` | `BB` | `R(a).newmethod(Syms(b),R(a+1)); R(a) = Syms(b)` | | `OP_ALIAS` | `BB` | `alias_method(target_class,Syms(a),Syms(b))` | | `OP_UNDEF` | `B` | `undef_method(target_class,Syms(a))` | @@ -121,8 +126,7 @@ sign) of operands. | `OP_TCLASS` | `B` | `R(a) = target_class` | | `OP_DEBUG` | `BBB` | `print a,b,c` | | `OP_ERR` | `B` | `raise(LocalJumpError, Pool(a))` | -| `OP_EXT1` | `-` | `make 1st operand 16bit` | -| `OP_EXT2` | `-` | `make 2nd operand 16bit` | +| `OP_EXT1` | `-` | `make 1st operand (a) 16bit` | +| `OP_EXT2` | `-` | `make 2nd operand (b) 16bit` | | `OP_EXT3` | `-` | `make 1st and 2nd operands 16bit` | | `OP_STOP` | `-` | `stop VM` | -| ------------------ | -------------- | ---------------------------------------------------------- | diff --git a/lib/mruby/doc.rb b/lib/mruby/doc.rb new file mode 100644 index 000000000..573f71aaa --- /dev/null +++ b/lib/mruby/doc.rb @@ -0,0 +1,49 @@ +autoload :Pathname, 'pathname' + +module MRuby + module Documentation + def Documentation.update_opcode_md + mrubydir = Pathname(MRUBY_ROOT) + path_ops_h = mrubydir + "include/mruby/ops.h" + path_opcode_md = mrubydir + "doc/internal/opcode.md" + + opspecs = { + "Z" => { prefix: "", modified: "-" }, + "B" => { prefix: "\'" }, + "BB" => { prefix: "\"" }, + "BBB" => { prefix: "\"" }, + "BS" => { prefix: "\'" }, + "BSS" => { prefix: "\'" }, + "S" => { prefix: "" }, + "W" => { prefix: "" }, + } + + diff = "" + + spliter = <<~'SPLITER' + | Instruction Name | Operand type | Semantics | + |--------------------|----------------|------------------------------------------------------------| + SPLITER + + diff = path_opcode_md.read.sub(/^#{Regexp.escape spliter}.*?(?=\z|^$\n)/m) do + repl = spliter + + ops = path_ops_h.read + ops.scan(/^\s*OPCODE\s*\(\s*(\w+)\s*,\s*(\w+)\s*\)\s*(?:\/\*\s*(.*?)\s*\*\/\s*)?/).each do |ins, opr, cmt| + if cmt + cmt.sub!(/\s*#.*/, "") + cmt.sub!(/\b(?=L_\w+\b)/, "OP_") + cmt.gsub!(/\b(Irep|Pool|R|Syms)\[([^\[\]]+)\]/, "\\1(\\2)") + end + spec = opspecs[opr] or raise "unknown operand type: #{opr}" + item = format(%(| %-18s | %-14s | %-58s |\n), "`OP_#{ins}`", "`#{spec[:modified] || opr}`", cmt && "`#{cmt}`") + repl << item + end + + repl + end + + path_opcode_md.binwrite diff + end + end +end diff --git a/tasks/doc.rake b/tasks/doc.rake index 353c42d9d..5f21c1118 100644 --- a/tasks/doc.rake +++ b/tasks/doc.rake @@ -1,3 +1,5 @@ +MRuby.autoload :Documentation, 'mruby/doc' + desc 'generate document' task :doc => %w[doc:api doc:capi] @@ -61,6 +63,18 @@ namespace :doc do end end end + + desc 'update doc/internal/opcode.md' + task 'update-opcode.md' do + unless system(*%W(git --git-dir #{MRUBY_ROOT}/.git --work-tree #{MRUBY_ROOT} diff --quiet @ -- doc/internal/opcode.md)) + abort <<~'ERRMESG' + The file "doc/internal/opcode.md" has been modified but not committed. + To avoid loss of your edits, the automatic update process has been aborted. + ERRMESG + end + + MRuby::Documentation.update_opcode_md + end end # deprecated