class Opal::Parser::Scope
along with the scope implementation.
temp variables and ivars so they can be processed and output
being processed. It is used to keep track of used variables,
Instances of Scope are used by the parser when a new scope is
def add_arg(arg)
def add_arg(arg) @args << arg unless @args.include? arg end
def add_ivar(ivar)
def add_ivar(ivar) if def_in_class? @parent.add_proto_ivar ivar else @ivars << ivar unless @ivars.include? ivar end end
def add_local(local)
def add_local(local) return if has_local? local @locals << local end
def add_proto_ivar(ivar)
def add_proto_ivar(ivar) @proto_ivars << ivar unless @proto_ivars.include? ivar end
def add_temp(*tmps)
def add_temp(*tmps) @temps.push *tmps end
def class?
def class? @type == :class end
def class_scope?
def class_scope? @type == :class or @type == :module end
def def_in_class?
used for optimizing ivars as we can set them to nil in the
Is this a normal def method directly inside a class? This is
def def_in_class? !@defs && @type == :def && @parent && @parent.class? end
def get_super_chain
def get_super_chain chain, scope, defn, mid = [], self, 'null', 'null' while scope if scope.type == :iter chain << scope.identify! scope = scope.parent if scope.parent elsif scope.type == :def defn = scope.identify! mid = "'$#{scope.mid}'" break else break end end [chain, defn, mid] end
def has_local?(local)
def has_local?(local) return true if @locals.include? local or @args.include? local return @parent.has_local?(local) if @parent and @type == :iter false end
def has_temp?(tmp)
def has_temp?(tmp) @temps.include? tmp end
def identify!
def identify! return @identity if @identity @identity = @parser.unique_temp @parent.add_temp @identity if @parent @identity end
def identity
def identity @identity end
def in_while?
def in_while? !@while_stack.empty? end
def initialize(type, parser)
def initialize(type, parser) @parser = parser @type = type @locals = [] @temps = [] @args = [] @ivars = [] @parent = nil @queue = [] @unique = "a" @while_stack = [] @defines_defs = false @defines_defn = false @methods = [] @smethods = [] @uses_block = false # used by classes to store all ivars used in direct def methods @proto_ivars = [] end
def iter?
def iter? @type == :iter end
def module?
def module? @type == :module end
def new_temp
def new_temp return @queue.pop unless @queue.empty? tmp = "_#{@unique}" @unique = @unique.succ @temps << tmp tmp end
def pop_while
def pop_while @while_stack.pop end
def proto
def proto "def" end
def push_while
def push_while info = {} @while_stack.push info info end
def queue_temp(name)
def queue_temp(name) @queue << name end
def should_donate?
def should_donate? @type == :module or @name.to_s == 'Object' end
def to_donate_methods
def to_donate_methods out = "" if should_donate? and !@methods.empty? # unless @methods.empty? out += "%s;#{@name}._donate([%s]);" % [@parser.parser_indent, @methods.map(&:inspect).join(', ')] end unless @smethods.empty? out += "%s;#{@name}._sdonate([%s]);" % [@parser.parser_indent, @smethods.map(&:inspect).join(', ')] end out end
def to_vars
#
def to_vars vars = @locals.map { |l| "#{l} = nil" } vars.push *@temps current_self = @parser.current_self iv = ivars.map do |ivar| "if (#{current_self}#{ivar} == null) #{current_self}#{ivar} = nil;\n" end indent = @parser.parser_indent res = vars.empty? ? '' : "var #{vars.join ', '};" str = ivars.empty? ? res : "#{res}\n#{indent}#{iv.join indent}" if class? and !@proto_ivars.empty? pvars = @proto_ivars.map { |i| "#{proto}#{i}"}.join(' = ') "%s\n%s%s = nil;" % [str, indent, pvars] else str end end
def top?
def top? @type == :top end
def uses_block!
def uses_block! if @type == :iter && @parent @parent.uses_block! else @uses_block = true # identify! end end
def uses_block?
def uses_block? @uses_block end