• ジャンプ先... +
    browser.coffee cake.coffee coffeescript.coffee command.coffee grammar.coffee helpers.coffee index.coffee lexer.coffee nodes.coffee optparse.coffee register.coffee repl.coffee rewriter.coffee scope.litcoffee sourcemap.litcoffee
  • scope.litcoffee

  • §

    スコープクラスは、CoffeeScript 内のレキシカルスコープを規制します。コードを生成すると、ネストされた関数本体と同じ形でスコープのツリーが作成されます。各スコープは、スコープ内で宣言された変数について認識し、その親である囲まれたスコープへの参照を持ちます。この方法で、どの変数が新しくvarで宣言する必要があるか、どの変数が外部スコープと共有されているかを把握できます。

    exports.Scope = class Scope
  • §

    チェーンの検索のために親を使用してスコープを初期化し、変数を宣言する必要があるブロックノードへの参照、スコープが属する関数への参照、ソースコード内で参照されており、変数を生成するときに回避する必要がある変数のリストを使用します。また、変数宣言の一部として出力されるべきコメントも追跡します。

      constructor: (@parent, @expressions, @method, @referencedVars) ->
        @variables = [{name: 'arguments', type: 'arguments'}]
        @comments  = {}
        @positions = {}
        @utilities = {} unless @parent
  • §

    @rootは、特定のファイルのトップレベルのスコープオブジェクトです。

        @root = @parent?.root ? this
  • §

    新しい変数を追加するか、既存の変数を上書きします。

      add: (name, type, immediate) ->
        return @parent.add name, type, immediate if @shared and not immediate
        if Object::hasOwnProperty.call @positions, name
          @variables[@positions[name]].type = type
        else
          @positions[name] = @variables.push({name, type}) - 1
  • §

    superが呼び出されると、現在のメソッドの名前を見つける必要があります。これにより、親クラスの同じメソッドを呼び出す方法がわかります。これは、内部関数からsuperが呼び出されると複雑になる可能性があります。namedMethodは、名前が埋め込まれた最初の関数オブジェクトが見つかるまで、または一番下まで到達するまでスコープツリーをさかのぼります。

      namedMethod: ->
        return @method if @method?.name or !@parent
        @parent.namedMethod()
  • §

    レキシカスコープ中で変数名を検索し、まだ存在していない場合は宣言します。

      find: (name, type = 'var') ->
        return yes if @check name
        @add name, type
        no
  • §

    このスコープの関数パラメーターに由来する変数名を予約します。内部参照にはvarは必要ありません。

      parameter: (name) ->
        return if @shared and @parent.check name, yes
        @add name, 'param'
  • §

    予約せずに変数がすでに宣言されているかどうかを確認するだけで、ルートスコープまでさかのぼります。

      check: (name) ->
        !!(@type(name) or @parent?.check(name))
  • §

    指定されたインデックスで一時変数名を生成します。

      temporary: (name, index, single=false) ->
        if single
          startCode = name.charCodeAt(0)
          endCode = 'z'.charCodeAt(0)
          diff = endCode - startCode
          newCode = startCode + index % (diff + 1)
          letter = String.fromCharCode(newCode)
          num = index // (diff + 1)
          "#{letter}#{num or ''}"
        else
          "#{name}#{index or ''}"
  • §

    変数のタイプを取得します。

      type: (name) ->
        return v.type for v in @variables when v.name is name
        null
  • §

    中間結果を格納する必要がある場合、コンパイラー生成変数に使用可能な名前を見つけます。_var、_var2など...

      freeVariable: (name, options={}) ->
        index = 0
        loop
          temp = @temporary name, index, options.single
          break unless @check(temp) or temp in @root.referencedVars
          index++
        @add temp, 'var', yes if options.reserve ? true
        temp
  • §

    このスコープの一番上に(または要求された場合はトップレベルスコープに)代入が行われるようにします。

      assign: (name, value) ->
        @add name, {value, assigned: yes}, yes
        @hasAssignments = yes
  • §

    このスコープには宣言された変数がありますか?

      hasDeclarations: ->
        !!@declaredVariables().length
  • §

    このスコープで最初に宣言された変数のリストを返します。

      declaredVariables: ->
        (v.name for v in @variables when v.type is 'var').sort()
  • §

    このスコープの一番上に配置されるはずの割り当てのリストを返します。

      assignedVariables: ->
        "#{v.name} = #{v.type.value}" for v in @variables when v.type.assigned