2014-11-11 12:09:14 +03:00
|
|
|
<%
|
2007-11-10 19:33:30 +03:00
|
|
|
# This file is interpreted by $(BASERUBY) and miniruby.
|
2007-11-15 05:54:55 +03:00
|
|
|
# $(BASERUBY) is used for miniprelude.c.
|
|
|
|
# miniruby is used for prelude.c.
|
2007-11-10 19:33:30 +03:00
|
|
|
# Since $(BASERUBY) may be older than Ruby 1.9,
|
|
|
|
# Ruby 1.9 feature should not be used.
|
|
|
|
|
2020-08-11 05:40:37 +03:00
|
|
|
require_relative '../tool/ruby_vm/helpers/c_escape'
|
|
|
|
|
2010-03-12 01:15:11 +03:00
|
|
|
class Prelude
|
2020-08-11 05:40:37 +03:00
|
|
|
include RubyVM::CEscape
|
2017-12-01 06:54:50 +03:00
|
|
|
LINE_LIMIT = 509 # by C89
|
|
|
|
|
2010-03-12 01:15:11 +03:00
|
|
|
def prelude_base(filename)
|
2014-11-11 12:09:14 +03:00
|
|
|
filename.chomp(".rb")
|
2010-03-12 01:15:11 +03:00
|
|
|
end
|
|
|
|
def prelude_name(filename)
|
|
|
|
"<internal:" + prelude_base(filename) + ">"
|
|
|
|
end
|
2007-08-24 19:26:28 +04:00
|
|
|
|
2019-11-09 12:44:06 +03:00
|
|
|
def initialize(output, preludes, vpath)
|
|
|
|
@output = output
|
2010-03-12 01:15:11 +03:00
|
|
|
@have_sublib = false
|
2014-11-11 12:09:14 +03:00
|
|
|
@vpath = vpath
|
2019-11-09 13:28:45 +03:00
|
|
|
@prelude_count = 0
|
|
|
|
@builtin_count = 0
|
2010-03-12 01:15:11 +03:00
|
|
|
@preludes = {}
|
2019-11-09 13:28:45 +03:00
|
|
|
@mains = preludes.map do |filename|
|
2019-12-10 10:19:13 +03:00
|
|
|
if prelude = filename.end_with?("golf_prelude.rb")
|
2019-11-09 13:28:45 +03:00
|
|
|
@prelude_count += 1
|
|
|
|
else
|
|
|
|
@builtin_count += 1
|
|
|
|
end
|
|
|
|
translate(filename, (filename unless prelude))[0]
|
|
|
|
end
|
2014-11-11 12:09:14 +03:00
|
|
|
@preludes.delete_if {|_, (_, _, lines, sub)| sub && lines.empty?}
|
2010-03-12 01:15:11 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
def translate(filename, sub = false)
|
|
|
|
idx = @preludes[filename]
|
|
|
|
return idx if idx
|
|
|
|
lines = []
|
2021-06-06 16:45:37 +03:00
|
|
|
start_line = nil
|
|
|
|
lineno = 0
|
2014-11-19 04:08:00 +03:00
|
|
|
result = [@preludes.size, @vpath.strip(filename), lines, sub]
|
2014-11-11 12:09:14 +03:00
|
|
|
@vpath.foreach(filename) do |line|
|
2019-04-19 13:45:16 +03:00
|
|
|
line.force_encoding("ASCII-8BIT") if line.respond_to?(:force_encoding)
|
2021-06-06 16:45:37 +03:00
|
|
|
line.rstrip!
|
|
|
|
lineno += 1
|
2014-11-11 12:09:14 +03:00
|
|
|
@preludes[filename] ||= result
|
2017-12-01 06:54:50 +03:00
|
|
|
comment = ($1 || '' if line.sub!(/(?:^|\s+)\#(?:$|[#\s](.*))/, ''))
|
2021-06-06 16:45:37 +03:00
|
|
|
if !line.empty? or start_line
|
|
|
|
line << "\n"
|
|
|
|
start_line ||= lineno
|
|
|
|
end
|
2017-12-01 06:54:50 +03:00
|
|
|
if line.size > LINE_LIMIT
|
|
|
|
raise "#{filename}:#{lines.size+1}: too long line"
|
|
|
|
end
|
2014-12-04 02:25:01 +03:00
|
|
|
line.sub!(/require(_relative)?\s*\(?\s*(["'])(.*?)(?:\.rb)?\2\)?/) do
|
|
|
|
orig, rel, path = $&, $2, $3
|
|
|
|
if rel
|
|
|
|
path = File.join(File.dirname(filename), path)
|
|
|
|
nil while path.gsub!(%r'(\A|/)(?!\.\.?/)[^/]+/\.\.(?:/|\z)', '')
|
|
|
|
end
|
|
|
|
path = translate("#{path}.rb", true) rescue nil
|
2014-11-11 12:09:14 +03:00
|
|
|
if path
|
2010-03-12 01:15:11 +03:00
|
|
|
@have_sublib = true
|
2014-11-11 12:09:14 +03:00
|
|
|
"TMP_RUBY_PREFIX.require(#{path[0]})"
|
2010-03-12 01:15:11 +03:00
|
|
|
else
|
|
|
|
orig
|
2009-07-31 10:09:13 +04:00
|
|
|
end
|
2009-07-30 18:12:25 +04:00
|
|
|
end
|
2017-12-01 06:54:50 +03:00
|
|
|
lines << [line, comment]
|
2009-07-31 10:09:13 +04:00
|
|
|
end
|
2021-06-06 16:45:37 +03:00
|
|
|
result << (start_line || 1)
|
2010-03-12 01:15:11 +03:00
|
|
|
result
|
2007-11-15 05:54:55 +03:00
|
|
|
end
|
2014-11-11 12:09:14 +03:00
|
|
|
end
|
2019-11-09 13:15:10 +03:00
|
|
|
Prelude.new(output, ARGV, vpath).instance_eval do
|
2014-11-11 12:09:14 +03:00
|
|
|
-%>
|
2009-07-30 18:12:25 +04:00
|
|
|
/* -*-c-*-
|
2014-11-11 12:09:14 +03:00
|
|
|
THIS FILE WAS AUTOGENERATED BY template/prelude.c.tmpl. DO NOT EDIT.
|
2009-07-30 18:12:25 +04:00
|
|
|
|
2017-12-01 06:54:50 +03:00
|
|
|
sources: <%= @preludes.map {|n,*| prelude_base(n)}.join(', ') %><%=%>
|
2009-07-30 18:12:25 +04:00
|
|
|
*/
|
2014-11-27 11:10:21 +03:00
|
|
|
%unless @preludes.empty?
|
* internal.h: declare internal functions here.
* node.h: declare NODE dependent internal functions here.
* iseq.h: declare rb_iseq_t dependent internal functions here.
* vm_core.h: declare rb_thread_t dependent internal functions here.
* bignum.c, class.c, compile.c, complex.c, cont.c, dir.c, encoding.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c, io.c,
iseq.c, load.c, marshal.c, math.c, numeric.c, object.c, parse.y,
proc.c, process.c, range.c, rational.c, re.c, ruby.c, string.c,
thread.c, time.c, transcode.c, variable.c, vm.c,
tool/compile_prelude.rb: don't declare internal functions declared
in above headers. include above headers if required.
Note that rb_thread_mark() was declared as
void rb_thread_mark(rb_thread_t *th) in cont.c but defined as
void rb_thread_mark(void *ptr) in vm.c. Now it is declared as
the later in internal.h.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32156 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-06-18 02:43:38 +04:00
|
|
|
#include "internal.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "internal/warnings.h"
|
2015-11-12 10:16:23 +03:00
|
|
|
#include "iseq.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "ruby/ruby.h"
|
|
|
|
#include "vm_core.h"
|
2007-08-25 03:49:19 +04:00
|
|
|
|
2020-08-11 05:45:54 +03:00
|
|
|
COMPILER_WARNING_PUSH
|
|
|
|
#if __has_warning("-Wstring-concatenation")
|
|
|
|
COMPILER_WARNING_IGNORED(-Wstring-concatenation)
|
|
|
|
#endif
|
2010-03-12 01:15:11 +03:00
|
|
|
% preludes = @preludes.values.sort
|
|
|
|
% preludes.each {|i, prelude, lines, sub|
|
|
|
|
|
2017-12-25 05:42:13 +03:00
|
|
|
% name = prelude_name(*prelude)
|
2020-08-11 05:40:37 +03:00
|
|
|
static const char prelude_name<%=i%><%=%>[] = <%=rstring2cstr(name)%>;
|
2017-12-01 06:54:50 +03:00
|
|
|
static const struct {
|
|
|
|
% size = beg = 0
|
|
|
|
% lines.each_with_index {|(line, comment), n|
|
|
|
|
% if size + line.size < Prelude::LINE_LIMIT
|
|
|
|
% size += line.size
|
|
|
|
% next
|
|
|
|
% end
|
|
|
|
char L<%=beg%><%=%>[<%=size%><%=%>]; /* <%=beg+1%>..<%=n%> */
|
|
|
|
% size = line.size
|
|
|
|
% beg = n
|
2007-12-21 03:27:40 +03:00
|
|
|
% }
|
2017-12-01 06:54:50 +03:00
|
|
|
% if size > 0
|
|
|
|
char L<%=beg%><%=%>[<%=size%><%=%>]; /* <%=beg+1%>..<%=lines.size+1%> */
|
|
|
|
% end
|
|
|
|
} prelude_code<%=i%><%=%> = {
|
|
|
|
% size = 0
|
2020-08-11 05:40:37 +03:00
|
|
|
#line 1 <%=rstring2cstr(prelude)%>
|
2017-12-01 06:54:50 +03:00
|
|
|
% lines.each_with_index {|(line, comment), n|
|
|
|
|
% if size + line.size >= Prelude::LINE_LIMIT
|
|
|
|
% size = 0
|
|
|
|
,
|
2020-08-11 05:40:37 +03:00
|
|
|
#line <%=n+1%> <%=rstring2cstr(prelude)%>
|
2017-12-01 06:54:50 +03:00
|
|
|
% end
|
|
|
|
% size += line.size
|
2020-08-11 05:40:37 +03:00
|
|
|
<%=rstring2cstr(line)%><%if comment%><%=commentify(comment)%><%end%>
|
2017-12-01 06:54:50 +03:00
|
|
|
% }
|
2019-11-09 12:44:06 +03:00
|
|
|
#line <%=_erbout.count("\n")+2%> "<%=@output%>"
|
2017-12-01 06:54:50 +03:00
|
|
|
};
|
2007-12-21 03:27:40 +03:00
|
|
|
% }
|
2007-08-25 05:20:30 +04:00
|
|
|
|
2020-08-11 05:45:54 +03:00
|
|
|
COMPILER_WARNING_POP
|
|
|
|
|
2014-11-25 18:22:01 +03:00
|
|
|
% if @have_sublib
|
2014-11-27 11:10:21 +03:00
|
|
|
#define PRELUDE_COUNT <%=preludes.size%>
|
|
|
|
|
2010-03-12 01:15:11 +03:00
|
|
|
struct prelude_env {
|
|
|
|
volatile VALUE prefix_path;
|
|
|
|
#if PRELUDE_COUNT > 0
|
|
|
|
char loaded[PRELUDE_COUNT];
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
prelude_prefix_path(VALUE self)
|
|
|
|
{
|
|
|
|
struct prelude_env *ptr = DATA_PTR(self);
|
|
|
|
return ptr->prefix_path;
|
|
|
|
}
|
|
|
|
|
2019-11-09 13:28:45 +03:00
|
|
|
% end
|
2010-04-28 04:49:25 +04:00
|
|
|
% unless preludes.empty?
|
2018-03-19 17:12:00 +03:00
|
|
|
#define PRELUDE_NAME(n) rb_usascii_str_new_static(prelude_name##n, sizeof(prelude_name##n)-1)
|
2019-04-19 13:45:16 +03:00
|
|
|
#define PRELUDE_CODE(n) rb_utf8_str_new_static(prelude_code##n.L0, sizeof(prelude_code##n))
|
2019-11-09 13:28:45 +03:00
|
|
|
|
|
|
|
static rb_ast_t *
|
|
|
|
prelude_ast(VALUE name, VALUE code, int line)
|
|
|
|
{
|
|
|
|
rb_ast_t *ast = rb_parser_compile_string_path(rb_parser_new(), name, code, line);
|
|
|
|
if (!ast->body.root) {
|
|
|
|
rb_ast_dispose(ast);
|
|
|
|
rb_exc_raise(rb_errinfo());
|
|
|
|
}
|
|
|
|
return ast;
|
|
|
|
}
|
|
|
|
|
|
|
|
% end
|
|
|
|
% if @builtin_count > 0
|
2021-06-06 16:45:37 +03:00
|
|
|
#define PRELUDE_AST(n, name_str, start_line) \
|
2019-11-09 13:28:45 +03:00
|
|
|
(((sizeof(prelude_name<%='##'%><%=%>n) - prefix_len - 2) == namelen) && \
|
|
|
|
(strncmp(prelude_name<%='##'%><%=%>n + prefix_len, feature_name, namelen) == 0) ? \
|
2021-06-06 16:45:37 +03:00
|
|
|
prelude_ast((name_str) = PRELUDE_NAME(n), PRELUDE_CODE(n), start_line) : 0)
|
2019-11-09 13:28:45 +03:00
|
|
|
|
|
|
|
rb_ast_t *
|
|
|
|
rb_builtin_ast(const char *feature_name, VALUE *name_str)
|
|
|
|
{
|
|
|
|
const size_t prefix_len = rb_strlen_lit("<internal:");
|
|
|
|
size_t namelen = strlen(feature_name);
|
|
|
|
rb_ast_t *ast = 0;
|
|
|
|
|
2021-06-06 16:45:37 +03:00
|
|
|
% @preludes.each_value do |i, prelude, lines, sub, start_line|
|
2019-11-09 13:28:45 +03:00
|
|
|
% if sub and sub != true
|
2021-06-06 16:45:37 +03:00
|
|
|
if ((ast = PRELUDE_AST(<%=i%><%=%>, *name_str, <%=start_line%>)) != 0) return ast;
|
2019-11-09 13:28:45 +03:00
|
|
|
% end
|
|
|
|
% end
|
|
|
|
return ast;
|
|
|
|
}
|
|
|
|
|
|
|
|
% end
|
|
|
|
% if @prelude_count > 0
|
2018-07-30 10:07:48 +03:00
|
|
|
COMPILER_WARNING_PUSH
|
|
|
|
#if GCC_VERSION_SINCE(4, 2, 0)
|
|
|
|
COMPILER_WARNING_ERROR(-Wmissing-field-initializers)
|
2017-12-25 05:09:14 +03:00
|
|
|
#endif
|
2017-12-26 02:59:56 +03:00
|
|
|
static void
|
|
|
|
prelude_eval(VALUE code, VALUE name, int line)
|
|
|
|
{
|
2015-11-12 10:16:23 +03:00
|
|
|
static const rb_compile_option_t optimization = {
|
|
|
|
TRUE, /* int inline_const_cache; */
|
|
|
|
TRUE, /* int peephole_optimization; */
|
2018-12-12 08:46:13 +03:00
|
|
|
FALSE,/* int tailcall_optimization; */
|
2015-11-12 10:16:23 +03:00
|
|
|
TRUE, /* int specialized_instruction; */
|
|
|
|
TRUE, /* int operands_unification; */
|
|
|
|
TRUE, /* int instructions_unification; */
|
|
|
|
TRUE, /* int stack_caching; */
|
2016-10-18 18:40:31 +03:00
|
|
|
TRUE, /* int frozen_string_literal; */
|
|
|
|
FALSE, /* int debug_frozen_string_literal; */
|
2017-12-25 05:09:14 +03:00
|
|
|
FALSE, /* unsigned int coverage_enabled; */
|
|
|
|
0, /* int debug_level; */
|
2015-11-12 10:16:23 +03:00
|
|
|
};
|
|
|
|
|
2019-11-09 13:28:45 +03:00
|
|
|
rb_ast_t *ast = prelude_ast(name, code, line);
|
2018-01-05 11:59:22 +03:00
|
|
|
rb_iseq_eval(rb_iseq_new_with_opt(&ast->body, name, name, Qnil, INT2FIX(line),
|
2020-10-23 07:27:21 +03:00
|
|
|
NULL, 0, ISEQ_TYPE_TOP, &optimization));
|
2017-10-27 19:44:57 +03:00
|
|
|
rb_ast_dispose(ast);
|
2010-04-28 04:49:25 +04:00
|
|
|
}
|
2018-07-30 10:07:48 +03:00
|
|
|
COMPILER_WARNING_POP
|
2010-04-28 04:49:25 +04:00
|
|
|
|
2019-11-09 13:28:45 +03:00
|
|
|
% end
|
2010-03-12 01:15:11 +03:00
|
|
|
% if @have_sublib
|
|
|
|
static VALUE
|
|
|
|
prelude_require(VALUE self, VALUE nth)
|
|
|
|
{
|
|
|
|
struct prelude_env *ptr = DATA_PTR(self);
|
|
|
|
VALUE code, name;
|
|
|
|
int n = FIX2INT(nth);
|
2021-06-06 16:45:37 +03:00
|
|
|
int start_line;
|
2010-03-12 01:15:11 +03:00
|
|
|
|
|
|
|
if (n > PRELUDE_COUNT) return Qfalse;
|
|
|
|
if (ptr->loaded[n]) return Qfalse;
|
|
|
|
ptr->loaded[n] = 1;
|
|
|
|
switch (n) {
|
2021-06-06 16:45:37 +03:00
|
|
|
% @preludes.each_value do |i, prelude, lines, sub, start_line|
|
2019-11-09 13:28:45 +03:00
|
|
|
% if sub == true
|
2015-09-26 16:33:17 +03:00
|
|
|
case <%=i%><%=%>:
|
2018-03-19 17:12:00 +03:00
|
|
|
code = PRELUDE_CODE(<%=i%><%=%>);
|
|
|
|
name = PRELUDE_NAME(<%=i%><%=%>);
|
2021-06-06 16:45:37 +03:00
|
|
|
start_line = <%=start_line%>;
|
2010-03-12 01:15:11 +03:00
|
|
|
break;
|
|
|
|
% end
|
|
|
|
% end
|
|
|
|
default:
|
|
|
|
return Qfalse;
|
|
|
|
}
|
2021-06-06 16:45:37 +03:00
|
|
|
prelude_eval(code, name, start_line);
|
2010-03-12 01:15:11 +03:00
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
% end
|
2014-11-27 11:10:21 +03:00
|
|
|
%end
|
2019-11-09 12:44:06 +03:00
|
|
|
% init_name = @output && @output[/\w+(?=_prelude.c\b)/] || 'prelude'
|
2007-08-24 19:26:28 +04:00
|
|
|
void
|
2019-11-09 12:44:06 +03:00
|
|
|
Init_<%=init_name%><%=%>(void)
|
2007-08-24 19:26:28 +04:00
|
|
|
{
|
2019-11-09 13:28:45 +03:00
|
|
|
%unless @prelude_count.zero?
|
2014-11-25 18:22:01 +03:00
|
|
|
% if @have_sublib
|
2010-03-12 01:15:11 +03:00
|
|
|
struct prelude_env memo;
|
|
|
|
ID name = rb_intern("TMP_RUBY_PREFIX");
|
2021-12-30 17:32:35 +03:00
|
|
|
VALUE prelude = Data_Wrap_Struct(rb_cObject, 0, 0, &memo);
|
2010-03-12 01:15:11 +03:00
|
|
|
|
|
|
|
memo.prefix_path = rb_const_remove(rb_cObject, name);
|
|
|
|
rb_const_set(rb_cObject, name, prelude);
|
|
|
|
rb_define_singleton_method(prelude, "to_s", prelude_prefix_path, 0);
|
|
|
|
% end
|
|
|
|
% if @have_sublib
|
|
|
|
memset(memo.loaded, 0, sizeof(memo.loaded));
|
|
|
|
rb_define_singleton_method(prelude, "require", prelude_require, 1);
|
|
|
|
% end
|
2021-06-06 16:45:37 +03:00
|
|
|
% preludes.each do |i, prelude, lines, sub, start_line|
|
2010-03-12 01:15:11 +03:00
|
|
|
% next if sub
|
2021-06-06 16:45:37 +03:00
|
|
|
prelude_eval(PRELUDE_CODE(<%=i%><%=%>), PRELUDE_NAME(<%=i%><%=%>), <%=start_line%>);
|
2010-03-12 01:15:11 +03:00
|
|
|
% end
|
2007-08-25 03:49:19 +04:00
|
|
|
|
|
|
|
#if 0
|
2007-12-21 03:27:40 +03:00
|
|
|
% preludes.length.times {|i|
|
2017-12-01 06:54:50 +03:00
|
|
|
printf("%.*s", (int)sizeof(prelude_code<%=i%><%=%>), prelude_code<%=i%><%=%>.L0);
|
2007-12-21 03:27:40 +03:00
|
|
|
% }
|
2007-08-25 03:49:19 +04:00
|
|
|
#endif
|
2014-11-27 11:10:21 +03:00
|
|
|
%end
|
2007-08-24 19:26:28 +04:00
|
|
|
}
|
2014-11-11 12:09:14 +03:00
|
|
|
<%end -%>
|