Class: Opal::Compiler
- Inherits:
- 
      Object
      
        - Object
- Opal::Compiler
 
- Includes:
- Nodes::Closure::CompilerSupport
- Defined in:
- opal/lib/opal/compiler.rb
Overview
Constant Summary collapse
- INDENT =
          Generated code gets indented with two spaces on each scope 
- ' '
- COMPARE =
          All compare method nodes - used to optimize performance of math comparisons 
- %w[< > <= >=].freeze 
Instance Attribute Summary collapse
- 
  
    
      #case_stmt  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Current case_stmt. 
- 
  
    
      #comments  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Comments from the source code. 
- 
  
    
      #dynamic_cache_result  ⇒ Object 
    
    
  
  
  
  
    
    
  
  
  
  
  
  
    Set if some rewritter caused a dynamic cache result, meaning it's not fit to be cached. 
- 
  
    
      #eof_content  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Any content in END special construct. 
- 
  
    
      #fragments  ⇒ Array 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    All [Opal::Fragment] used to produce result. 
- 
  
    
      #magic_comments  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Magic comment flags extracted from the leading comments. 
- 
  
    
      #method_calls  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Method calls made in this file. 
- 
  
    
      #result  ⇒ String 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    The compiled ruby code. 
- 
  
    
      #scope  ⇒ Object 
    
    
  
  
  
  
    
    
  
  
  
  
  
  
    Current scope. 
- 
  
    
      #source  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Access the source code currently processed. 
- 
  
    
      #top_scope  ⇒ Object 
    
    
  
  
  
  
    
    
  
  
  
  
  
  
    Top scope. 
Class Method Summary collapse
- 
  
    
      .compiler_option(name, config = {})  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Defines a compiler option. 
- .module_name(path) ⇒ Object
Instance Method Summary collapse
- 
  
    
      #arity_check?  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    adds an arity check to every method definition. 
- 
  
    
      #async_await  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Enable async/await support and optionally enable auto-await. 
- 
  
    
      #async_await_before_typecasting  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Enable async/await support and optionally enable auto-await. 
- #async_await_set_to_regexp(set) ⇒ Object
- 
  
    
      #autoloads  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    An array of things (requires, trees) which don't need to success in loading compile-time. 
- 
  
    
      #backtick_javascript?  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Allows use of a backtick operator (and %x{}`) to embed verbatim JavaScript.
- 
  
    
      #backtick_javascript_or_warn?  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    Warn about impending compatibility break. 
- 
  
    
      #compile  ⇒ String 
    
    
  
  
  
  
  
  
  
  
  
    Compile some ruby code to a string. 
- 
  
    
      #dynamic_require_severity  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    how to handle dynamic requires (:error, :warning, :ignore). 
- 
  
    
      #enable_file_source_embed?  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Embeds source code along compiled files. 
- 
  
    
      #enable_source_location?  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Adds source_location for every method definition. 
- 
  
    
      #error(msg, line = nil)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    This is called when a parsing/processing error occurs. 
- 
  
    
      #esm?  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Encourage ESM semantics, eg. 
- 
  
    
      #file  ⇒ String 
    
    
  
  
  
  
  
  
  
  
  
    The filename to use for compiling this code. 
- #fragment(str, scope, sexp = nil) ⇒ Object
- #freezing? ⇒ Boolean deprecated Deprecated.
- #handle_block_given_call(sexp) ⇒ Object
- #handlers ⇒ Object
- 
  
    
      #helper(name)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Use the given helper. 
- 
  
    
      #helpers  ⇒ Set<Symbol> 
    
    
  
  
  
  
  
  
  
  
  
    Any helpers required by this file. 
- #in_case ⇒ Object
- 
  
    
      #in_while  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Used when we enter a while statement. 
- 
  
    
      #in_while?  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    Returns true if the parser is curently handling a while sexp, false otherwise. 
- 
  
    
      #indent  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    To keep code blocks nicely indented, this will yield a block after adding an extra layer of indent, and then returning the resulting code after reverting the indent. 
- 
  
    
      #initialize(source, options = {})  ⇒ Compiler 
    
    
  
  
  
    constructor
  
  
  
  
  
  
  
    A new instance of Compiler. 
- 
  
    
      #inline_operators?  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    are operators compiled inline. 
- 
  
    
      #irb?  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    compile top level local vars with support for irb style vars. 
- 
  
    
      #load?  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Instantly load a requirable module. 
- 
  
    
      #marshal_dump  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Marshalling for cache shortpath. 
- #marshal_load(src) ⇒ Object
- 
  
    
      #method_missing?  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    adds method stubs for all used methods in file. 
- 
  
    
      #no_export?  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Don't export this compile, even if ESM mode is enabled. 
- 
  
    
      #option_value(name, config)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Fetches and memoizes the value for an option. 
- #parse ⇒ Object
- 
  
    
      #parse_comments?  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Adds comments for every method definition. 
- 
  
    
      #parser_indent  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Instances of Scopecan use this to determine the current scope indent.
- 
  
    
      #process(sexp, level = :expr)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Process the given sexp by creating a node instance, based on its type, and compiling it to fragments. 
- #re_raise_with_location ⇒ Object
- #record_method_call(mid) ⇒ Object
- 
  
    
      #requirable?  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Prepare the code for future requires. 
- 
  
    
      #required_trees  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    An array of trees required in this file (typically by calling #require_tree). 
- 
  
    
      #requires  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    An array of requires used in this file. 
- 
  
    
      #returns(sexp)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    The last sexps in method bodies, for example, need to be returned in the compiled javascript. 
- 
  
    
      #s(type, *children)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Create a new sexp using the given parts. 
- 
  
    
      #source_map  ⇒ Opal::SourceMap 
    
    
  
  
  
  
  
  
  
  
  
    Returns a source map that can be used in the browser to map back to original ruby code. 
- 
  
    
      #unique_temp(name)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Used to generate a unique id name per file. 
- 
  
    
      #use_strict?  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Enables JavaScript's strict mode (i.e., adds 'use strict'; statement). 
- 
  
    
      #warning(msg, line = nil)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    This is called when a parsing/processing warning occurs. 
- 
  
    
      #with_temp  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Temporary varibales will be needed from time to time in the generated code, and this method will assign (or reuse) on while the block is yielding, and queue it back up once it is finished. 
Methods included from Nodes::Closure::CompilerSupport
Constructor Details
#initialize(source, options = {}) ⇒ Compiler
Returns a new instance of Compiler.
| 281 282 283 284 285 286 287 288 289 290 291 292 | # File 'opal/lib/opal/compiler.rb', line 281 def initialize(source, = {}) @source = source @indent = '' @unique = 0 @options = @comments = Hash.new([]) @case_stmt = nil @method_calls = Set.new @option_values = {} @magic_comments = {} @dynamic_cache_result = false end | 
Instance Attribute Details
#case_stmt ⇒ Object (readonly)
Current case_stmt
| 260 261 262 | # File 'opal/lib/opal/compiler.rb', line 260 def case_stmt @case_stmt end | 
#comments ⇒ Object (readonly)
Comments from the source code
| 266 267 268 | # File 'opal/lib/opal/compiler.rb', line 266 def comments @comments end | 
#dynamic_cache_result ⇒ Object
Set if some rewritter caused a dynamic cache result, meaning it's not fit to be cached
| 279 280 281 | # File 'opal/lib/opal/compiler.rb', line 279 def dynamic_cache_result @dynamic_cache_result end | 
#eof_content ⇒ Object (readonly)
Any content in END special construct
| 263 264 265 | # File 'opal/lib/opal/compiler.rb', line 263 def eof_content @eof_content end | 
#fragments ⇒ Array (readonly)
Returns all [Opal::Fragment] used to produce result.
| 251 252 253 | # File 'opal/lib/opal/compiler.rb', line 251 def fragments @fragments end | 
#magic_comments ⇒ Object (readonly)
Magic comment flags extracted from the leading comments
| 272 273 274 | # File 'opal/lib/opal/compiler.rb', line 272 def magic_comments @magic_comments end | 
#method_calls ⇒ Object (readonly)
Method calls made in this file
| 269 270 271 | # File 'opal/lib/opal/compiler.rb', line 269 def method_calls @method_calls end | 
#result ⇒ String (readonly)
Returns The compiled ruby code.
| 248 249 250 | # File 'opal/lib/opal/compiler.rb', line 248 def result @result end | 
#scope ⇒ Object
Current scope
| 254 255 256 | # File 'opal/lib/opal/compiler.rb', line 254 def scope @scope end | 
#source ⇒ Object (readonly)
Access the source code currently processed
| 275 276 277 | # File 'opal/lib/opal/compiler.rb', line 275 def source @source end | 
#top_scope ⇒ Object
Top scope
| 257 258 259 | # File 'opal/lib/opal/compiler.rb', line 257 def top_scope @top_scope end | 
Class Method Details
.compiler_option(name, config = {}) ⇒ Object
Defines a compiler option.
| 72 73 74 75 | # File 'opal/lib/opal/compiler.rb', line 72 def self.compiler_option(name, config = {}) method_name = config.fetch(:as, name) define_method(method_name) { option_value(name, config) } end | 
.module_name(path) ⇒ Object
| 63 64 65 66 | # File 'opal/lib/opal/compiler.rb', line 63 def self.module_name(path) path = File.join(File.dirname(path), File.basename(path).split('.').first) Pathname(path).cleanpath.to_s end | 
Instance Method Details
#arity_check? ⇒ Boolean
adds an arity check to every method definition
| 122 | # File 'opal/lib/opal/compiler.rb', line 122 compiler_option :arity_check, default: false, as: :arity_check? | 
#async_await ⇒ Object
Enable async/await support and optionally enable auto-await.
Use either true, false, an Array of Symbols, a String containing names to auto-await separated by a comma or a Regexp.
Auto-await awaits provided methods by default as if .await was added to them automatically.
By default, the support is disabled (set to false).
If the config value is not set to false, any calls to #await will be translated to ES8 await keyword which makes the scope return a Promise and a containing scope will be async (instead of a value, it will return a Promise).
If the config value is an array, or a String separated by a comma, auto-await is also enabled.
A member of this collection can contain a wildcard character * in which case all methods containing a given substring will be awaited.
It can be used as a magic comment, examples:
# await: true
# await: *await*
# await: *await*, sleep, gets
| 245 | # File 'opal/lib/opal/compiler.rb', line 245 compiler_option :await, default: false, as: :async_await, magic_comment: true | 
#async_await_before_typecasting ⇒ Object
Enable async/await support and optionally enable auto-await.
Use either true, false, an Array of Symbols, a String containing names to auto-await separated by a comma or a Regexp.
Auto-await awaits provided methods by default as if .await was added to them automatically.
By default, the support is disabled (set to false).
If the config value is not set to false, any calls to #await will be translated to ES8 await keyword which makes the scope return a Promise and a containing scope will be async (instead of a value, it will return a Promise).
If the config value is an array, or a String separated by a comma, auto-await is also enabled.
A member of this collection can contain a wildcard character * in which case all methods containing a given substring will be awaited.
It can be used as a magic comment, examples:
# await: true
# await: *await*
# await: *await*, sleep, gets
| 357 | # File 'opal/lib/opal/compiler.rb', line 357 compiler_option :await, default: false, as: :async_await, magic_comment: true | 
#async_await_set_to_regexp(set) ⇒ Object
| 377 378 379 380 381 | # File 'opal/lib/opal/compiler.rb', line 377 def async_await_set_to_regexp(set) set = set.map { |name| Regexp.escape(name.to_s).gsub('\*', '.*?') } set = set.join('|') /^(#{set})$/ end | 
#autoloads ⇒ Object
An array of things (requires, trees) which don't need to success in loading compile-time.
| 540 541 542 | # File 'opal/lib/opal/compiler.rb', line 540 def autoloads @autoloads ||= [] end | 
#backtick_javascript? ⇒ Object
Allows use of a backtick operator (and %x{}`) to embed verbatim JavaScript.
If false, backtick operator will
| 195 | # File 'opal/lib/opal/compiler.rb', line 195 compiler_option :backtick_javascript, default: nil, as: :backtick_javascript?, magic_comment: true | 
#backtick_javascript_or_warn? ⇒ Boolean
Warn about impending compatibility break
| 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | # File 'opal/lib/opal/compiler.rb', line 198 def backtick_javascript_or_warn? case backtick_javascript? when true true when nil @backtick_javascript_warned ||= begin warning 'Backtick operator usage interpreted as intent to embed JavaScript; this code will ' \ 'break in Opal 2.0; add a magic comment: `# backtick_javascript: true`' true end true when false false end end | 
#compile ⇒ String
Compile some ruby code to a string.
| 297 298 299 300 301 302 303 304 | # File 'opal/lib/opal/compiler.rb', line 297 def compile parse @fragments = re_raise_with_location { process(@sexp).flatten } @fragments << fragment("\n", nil, s(:newline)) unless @fragments.last.code.end_with?("\n") @result = @fragments.map(&:code).join('') end | 
#dynamic_require_severity ⇒ Object
how to handle dynamic requires (:error, :warning, :ignore)
| 140 | # File 'opal/lib/opal/compiler.rb', line 140 compiler_option :dynamic_require_severity, default: :ignore, valid_values: %i[error warning ignore] | 
#enable_file_source_embed? ⇒ Object
Embeds source code along compiled files
| 179 | # File 'opal/lib/opal/compiler.rb', line 179 compiler_option :enable_file_source_embed, default: false, as: :enable_file_source_embed? | 
#enable_source_location? ⇒ Object
Adds source_location for every method definition
| 174 | # File 'opal/lib/opal/compiler.rb', line 174 compiler_option :enable_source_location, default: false, as: :enable_source_location? | 
#error(msg, line = nil) ⇒ Object
This is called when a parsing/processing error occurs. This method simply appends the filename and curent line number onto the message and raises it.
| 386 387 388 389 390 | # File 'opal/lib/opal/compiler.rb', line 386 def error(msg, line = nil) error = ::Opal::SyntaxError.new(msg) error.location = Opal::OpalBacktraceLocation.new(file, line) raise error end | 
#esm? ⇒ Object
Encourage ESM semantics, eg. exporting run result
| 155 | # File 'opal/lib/opal/compiler.rb', line 155 compiler_option :esm, default: false, as: :esm? | 
#file ⇒ String
The filename to use for compiling this code. Used for FILE directives as well as finding relative require()
| 108 | # File 'opal/lib/opal/compiler.rb', line 108 compiler_option :file, default: '(file)' | 
#fragment(str, scope, sexp = nil) ⇒ Object
| 423 424 425 | # File 'opal/lib/opal/compiler.rb', line 423 def fragment(str, scope, sexp = nil) Fragment.new(str, scope, sexp) end | 
#freezing? ⇒ Boolean
stubs out #freeze and #frozen?
| 130 | # File 'opal/lib/opal/compiler.rb', line 130 compiler_option :freezing, default: true, as: :freezing? | 
#handle_block_given_call(sexp) ⇒ Object
| 629 630 631 632 633 634 635 636 637 638 | # File 'opal/lib/opal/compiler.rb', line 629 def handle_block_given_call(sexp) @scope.uses_block! if @scope.block_name fragment("(#{@scope.block_name} !== nil)", scope, sexp) elsif (scope = @scope.find_parent_def) && scope.block_name fragment("(#{scope.block_name} !== nil)", scope, sexp) else fragment('false', scope, sexp) end end | 
#handlers ⇒ Object
| 523 524 525 | # File 'opal/lib/opal/compiler.rb', line 523 def handlers @handlers ||= Opal::Nodes::Base.handlers end | 
#helper(name) ⇒ Object
Use the given helper
| 458 459 460 | # File 'opal/lib/opal/compiler.rb', line 458 def helper(name) helpers << name end | 
#helpers ⇒ Set<Symbol>
Any helpers required by this file. Used by Nodes::Top to reference runtime helpers that are needed. These are used to minify resulting javascript by keeping a reference to helpers used.
| 347 348 349 350 351 | # File 'opal/lib/opal/compiler.rb', line 347 def helpers @helpers ||= Set.new( magic_comments[:helpers].to_s.split(',').map { |h| h.strip.to_sym } ) end | 
#in_case ⇒ Object
| 497 498 499 500 501 502 503 | # File 'opal/lib/opal/compiler.rb', line 497 def in_case return unless block_given? old = @case_stmt @case_stmt = {} yield @case_stmt = old end | 
#in_while ⇒ Object
Used when we enter a while statement. This pushes onto the current scope's while stack so we know how to handle break, next etc.
| 489 490 491 492 493 494 495 | # File 'opal/lib/opal/compiler.rb', line 489 def in_while return unless block_given? @while_loop = @scope.push_while result = yield @scope.pop_while result end | 
#in_while? ⇒ Boolean
Returns true if the parser is curently handling a while sexp, false otherwise.
| 507 508 509 | # File 'opal/lib/opal/compiler.rb', line 507 def in_while? @scope.in_while? end | 
#indent ⇒ Object
To keep code blocks nicely indented, this will yield a block after adding an extra layer of indent, and then returning the resulting code after reverting the indent.
| 465 466 467 468 469 470 471 472 473 | # File 'opal/lib/opal/compiler.rb', line 465 def indent indent = @indent @indent += INDENT @space = "\n#{@indent}" res = yield @indent = indent @space = "\n#{@indent}" res end | 
#inline_operators? ⇒ Object
are operators compiled inline
| 167 | # File 'opal/lib/opal/compiler.rb', line 167 compiler_option :inline_operators, default: true, as: :inline_operators? | 
#irb? ⇒ Object
compile top level local vars with support for irb style vars
| 135 | # File 'opal/lib/opal/compiler.rb', line 135 compiler_option :irb, default: false, as: :irb? | 
#load? ⇒ Object
Instantly load a requirable module
| 150 | # File 'opal/lib/opal/compiler.rb', line 150 compiler_option :load, default: false, as: :load? | 
#marshal_dump ⇒ Object
Marshalling for cache shortpath
| 641 642 643 644 645 | # File 'opal/lib/opal/compiler.rb', line 641 def marshal_dump [@options, @option_values, @source_map ||= source_map.cache, @magic_comments, @result, @required_trees, @requires, @autoloads] end | 
#marshal_load(src) ⇒ Object
| 647 648 649 650 651 | # File 'opal/lib/opal/compiler.rb', line 647 def marshal_load(src) @options, @option_values, @source_map, @magic_comments, @result, @required_trees, @requires, @autoloads = src end | 
#method_missing? ⇒ Boolean
adds method stubs for all used methods in file
| 115 | # File 'opal/lib/opal/compiler.rb', line 115 compiler_option :method_missing, default: true, as: :method_missing? | 
#no_export? ⇒ Object
Don't export this compile, even if ESM mode is enabled. We use this internally in CLI, so that even if ESM output is desired, we would only have one default export.
| 162 | # File 'opal/lib/opal/compiler.rb', line 162 compiler_option :no_export, default: false, as: :no_export? | 
#option_value(name, config) ⇒ Object
Fetches and memoizes the value for an option.
| 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | # File 'opal/lib/opal/compiler.rb', line 78 def option_value(name, config) return @option_values[name] if @option_values.key? name default_value = config[:default] valid_values = config[:valid_values] magic_comment = config[:magic_comment] value = @options.fetch(name, default_value) if magic_comment && @magic_comments.key?(name) value = @magic_comments.fetch(name) end if valid_values && !valid_values.include?(value) raise( ArgumentError, "invalid value #{value.inspect} for option #{name.inspect} " \ "(valid values: #{valid_values.inspect})" ) end @option_values[name] = value end | 
#parse ⇒ Object
| 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | # File 'opal/lib/opal/compiler.rb', line 306 def parse @buffer = ::Opal::Parser::SourceBuffer.new(file, 1) @buffer.source = @source @parser = Opal::Parser.default_parser sexp, comments, tokens = re_raise_with_location { @parser.tokenize(@buffer) } kind = case when requirable? :require when eval? :eval else :main end @sexp = sexp.tap { |i| i.[:kind] = kind } first_node = sexp.children.first if sexp.children.first.location @comments = ::Parser::Source::Comment.associate_locations(first_node, comments) @magic_comments = MagicComments.parse(first_node, comments) @eof_content = EofContent.new(tokens, @source).eof end | 
#parse_comments? ⇒ Object
Adds comments for every method definition
| 189 | # File 'opal/lib/opal/compiler.rb', line 189 compiler_option :parse_comments, default: false, as: :parse_comments? | 
#parser_indent ⇒ Object
Instances of Scope can use this to determine the current
scope indent. The indent is used to keep generated code easily
readable.
| 414 415 416 | # File 'opal/lib/opal/compiler.rb', line 414 def parser_indent @indent end | 
#process(sexp, level = :expr) ⇒ Object
Process the given sexp by creating a node instance, based on its type, and compiling it to fragments.
| 513 514 515 516 517 518 519 520 521 | # File 'opal/lib/opal/compiler.rb', line 513 def process(sexp, level = :expr) return fragment('', scope) if sexp.nil? if handler = handlers[sexp.type] return handler.new(sexp, level, self).compile_to_fragments else error "Unsupported sexp: #{sexp.type}" end end | 
#re_raise_with_location ⇒ Object
| 392 393 394 395 396 397 398 399 400 401 402 | # File 'opal/lib/opal/compiler.rb', line 392 def re_raise_with_location yield rescue StandardError, ::Opal::SyntaxError => error opal_location = ::Opal.opal_location_from_error(error) opal_location.path = file opal_location.label ||= @source.lines[opal_location.line.to_i - 1].strip new_error = ::Opal::SyntaxError.new(error.) new_error.set_backtrace error.backtrace ::Opal.add_opal_location_to_error(opal_location, new_error) raise new_error end | 
#record_method_call(mid) ⇒ Object
| 353 354 355 | # File 'opal/lib/opal/compiler.rb', line 353 def record_method_call(mid) @method_calls << mid end | 
#requirable? ⇒ Object
Prepare the code for future requires
| 145 | # File 'opal/lib/opal/compiler.rb', line 145 compiler_option :requirable, default: false, as: :requirable? | 
#required_trees ⇒ Object
An array of trees required in this file (typically by calling #require_tree)
| 534 535 536 | # File 'opal/lib/opal/compiler.rb', line 534 def required_trees @required_trees ||= [] end | 
#requires ⇒ Object
An array of requires used in this file
| 528 529 530 | # File 'opal/lib/opal/compiler.rb', line 528 def requires @requires ||= [] end | 
#returns(sexp) ⇒ Object
The last sexps in method bodies, for example, need to be returned
in the compiled javascript. Due to syntax differences between
javascript any ruby, some sexps need to be handled specially. For
example, if statemented cannot be returned in javascript, so
instead the "truthy" and "falsy" parts of the if statement both
need to be returned instead.
Sexps that need to be returned are passed to this method, and the
alterned/new sexps are returned and should be used instead. Most
sexps can just be added into a s(:return) sexp, so that is the
default action if no special case is required.
| 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 | # File 'opal/lib/opal/compiler.rb', line 555 def returns(sexp) return returns s(:nil) unless sexp case sexp.type when :undef # undef :method_name always returns nil returns sexp.updated(:begin, [sexp, s(:nil)]) when :break, :next, :redo, :retry sexp when :yield sexp.updated(:returnable_yield, nil) when :when *when_sexp, then_sexp = *sexp sexp.updated(nil, [*when_sexp, returns(then_sexp)]) when :rescue body_sexp, *resbodies, else_sexp = *sexp resbodies = resbodies.map do |resbody| returns(resbody) end if else_sexp else_sexp = returns(else_sexp) end sexp.updated( nil, [ returns(body_sexp), *resbodies, else_sexp ] ) when :resbody klass, lvar, body = *sexp sexp.updated(nil, [klass, lvar, returns(body)]) when :ensure rescue_sexp, ensure_body = *sexp sexp = sexp.updated(nil, [returns(rescue_sexp), ensure_body]) sexp.updated(:js_return, [sexp]) when :begin, :kwbegin # Wrapping last expression with s(:js_return, ...) *rest, last = *sexp sexp.updated(nil, [*rest, returns(last)]) when :while, :until, :while_post, :until_post sexp when :return, :js_return, :returnable_yield sexp when :xstr if backtick_javascript_or_warn? sexp.updated(nil, [s(:js_return, *sexp.children)]) else sexp end when :if cond, true_body, false_body = *sexp sexp.updated( nil, [ cond, returns(true_body), returns(false_body) ] ).tap { |s| s.[:returning] = true } else if sexp.type == :send && sexp.children[1] == :debugger # debugger is a statement, so it doesn't return a value # and returning it is invalid. Therefore we update it # to do `debugger; return nil`. sexp.updated(:begin, [sexp, s(:js_return, s(:nil))]) else sexp.updated(:js_return, [sexp]) end end end | 
#s(type, *children) ⇒ Object
Create a new sexp using the given parts.
| 419 420 421 | # File 'opal/lib/opal/compiler.rb', line 419 def s(type, *children) ::Opal::AST::Node.new(type, children) end | 
#source_map ⇒ Opal::SourceMap
Returns a source map that can be used in the browser to map back to original ruby code.
| 337 338 339 340 | # File 'opal/lib/opal/compiler.rb', line 337 def source_map # We only use @source_map if compiler is cached. @source_map || ::Opal::SourceMap::File.new(@fragments, file, @source, @result) end | 
#unique_temp(name) ⇒ Object
Used to generate a unique id name per file. These are used mainly to name method bodies for methods that use blocks.
| 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 | # File 'opal/lib/opal/compiler.rb', line 429 def unique_temp(name) name = name.to_s if name && !name.empty? name = name .to_s .gsub('<=>', '$lt_eq_gt') .gsub('===', '$eq_eq_eq') .gsub('==', '$eq_eq') .gsub('=~', '$eq_tilde') .gsub('!~', '$excl_tilde') .gsub('!=', '$not_eq') .gsub('<=', '$lt_eq') .gsub('>=', '$gt_eq') .gsub('=', '$eq') .gsub('?', '$ques') .gsub('!', '$excl') .gsub('/', '$slash') .gsub('%', '$percent') .gsub('+', '$plus') .gsub('-', '$minus') .gsub('<', '$lt') .gsub('>', '$gt') .gsub(/[^\w\$]/, '$') end unique = (@unique += 1) "#{'$' unless name.start_with?('$')}#{name}$#{unique}" end | 
#use_strict? ⇒ Object
Enables JavaScript's strict mode (i.e., adds 'use strict'; statement)
| 184 | # File 'opal/lib/opal/compiler.rb', line 184 compiler_option :use_strict, default: false, as: :use_strict?, magic_comment: true | 
#warning(msg, line = nil) ⇒ Object
This is called when a parsing/processing warning occurs. This method simply appends the filename and curent line number onto the message and issues a warning.
| 407 408 409 | # File 'opal/lib/opal/compiler.rb', line 407 def warning(msg, line = nil) warn "warning: #{msg} -- #{file}:#{line}" end | 
#with_temp ⇒ Object
Temporary varibales will be needed from time to time in the generated code, and this method will assign (or reuse) on while the block is yielding, and queue it back up once it is finished. Variables are queued once finished with to save the numbers of variables needed at runtime.
| 480 481 482 483 484 485 | # File 'opal/lib/opal/compiler.rb', line 480 def with_temp tmp = @scope.new_temp res = yield tmp @scope.queue_temp tmp res end |