summaryrefslogtreecommitdiffhomepage
path: root/tasks
diff options
context:
space:
mode:
Diffstat (limited to 'tasks')
-rw-r--r--tasks/presym.rake141
1 files changed, 141 insertions, 0 deletions
diff --git a/tasks/presym.rake b/tasks/presym.rake
new file mode 100644
index 000000000..20adb7064
--- /dev/null
+++ b/tasks/presym.rake
@@ -0,0 +1,141 @@
+op_table = {
+ "!" => "not",
+ "!=" => "neq",
+ "!~" => "nmatch",
+ "%" => "mod",
+ "&" => "and",
+ "&&" => "andand",
+ "*" => "mul",
+ "**" => "pow",
+ "+" => "add",
+ "+@" => "plus",
+ "-" => "sub",
+ "-@" => "minus",
+ "/" => "div",
+ "<" => "lt",
+ "<=" => "le",
+ "<<" => "lshift",
+ "<=>" => "cmp",
+ "==" => "eq",
+ "===" => "eqq",
+ "=~" => "match",
+ ">" => "gt",
+ ">=" => "ge",
+ ">>" => "rshift",
+ "[]" => "aref",
+ "[]=" => "aset",
+ "^" => "xor",
+ "`" => "tick",
+ "|" => "or",
+ "||" => "oror",
+ "~" => "neg",
+}
+macro_to_symbol = {
+# Macro Symbol
+# [prefix, suffix] => [prefix, suffix]
+ ["CV" , "" ] => ["@@" , "" ],
+ ["IV" , "" ] => ["@" , "" ],
+ ["" , "_B" ] => ["" , "!" ],
+ ["" , "_Q" ] => ["" , "?" ],
+ ["" , "_E" ] => ["" , "=" ],
+ ["" , "" ] => ["" , "" ],
+}
+
+core_cfiles = nil
+core_rbfiles = nil
+MRuby.each_target do |build|
+ core_cfiles ||= Dir.glob("#{MRUBY_ROOT}/src/*.c")
+ core_rbfiles ||= Dir.glob("#{MRUBY_ROOT}/mrblib/*.rb")
+ cfiles = core_cfiles.dup
+ rbfiles = core_rbfiles.dup
+ psfiles = []
+ presym_file = build.presym_file
+ presym_inc = build.presym_inc
+
+ build.compilers.each {|c| c.include_paths << "#{build.build_dir}/include"}
+ build.gems.each do |gem|
+ cfiles.concat(Dir.glob(gem.dir+"/{src,core}/*.c"))
+ if gem.cdump?
+ rbfiles.concat(gem.rbfiles)
+ psfiles.concat(Dir.glob(gem.dir+"/**/presym"))
+ gem.compilers.each {|c| c.include_paths << "#{build.build_dir}/include"}
+ end
+ end
+
+ file presym_file => [*cfiles, *rbfiles, *psfiles, __FILE__] do
+ prefix_re = Regexp.union(*macro_to_symbol.keys.uniq.map(&:first))
+ suffix_re = Regexp.union(*macro_to_symbol.keys.uniq.map(&:last))
+ macro_re = /MRB_(#{prefix_re})SYM(#{suffix_re})\((\w+)\)/o
+ csymbols = cfiles.map do |f|
+ src = File.read(f)
+ src.gsub!(/\/\/.+(\n|$)/, "\n")
+ [src.scan(/intern_lit\([^\n"]*"([^\n "]*)"/),
+ src.scan(/mrb_define_method\([^\n"]*"([^\n"]*)"/),
+ src.scan(/mrb_define_class_method\([^\n"]*"([^\n"]*)"/),
+ src.scan(/mrb_define_class\([^\n"]*"([^\n"]*)"/),
+ src.scan(/mrb_define_module\([^\n"]*"([^\n"]*)"/),
+ src.scan(/mrb_define_module_function\([^\n"]*"([^\n"]*)"/),
+ src.scan(/mrb_define_const\([^\n"]*"([^\n"]*)"/),
+ src.scan(/mrb_define_global_const\([^\n"]*"([^\n"]*)"/),
+ src.scan(macro_re).map{|prefix, suffix, name|
+ macro_to_symbol[[prefix, suffix]] * name
+ }]
+ end
+ csymbols += File.readlines("#{MRUBY_ROOT}/include/mruby.h").grep(/define E_/).join.scan(/MRB_SYM\((\w+)\)/)
+
+ rbsymbols = rbfiles.map do |f|
+ src = File.read(f)
+ src.force_encoding(Encoding::BINARY)
+ [src.scan(/\bclass +([A-Z]\w*)/),
+ src.scan(/\bmodule +([A-Z]\w*)/),
+ src.scan(/\bdef +(\w+[!?=]?)/),
+ src.scan(/\balias +(\w+[!?]?)/),
+ src.scan(/\b([A-Z]\w*) *=[^=]/),
+ src.scan(/(\$[a-zA-Z_]\w*)/),
+ src.scan(/(\$[$!?0-9]\w*)/),
+ src.scan(/(@@?[a-zA-Z_]\w*)/),
+ src.scan(/[^.]\.([a-zA-Z_]\w*[!?]?)/),
+ src.scan(/\.([a-zA-Z_]\w* *=)/).map{|x|x.map{|s|s.gsub(' ', '')}},
+ src.scan(/\b([a-zA-Z_]\w*):/),
+ src.scan(/:([a-zA-Z_]\w*[!?=]?)/),
+ src.scan(/[\(\[\{ ]:"([^"]+)"/).map{|x|x.map{|s|s.gsub('\#', '#')}},
+ src.scan(/[ \(\[\{]:'([^']+)'/)
+ ]
+ end
+ symbols = [csymbols, rbsymbols, op_table.keys, psfiles.map{|file| symbols.concat(File.readlines(file).grep_v(/^# /))}]
+ symbols = symbols.flatten.compact.uniq.grep_v(/#/).map{|x| x.gsub("\n", '\n')}.sort_by!{|x| [x.bytesize, x]}
+ presyms = File.readlines(presym_file) rescue []
+ presyms.each{|x| x.chomp!}
+ if presyms != symbols
+ _pp "GEN", presym_file.relative_path
+ mkdir_p(File.dirname(presym_file))
+ File.write(presym_file, symbols.join("\n"))
+ Rake::Task["gensym:#{presym_inc}"].invoke
+ end
+ end
+
+ task "gensym:#{presym_inc}" do
+ presyms = File.readlines(presym_file)
+ presyms.each{|x| x.chomp!}
+ symbol_to_macro = macro_to_symbol.invert
+ prefix_re = Regexp.union(*symbol_to_macro.keys.uniq.map(&:first))
+ suffix_re = Regexp.union(*symbol_to_macro.keys.uniq.map(&:last))
+ macro_re = /\A(#{prefix_re})?([\w&&\D]\w*)(#{suffix_re})?\z/o
+ mkdir_p(File.dirname(presym_inc))
+ _pp "GEN", presym_inc.relative_path
+ File.open(presym_inc, "w") do |f|
+ f.puts "/* MRB_PRESYM_NAMED(lit, num, type, name) */"
+ f.puts "/* MRB_PRESYM_UNNAMED(lit, num) */"
+ presyms.each.with_index(1) do |sym, num|
+ if macro_re =~ sym && (affixes = symbol_to_macro[[$1, $3]])
+ f.puts %|MRB_PRESYM_NAMED("#{sym}", #{num}, #{affixes * 'SYM'}, #{$2})|
+ elsif name = op_table[sym]
+ f.puts %|MRB_PRESYM_NAMED("#{sym}", #{num}, OPSYM, #{name})|
+ elsif
+ f.puts %|MRB_PRESYM_UNNAMED("#{sym}", #{num})|
+ end
+ end
+ f.print "#define MRB_PRESYM_MAX #{presyms.size}"
+ end
+ end
+end