Back to Coffeescript

scope.litcoffee

docs/v2/annotated-source/scope.html

2.7.04.7 KB
Original Source

browser.coffeecake.coffeecoffeescript.coffeecommand.coffeegrammar.coffeehelpers.coffeeindex.coffeelexer.coffeenodes.coffeeoptparse.coffeeregister.coffeerepl.coffeerewriter.coffeescope.litcoffeesourcemap.litcoffee

scope.litcoffee

§

The Scope class regulates lexical scoping within CoffeeScript. As you generate code, you create a tree of scopes in the same shape as the nested function bodies. Each scope knows about the variables declared within it, and has a reference to its parent enclosing scope. In this way, we know which variables are new and need to be declared with var, and which are shared with external scopes.

exports.Scope =class Scope

§

Initialize a scope with its parent, for lookups up the chain, as well as a reference to the Block node it belongs to, which is where it should declare its variables, a reference to the function that it belongs to, and a list of variables referenced in the source code and therefore should be avoided when generating variables. Also track comments that should be output as part of variable declarations.

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

§

The @root is the top-level Scope object for a given file.

@root = @parent?.root ? this

§

Adds a new variable or overrides an existing one.

add:(name, type, immediate) -\>[email protected] name, type, immediateif@sharedandnotimmediateifObject::hasOwnProperty.call @positions, name
      @variables[@positions[name]].type = typeelse@positions[name] = @variables.push({name, type}) -1

§

When super is called, we need to find the name of the current method we’re in, so that we know how to invoke the same method of the parent class. This can get complicated if super is being called from an inner function. namedMethod will walk up the scope tree until it either finds the first function object that has a name filled in, or bottoms out.

namedMethod:-\>return@methodif@method?.nameor!@parent
    @parent.namedMethod()

§

Look up a variable name in lexical scope, and declare it if it does not already exist.

find:(name, type = 'var') -\>returnyesif@check name
    @add name, typeno

§

Reserve a variable name as originating from a function parameter for this scope. No var required for internal references.

parameter:(name) -\>returnif@[email protected] name,yes@add name,'param'

§

Just check to see if a variable has already been declared, without reserving, walks up to the root scope.

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

§

Generate a temporary variable name at the given index.

temporary:(name, index, single=false) -\>ifsingle
      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 ''}"

§

Gets the type of a variable.

type:(name) -\>[email protected]

§

If we need to store an intermediate result, find an available name for a compiler-generated variable. _var, _var2, and so on…

freeVariable:(name, options={}) -\>index =0looptemp = @temporary name, index, options.singlebreakunless@check(temp)[email protected]
      index++
    @add temp,'var',yesifoptions.reserve ?truetemp

§

Ensure that an assignment is made at the top of this scope (or at the top-level scope, if requested).

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

§

Does this scope have any declared variables?

hasDeclarations:-\>!!@declaredVariables().length

§

Return the list of variables first declared in this scope.

declaredVariables:-\>([email protected]'var').sort()

§

Return the list of assignments that are supposed to be made at the top of this scope.

assignedVariables:-\>"#{v.name} = #{v.type.value}"[email protected]