Add mrbdoc - first draft

This commit is contained in:
Daniel Bovensiepen
2013-06-23 17:37:39 +08:00
parent 0a8381b7a0
commit 52336e5408
6 changed files with 2022 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/env ruby
c_dir = File.dirname(__FILE__)
MRUBY_ROOT = File.expand_path("#{c_dir}/../..")
DOC_DIR = File.expand_path(c_dir)
puts `#{DOC_DIR}/mrbdoc/mrbdoc.rb #{MRUBY_ROOT} #{DOC_DIR}`
Binary file not shown.
+215
View File
@@ -0,0 +1,215 @@
class MRBDoc
SRC_DIR = 'src'
MRBLIB_DIR = 'mrblib'
def analyze_code dir, &block
@mrb_files = {}
@dir = File.expand_path(dir)
block.call "MRBDOC\tStart Analyzing Source of #{@dir}"
analyze(dir) do |progress|
block.call progress
end
block.call "MRBDOC\tFinish Analyzing Source"
end
def each_file(&block); @mrb_files.each {|k,v| block.call k,v}; end
def find_c_func(c_func_name)
each_file do |file_name, file|
c_func = file.c_funcs(c_func_name)
return c_func unless c_func.nil?
end
{}
end
def find_c_file(rb_obj_name, c_func_name)
last_file_name_match = ''
each_file do |file_name, file|
c_func = file.c_funcs(c_func_name)
if c_func and file.rb_class(rb_obj_name) or file.rb_module(rb_obj_name)
return file_name
elsif c_func
last_file_name_match = file_name
end
end
last_file_name_match
end
def find_c_file_by_class(name)
each_file do |file_name, file|
rb_class = file.rb_class(name)
return file_name unless rb_class.nil?
end
'nil'
end
def find_c_file_by_module(name)
each_file do |file_name, file|
rb_module = file.rb_module(name)
return file_name unless rb_module.nil?
end
'nil'
end
private
def analyze dir, &block
collect_all_files dir, &block
end
def collect_all_files dir, &block
l = lambda {|f| block.call " - #{f.name}"}
collect_files(src_code_dir(dir), /\.c$/, &l)
collect_files(mrb_code_dir(dir), /\.rb$/, &l)
end
def collect_files dir, rxp, &block
Dir.foreach(dir) do |file|
next unless file =~ rxp
file_path = "#{dir}/#{file}"
mrb_file = MRBFile.new "#{file_path}"
@mrb_files["#{file_path}"] = mrb_file
block.call mrb_file
end
end
def src_code_dir dir; File.expand_path SRC_DIR, dir; end
def mrb_code_dir dir; File.expand_path MRBLIB_DIR, dir; end
end
class MRBFile
attr_reader :name
attr_reader :file
def initialize mrb_file
@file = mrb_file
@name = File.basename file
@c_funcs = {}
@rb_class_c_def = {}
@rb_method_c_def = {}
@rb_class_method_c_def = {}
@rb_module_c_def = {}
@last_line = nil
@assignments = {}
analyze
end
def each_class &block
@rb_class_c_def.each do |class_name, class_hsh|
block.call class_name, class_hsh
end
end
def each_method name, &block
@rb_method_c_def.each do |met_name, met_hsh|
met_name_tmp = met_name.sub /^#{name}_/, ''
block.call met_name_tmp, met_hsh if met_hsh[:rb_class] == name
end
end
def each_class_method name, &block
@rb_class_method_c_def.each do |met_name, met_hsh|
met_name_tmp = met_name.sub /^#{name}_/, ''
block.call met_name_tmp, met_hsh if met_hsh[:rb_class] == name
end
end
def each_module &block
@rb_module_c_def.each_key do |module_name|
block.call module_name
end
end
def each_core_object &block
each_class {|n| block.call n}
each_module {|n| block.call n}
end
def c_funcs c_func_name; @c_funcs[c_func_name]; end
def rb_class rb_class_name; @rb_class_c_def[rb_class_name]; end
def rb_module rb_module_name; @rb_module_c_def[rb_module_name]; end
private
def analyze
File.open(file).each_line.each_with_index do |line, idx|
line_no = idx.succ
if c_file?
analyze_c_line line, line_no
elsif rb_file?
analyze_rb_line line, line_no
else
raise ArgumentError.new "#{file} is a not supported file type"
end
@last_line = line.strip
end
end
def c_file?; (name =~ /\.c$/); end
def rb_file?; (name =~ /\.rb$/); end
RXP_C_VAR = /\s*([^\s]*?)\s*?/
RXP_C_STR = /\s*?\"(.*?)\"\s*?/
#RXP_C_ISO = /\s*\;\s*[\/\*]*\s*.*?([15\.]{0,3}[0-9\.]*)\s*[\\\\\*]*/
RXP_C_ISO = /\s*;\s*[\/\*]*[\sa-zA-Z]*([\d\.]*)[\sa-zA-Z]*[\*\/]*/
def analyze_c_line line, line_no
case line.strip
when /^([a-zA-Z\_][a-zA-Z\_0-9]*?)\((.*?)\)\s*?$/
# assuming c method definition
@c_funcs[$1] = {:line_no => line_no, :args => $2, :return => @last_line}
when /mrb_define_class\(.*?\,#{RXP_C_STR}\,#{RXP_C_VAR}\)#{RXP_C_ISO}/
# assuming ruby class definition in c
class_name = $1.clone
iso = $3.clone
iso.strip!
@rb_class_c_def[class_name] = {:c_object => $2, :iso => iso}
assigns = line.split '='
if assigns.size > 1
assigns[0..-2].each do |v|
@assignments[v.strip] = class_name
end
end
when /mrb_define_module\(.*?\,#{RXP_C_STR}\)#{RXP_C_ISO}/
# assuming ruby class definition in c
module_name = $1.clone
iso = $2.clone
iso.strip!
@rb_module_c_def[module_name] = {:iso => iso}
assigns = line.split '='
if assigns.size > 1
assigns[0..-2].each do |v|
@assignments[v.strip] = module_name
end
end
when /mrb_define_method\(.*?\,#{RXP_C_VAR}\,#{RXP_C_STR}\,#{RXP_C_VAR}\,#{RXP_C_VAR}\)#{RXP_C_ISO}/
# assuming ruby method definition in c
name = $1.clone
name = resolve_obj(name)
iso = $5.clone
iso.strip!
@rb_method_c_def["#{name}_#{$2}"] = {:c_func => $3, :args => $4, :rb_class => name, :iso => iso}
when /mrb_define_class_method\(.*?\,#{RXP_C_VAR}\,#{RXP_C_STR}\,#{RXP_C_VAR}\,#{RXP_C_VAR}\)#{RXP_C_ISO}/
# assuming ruby class method definition in c
class_name = $1.clone
class_name = resolve_obj(class_name)
iso = $5.clone
iso.strip!
@rb_class_method_c_def["#{class_name}_#{$2}"] = {:c_func => $3, :args => $4, :rb_class => class_name, :iso => iso}
end
end
def analyze_rb_line line, line_no
end
def resolve_obj c_var
@assignments[c_var]
end
end
+116
View File
@@ -0,0 +1,116 @@
class MRBDoc
DOC_DIR = 'language'
def write_documentation dir, &block
block.call "MRBDOC\tStart Building Documentation to #{doc_dir(dir)}"
write(dir) do |progress|
block.call progress
end
block.call "MRBDOC\tFinish Building Documentation"
end
private
def write dir
# io = STDOUT
File.open(File.expand_path('Core_Classes.md', dir), 'w+') do |io|
print_core_classes(io)
print_core_modules(io)
end
end
def get_core_list id
core_list = {}
each_file do |file_path, mrb_file|
mrb_file.send(id) do |name, cls_hsh|
core_list[name] = {:data => cls_hsh, :methods => {}, :class_methods => {}}
mrb_file.each_method name do |met_name, met_hsh|
core_list[name][:methods][met_name] = met_hsh
end
mrb_file.each_class_method name do |met_name, met_hsh|
core_list[name][:class_methods][met_name] = met_hsh
end
end
end
core_list
end
def print_core_classes(io)
core_list = get_core_list :each_class
io.puts "# Core Classes\n\n"
core_list.sort.each do |name, hsh|
file = find_c_file_by_class(name)
file = file.split("#{@dir}/")[1]
iso = hsh[:data][:iso]
iso = 'n/a' if iso.nil?
io.puts <<CLASS
## #{name}
ISO Code | Mixins | Source File
--- | --- | ---
#{hsh[:data][:iso]} | n/a | #{file}
CLASS
print_class_methods(io, hsh)
print_methods(io, hsh)
end
end
def print_core_modules(io)
core_list = get_core_list :each_module
io.puts "# Core Modules\n\n"
core_list.sort.each do |name, hsh|
file = find_c_file_by_module(name)
file = file.split("#{@dir}/")[1]
iso = hsh[:iso]
iso = 'n/a' if iso.nil?
io.puts <<CLASS
## #{name}
ISO Code | Source File
--- | ---
#{iso} | #{file}
CLASS
print_class_methods(io, hsh)
print_methods(io, hsh)
end
end
def print_methods(io, hsh)
return unless hsh[:methods].size > 0
io.puts "### Methods\n\n"
hsh[:methods].sort.each do |met_name, met_hsh|
print_method(io, met_name, met_hsh)
end
end
def print_class_methods(io, hsh)
return unless hsh[:class_methods].size > 0
io.puts "### Class Methods\n\n"
hsh[:class_methods].sort.each do |met_name, met_hsh|
print_method(io, met_name, met_hsh)
end
end
def print_method(io, met_name, met_hsh)
line_no = find_c_func(met_hsh[:c_func])[:line_no]
file = find_c_file(met_hsh[:rb_class], met_hsh[:c_func])
file = file.split("#{@dir}/")[1]
io.puts <<METHOD
#### #{met_name}
ISO Code | Source File | C Function | Line
--- | --- | ---
#{met_hsh[:iso]} | #{file} | #{met_hsh[:c_func]} | #{line_no}
METHOD
end
def doc_dir dir; File.expand_path DOC_DIR, dir; end
end
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/env ruby
$: << File.dirname(__FILE__) + '/lib'
require 'mrbdoc_analyze'
require 'mrbdoc_docu'
MRUBY_ROOT = ARGV[0]
DOC_ROOT = ARGV[1]
raise ArgumentError.new 'mruby root missing!' if MRUBY_ROOT.nil?
raise ArgumentError.new 'doc root missing!' if DOC_ROOT.nil?
mrbdoc = MRBDoc.new
mrbdoc.analyze_code MRUBY_ROOT do |progress|
puts progress
end
mrbdoc.write_documentation DOC_ROOT do |progress|
puts progress
end