Skip to content

Commit

Permalink
Support special DATA constant when __END__ construct is used
Browse files Browse the repository at this point in the history
  • Loading branch information
adambeynon committed Dec 7, 2013
1 parent 17690dc commit 4133522
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 3 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Expand Up @@ -52,7 +52,8 @@
output javascript.

* Support parsing `__END__` constructs in ruby code, inside the lexer. The
content is gathered up by use of the parser.
content is gathered up by use of the parser. The special constant `DATA`
is then available inside the ruby code to read the content.

* Support single character strings (using ? prefix) with escaped characters.

Expand Down
7 changes: 6 additions & 1 deletion lib/opal/compiler.rb
Expand Up @@ -49,6 +49,9 @@ def self.compiler_option(name, default_value, mid = nil)
# Current case_stmt
attr_reader :case_stmt

# Any content in __END__ special construct
attr_reader :eof_content

def initialize
@line = 1
@indent = ''
Expand All @@ -60,8 +63,10 @@ def initialize
def compile(source, options = {})
@source = source
@options.update options
@parser = Parser.new

@sexp = s(:top, Parser.new.parse(@source, self.file) || s(:nil))
@sexp = s(:top, @parser.parse(@source, self.file) || s(:nil))
@eof_content = @parser.lexer.eof_content

@fragments = process(@sexp).flatten

Expand Down
4 changes: 3 additions & 1 deletion lib/opal/nodes/constants.rb
Expand Up @@ -8,7 +8,9 @@ class ConstNode < Base
children :name

def compile
if compiler.const_missing?
if name == :DATA and compiler.eof_content
push("$__END__")
elsif compiler.const_missing?
with_temp do |tmp|
push "((#{tmp} = $scope.#{name}) == null ? $opal.cm('#{name}') : #{tmp})"
end
Expand Down
9 changes: 9 additions & 0 deletions lib/opal/nodes/top.rb
Expand Up @@ -27,6 +27,7 @@ def compile

compile_method_stubs
compile_irb_vars
compile_end_construct

line body_code
end
Expand Down Expand Up @@ -57,6 +58,14 @@ def compile_method_stubs
end
end

# Any special __END__ content in code
def compile_end_construct
if content = compiler.eof_content
line "var $__END__ = Opal.Object.$new();"
line "$__END__.$read = function() { return #{content.inspect}; };"
end
end

def version_comment
"/* Generated by Opal #{Opal::VERSION} */"
end
Expand Down
19 changes: 19 additions & 0 deletions spec/cli/compiler_spec.rb
Expand Up @@ -38,6 +38,25 @@
end
end

describe "DATA special variable" do
it "is not a special case unless __END__ part present in source" do
expect_compiled("DATA").to include("DATA")
expect_compiled("DATA\n__END__").to_not include("DATA")
end

it "DATA gets compiled as a reference to special $__END__ variable" do
expect_compiled("a = DATA\n__END__").to include("a = $__END__")
end

it "causes the compiler to create a reference to special __END__ variable" do
expect_compiled("DATA\n__END__\nFord Perfect").to include("$__END__ = ")
end

it "does not create a reference to __END__ vairbale unless __END__ content present" do
expect_compiled("DATA").to_not include("$__END__ = ")
end
end

def expect_compiled(source)
expect(Opal::Compiler.new.compile source)
end
Expand Down

0 comments on commit 4133522

Please sign in to comment.