Skip to content

Instantly share code, notes, and snippets.

@pbevin
Created August 26, 2009 16:52
Show Gist options
  • Save pbevin/175639 to your computer and use it in GitHub Desktop.
Save pbevin/175639 to your computer and use it in GitHub Desktop.
diff --git a/kernel/common/compiled_method.rb b/kernel/common/compiled_method.rb
index df80cc9..338c18a 100644
--- a/kernel/common/compiled_method.rb
+++ b/kernel/common/compiled_method.rb
@@ -198,6 +198,8 @@ module Rubinius
class Script
attr_accessor :path
+ def root_script=(value); @root_script = value; end
+ def root_script?; @root_script; end
end
def as_script(script=nil)
diff --git a/kernel/common/data.rb b/kernel/common/data.rb
new file mode 100644
index 0000000..56901c5
--- /dev/null
+++ b/kernel/common/data.rb
@@ -0,0 +1,6 @@
+module Rubinius
+ def self.set_data(str)
+ require 'stringio'
+ Object.const_set :DATA, StringIO.new(str)
+ end
+end
diff --git a/kernel/common/load_order.txt b/kernel/common/load_order.txt
index cf063c3..f521835 100644
--- a/kernel/common/load_order.txt
+++ b/kernel/common/load_order.txt
@@ -37,6 +37,7 @@ compiled_method.rbc
continuation.rbc
delegated_method.rbc
fixnum.rbc
+data.rbc
dir.rbc
dir_186.rbc
dir_glob.rbc
diff --git a/kernel/common/static_scope.rb b/kernel/common/static_scope.rb
index e4003b1..299c20e 100644
--- a/kernel/common/static_scope.rb
+++ b/kernel/common/static_scope.rb
@@ -74,12 +74,8 @@ module Rubinius
end
def active_path
- scope = self
- while scope and !scope.script
- scope = scope.parent
- end
-
- if scope and script = scope.script
+ script = current_script
+ if script
if path = script.path
return path.dup
end
@@ -88,6 +84,19 @@ module Rubinius
return "__unknown__.rb"
end
+ def root_script?
+ script = current_script
+ return script && script.root_script?
+ end
+
+ def current_script
+ scope = self
+ while scope and !scope.script
+ scope = scope.parent
+ end
+ return scope && scope.script
+ end
+
def const_defined?(name)
scope = self
while scope and scope.module != Object
diff --git a/kernel/compiler/bytecode.rb b/kernel/compiler/bytecode.rb
index 13e40fb..143ad55 100644
--- a/kernel/compiler/bytecode.rb
+++ b/kernel/compiler/bytecode.rb
@@ -1052,6 +1052,27 @@ class Compiler
end
end
+ class EndData
+ def bytecode(g)
+ # if (scope.root_script?)
+ # Rubinius.set_data(...)
+ # end
+ not_root = g.new_label
+ done = g.new_label
+
+ g.push_scope
+ g.send :root_script?, 0
+ g.gif not_root
+ g.push_const(:Rubinius)
+ g.push_literal(data)
+ g.send :set_data, 1
+ g.goto done
+ not_root.set!
+ g.push_nil
+ done.set!
+ end
+ end
+
class Ensure
def bytecode(g)
pos(g)
diff --git a/kernel/compiler/compile.rb b/kernel/compiler/compile.rb
index a9b47f2..e5ffb86 100644
--- a/kernel/compiler/compile.rb
+++ b/kernel/compiler/compile.rb
@@ -243,6 +243,7 @@ class Compiler
end
cm.as_script do |script|
script.path = rb_path
+ script.root_script = options[:root_script]
end
rescue Exception => e
$LOADED_FEATURES.delete(rb) if requiring
diff --git a/kernel/compiler/nodes.rb b/kernel/compiler/nodes.rb
index 97839e1..805a3ed 100644
--- a/kernel/compiler/nodes.rb
+++ b/kernel/compiler/nodes.rb
@@ -989,6 +989,16 @@ raise "no"
kind :zarray
end
+ class EndData < Node
+ kind :end_data
+
+ def args(data)
+ @data = data
+ end
+
+ attr_accessor :data
+ end
+
class Ensure < Node
kind :ensure
diff --git a/kernel/loader.rb b/kernel/loader.rb
index ab74f73..d45b303 100644
--- a/kernel/loader.rb
+++ b/kernel/loader.rb
@@ -317,7 +317,8 @@ module Rubinius
if File.exist?(@script)
$0 = @script
Compiler::Utils.debug_script! if @debugging
- Compiler::Utils.load_from_extension @script, :no_rbc => @no_rbc
+ Compiler::Utils.load_from_extension @script,
+ :no_rbc => @no_rbc, :root_script => true
else
if @script.suffix?(".rb")
puts "Unable to find '#{@script}'"
diff --git a/vm/codegen/node_types.rb b/vm/codegen/node_types.rb
new file mode 100644
index 0000000..5022267
--- /dev/null
+++ b/vm/codegen/node_types.rb
@@ -0,0 +1,191 @@
+node_types = %w{
+ method
+ fbody
+ cfunc
+ scope
+ block
+ if
+ case
+ when
+ opt_n
+ while
+ until
+ iter
+ for
+ break
+ next
+ redo
+ retry
+ begin
+ rescue
+ resbody
+ ensure
+ and
+ or
+ not
+ masgn
+ lasgn
+ dasgn
+ dasgn_curr
+ gasgn
+ iasgn
+ cdecl
+ cvasgn
+ cvdecl
+ op_asgn1
+ op_asgn2
+ op_asgn_and
+ op_asgn_or
+ call
+ fcall
+ vcall
+ super
+ zsuper
+ array
+ zarray
+ hash
+ return
+ yield
+ lvar
+ dvar
+ gvar
+ ivar
+ const
+ cvar
+ nth_ref
+ back_ref
+ match
+ match2
+ match3
+ lit
+ str
+ dstr
+ xstr
+ dxstr
+ evstr
+ dregx
+ dregx_once
+ args
+ argscat
+ argspush
+ splat
+ to_ary
+ svalue
+ block_arg
+ block_pass
+ defn
+ defs
+ alias
+ valias
+ undef
+ class
+ module
+ sclass
+ colon2
+ colon3
+ cref
+ dot2
+ dot3
+ flip2
+ flip3
+ attrset
+ self
+ nil
+ true
+ false
+ defined
+ newline
+ postexe
+ dmethod
+ bmethod
+ memo
+ ifunc
+ dsym
+ attrasgn
+ regex
+ fixnum
+ number
+ hexnum
+ binnum
+ octnum
+ float
+ negate
+ last
+ file
+ end_data
+}
+
+File.open("vm/parser/node_types.cpp", "w") do |f|
+ f.puts <<EOF
+/* This file is generated by node_types.rb. Do not edit. */
+
+#include "node_types.hpp"
+
+namespace rubinius {
+ namespace parser {
+
+ static const char node_types[] = {
+EOF
+
+ node_types.each do |type|
+ f.puts(" \"#{type}\\0\"")
+ end
+
+ f.puts(" };")
+ f.puts
+
+ f.puts(" static const unsigned short node_types_offsets[] = {")
+ offset = 0
+
+ node_types.each_with_index do |type, index|
+ f.puts(",") if index > 0
+ f.write(" #{offset}")
+ offset += node_types[index].length + 1
+ end
+
+ f.puts <<EOF
+
+ };
+
+ const char *get_node_type_string(enum node_type nt) {
+ return node_types + node_types_offsets[nt];
+ }
+
+ }; // namespace parser
+}; // namespace rubinius
+EOF
+end
+
+File.open("vm/parser/node_types.hpp", "w") do |f|
+ f.puts <<EOF
+/* This file is generated by node_types.rb. Do not edit. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+namespace rubinius {
+ namespace parser {
+
+ enum node_type {
+EOF
+
+ node_types.each_with_index do |type, index|
+ f.puts(",") if index > 0
+ f.write(" NODE_#{type.upcase}")
+ end
+
+ f.puts <<EOF
+
+ };
+
+ const char *get_node_type_string(enum node_type nt);
+
+ }; // namespace parser
+}; // namespace rubinius
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+end
diff --git a/vm/parser/grammar.y b/vm/parser/grammar.y
index c746b1e..455052d 100644
--- a/vm/parser/grammar.y
+++ b/vm/parser/grammar.y
@@ -337,16 +337,17 @@ static NODE *extract_block_vars(rb_parse_state *parse_state, NODE* node, var_tab
klEND
k__LINE__
k__FILE__
+ k__END__
%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tXSTRING_BEG
-%token <node> tINTEGER tFLOAT tSTRING_CONTENT
+%token <node> tINTEGER tFLOAT tSTRING_CONTENT tEND_DATA
%token <node> tNTH_REF tBACK_REF
%token <num> tREGEXP_END
%type <node> singleton strings string string1 xstring regexp
%type <node> string_contents xstring_contents string_content
%type <node> words qwords word_list qword_list word
%type <node> literal numeric dsym cpath
-%type <node> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
+%type <node> bodystmt compstmt opt_end_data stmts stmt expr arg primary command command_call method_call
%type <node> expr_value arg_value primary_value
%type <node> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
%type <node> args when_args call_args call_args2 open_args paren_args opt_paren_args
@@ -425,7 +426,7 @@ program : {
vps->variables = new LocalState(0);
class_nest = 0;
}
- compstmt
+ compstmt opt_end_data
{
if ($2 && !compile_for_eval) {
/* last expression should not be void */
@@ -439,6 +440,8 @@ program : {
}
}
vps->top = block_append(vps, vps->top, $2);
+ if ($3)
+ vps->top = block_append(vps, $3, vps->top);
class_nest = 0;
}
;
@@ -470,6 +473,12 @@ compstmt : stmts opt_terms
}
;
+opt_end_data : none
+ | k__END__ tEND_DATA
+ {
+ $$ = $2;
+ }
+
stmts : none
| stmt
{
@@ -1033,7 +1042,7 @@ op : '|' { $$ = '|'; }
| '`' { $$ = '`'; }
;
-reswords : k__LINE__ | k__FILE__ | klBEGIN | klEND
+reswords : k__LINE__ | k__FILE__ | klBEGIN | klEND | k__END__
| kALIAS | kAND | kBEGIN | kBREAK | kCASE | kCLASS | kDEF
| kDEFINED | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
| kFOR | kIN | kMODULE | kNEXT | kNIL | kNOT
@@ -2569,6 +2578,7 @@ yycompile(rb_parse_state *parse_state, char *f, int line)
/* Setup an initial empty scope. */
heredoc_end = 0;
lex_strterm = 0;
+ parse_state->end_seen = 0;
ruby_sourcefile = f;
n = yyparse(parse_state);
ruby_debug_lines = 0;
@@ -3475,6 +3485,18 @@ yylex(void *yylval_v, void *vstate)
}
return token;
}
+
+ if (parse_state->end_seen) { /* After __END__ */
+ newtok(parse_state);
+ while ((c = nextc()) != -1) {
+ tokadd(c, parse_state);
+ }
+ tokfix();
+ pslval->node = NEW_END_DATA(string_new(tok(), toklen()));
+ parse_state->end_seen = 0;
+ return tEND_DATA;
+ }
+
cmd_state = command_start;
command_start = FALSE;
retry:
@@ -4493,7 +4515,9 @@ yylex(void *yylval_v, void *vstate)
case '_':
if (was_bol() && whole_match_p("__END__", 7, 0, parse_state)) {
parse_state->lex_lastline = 0;
- return -1;
+ parse_state->end_seen = 1;
+ parse_state->lex_p = parse_state->lex_pend;
+ return k__END__;
}
newtok(parse_state);
break;
diff --git a/vm/parser/grammar_node.hpp b/vm/parser/grammar_node.hpp
index c1f7f9b..3c25b0b 100644
--- a/vm/parser/grammar_node.hpp
+++ b/vm/parser/grammar_node.hpp
@@ -248,6 +248,7 @@ namespace rubinius {
#define NEW_NEGATE(l) NEW_NODE(NODE_NEGATE,l,0,0)
#define NEW_REGEX(l,o) NEW_NODE(NODE_REGEX,l,0,o)
#define NEW_FILE() NEW_NODE(NODE_FILE,0,0,0)
+#define NEW_END_DATA(s) NEW_NODE(NODE_END_DATA,s,0,0)
#define NOEX_PUBLIC 0
#define NOEX_NOSUPER 1
#define NOEX_PRIVATE 2
diff --git a/vm/parser/grammar_runtime.cpp b/vm/parser/grammar_runtime.cpp
index 2659cc6..1872618 100644
--- a/vm/parser/grammar_runtime.cpp
+++ b/vm/parser/grammar_runtime.cpp
@@ -813,6 +813,7 @@ namespace rubinius {
case NODE_XSTR: /* u1 (%x{ls}) */
case NODE_STR: /* u1 */
+ case NODE_END_DATA:
array_push(state, current, string_newfrombstr(state, node->nd_str));
bdestroy(node->nd_str);
break;
diff --git a/vm/parser/node_types.cpp b/vm/parser/node_types.cpp
index 5bf7819..79e3d02 100644
--- a/vm/parser/node_types.cpp
+++ b/vm/parser/node_types.cpp
@@ -119,6 +119,7 @@ namespace rubinius {
"negate\0"
"last\0"
"file\0"
+ "end_data\0"
};
static const unsigned short node_types_offsets[] = {
@@ -234,7 +235,8 @@ namespace rubinius {
697,
703,
710,
- 715
+ 715,
+ 720
};
const char *get_node_type_string(enum node_type nt) {
diff --git a/vm/parser/node_types.hpp b/vm/parser/node_types.hpp
index f00eaf2..513c4de 100644
--- a/vm/parser/node_types.hpp
+++ b/vm/parser/node_types.hpp
@@ -120,7 +120,8 @@ namespace rubinius {
NODE_FLOAT,
NODE_NEGATE,
NODE_LAST,
- NODE_FILE
+ NODE_FILE,
+ NODE_END_DATA
};
const char *get_node_type_string(enum node_type nt);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment