We wrap the _evaluate method so we can track `seen` nodes, we push an item
to the map before we actually evaluate it so we can deopt on self recursive
nodes such as:

var g = a ? 1 : 2,
a = g * this.foo
559885
function evaluateCached(path, state) {
  const { node } = path;
  const { seen } = state;

  if (seen.has(node)) {
    const existing = seen.get(node);
    if (existing.resolved) {
      return existing.value;
    } else {
      deopt(path, state);
      return;
    }
  } else {
    const item = { resolved: false };
    seen.set(node, item);

    const val = _evaluate(path, state);
    if (state.confident) {
      item.resolved = true;
      item.value = val;
    }
    return val;
  }
}
1320129
function visitEvalCallExpressions(traverse, node, path, state) {
    utils.catchup(node.range[1], state, function(value) {
      if(optimizeFunction(node.callee.name)) {
        // Unpack the id
        var id = extractId(node.callee.name);
        // Create path and object call
        var pathDeclaration = f('var path_%s = %s;\n', id, transformedFileData1.code.substring(node.arguments[0].range[0], node.arguments[0].range[1]));
        var objectDeclaration = f('var object_%s = %s;\n', id, transformedFileData1.code.substring(node.arguments[1].range[0], node.arguments[1].range[1]));

        // Get the function code
        var code = functions[node.callee.name].code;

        // Replace path and object in source
        var functionSource = code
          .replace(/object/g, f('object_%s', id))
          .replace(/path/g, f('path_%s', id))
          .replace(/return errors\;/, '');

        // Return the in-lined function
        return f('%s\n%s\n%s', objectDeclaration, pathDeclaration, functionSource);
      } else if(!skipTopLevelOptimization && ast.type == 'object' && node.callee.name === f('object_validation_%s', ast.id)) {
        return '';
      } else {
        return value;
      }
    });
  }
1138794
function traverse (value, v) {
  var state = {}
  var visitor = v.visitor
  var seen = []

  /**
   * Recursively walk the value, dispatching visitor methods as values are encountered.
   *
   * @param {*} val Value
   * @param {Value|null} parent Parent value
   * @param {object} [opts] Additional options
   */
  function traverseValue (val, parent, opts) {
    var wrapper = Value(val, parent, opts)
    var enterFn = wrapper.type + 'Enter'
    var exitFn = wrapper.type + 'Exit'
    var keys

    if (wrapper.type === 'object' || wrapper.type === 'array') {
      if (seen.indexOf(wrapper.value) >= 0) {
        wrapper.isCircularRef = true
      }
      seen.push(wrapper.value)
    }

    if (wrapper.type === 'object') {
      keys = Object.keys(wrapper.value).sort()
      wrapper.length = keys.length
    }

    if (visitor[enterFn]) {
      visitor[enterFn](wrapper, state)
    } else if (visitor.otherEnter) {
      visitor.otherEnter(wrapper, state)
    }

    switch (wrapper.type) {
      case 'array':
        if (!wrapper.isCircularRef) {
          wrapper.value.forEach(function (child, i) {
            traverseValue(child, wrapper, { key: i })
          })
        }
        break

      case 'object':
        if (!wrapper.isCircularRef) {
          keys.forEach(function (key) {
            traverseValue(wrapper.value[key], wrapper, { key: key })
          })
        }
        break

      default:
        /* do nothing */
        break
    }

    if (visitor[exitFn]) {
      visitor[exitFn](wrapper, state)
    }

    if (wrapper.type === 'object' || wrapper.type === 'array') {
      seen.pop()
    }
  }

  if (v.pre) { v.pre.call(null, state) }
  traverseValue(value, null, null)
  if (v.post) { v.post.call(null, state) }
}
48362
def evaluate(node, indent)
      # Check if this is a substructure of a control block and remove the last
      # end evaluation if it is
      if node[@value] =~ Settings::END_REMOVAL
        @template.pop if @template[-1] == [:eval, 'end']
      end

      # Check for explicit end node
      if node[@value] =~ Settings::END_EXPLICIT
        Logger.error :compile, @template, :explicit_end, node
      end

      # Evaluate the current expression
      buffer_eval node[@value]

      # If the node has children, evaluate each one of them
      node[@children].each do |child|
        root child, indent + @settings[:indent]
      end if node[@children]

      # Check if the node is actually a block expression
      buffer_eval 'end' if node[@value] =~ Settings::END_INSERTION
    end
174666
function visit(ast, context, visitor) {
  var stack;
  var parent;
  var keys = [];
  var index = -1;

  do {
    index++;
    if (stack && index === keys.length) {
      parent = stack.parent;
      keys = stack.keys;
      index = stack.index;
      stack = stack.prev;
    } else {
      var node = parent ? parent[keys[index]] : getProgram(ast);
      if (node && typeof node === 'object' && (node.type || node.length)) {
        if (node.type) {
          var visitFn = visitor[node.type];
          if (visitFn && visitFn(context, node, ast) === false) {
            continue;
          }
        }
        stack = {parent: parent, keys: keys, index: index, prev: stack};
        parent = node;
        keys = Object.keys(node);
        index = -1;
      }
    }
  } while (stack);
}
1361240
def eval_context(context, node)
      node.context(&context[:block]) if context[:nodes].matches?(node.name)
    end
285887
function visit(item, cycle) {
    let visitedDeps = visited.get(item);

    // Create an object for the item to mark visited deps.
    if (!visitedDeps) {
      visitedDeps = [];
      visited.set(item, visitedDeps);
    }

    // Get the current deps for the item.
    let deps = currDepsMap.get(item);
    if (typeof deps === 'undefined') return;

    // For each dep,
    for (let dep of deps) {
      // Check if this dep creates a cycle. We know it's a cycle if the first
      // item is the same as our dep.
      if (cycle[0] === dep) {
        cycles.push(cycle);
      }

      // If an item hasn't been visited, visit it (and pass an updated
      // potential cycle)
      if (!arrayIncludes(visitedDeps, dep)) {
        visitedDeps.push(dep);
        visit(dep, cycle.concat(dep));
      }
    }
  }
354396
private Object evalInternal(
    Selector sel,
    MatchSpaceKey bind,
    EvalCache cache,
    Object contextValue,
    boolean permissive)
    throws BadMessageFormatMatchingException
  {
    if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
      tc.entry(cclass, "evalInternal", new Object[] { sel, bind, cache, contextValue, new Boolean(permissive) });
    
    Object theReturn = null;
    // If sel is a literal, its value is simply the literal's value
    if (sel instanceof Literal)
    {
      if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
        tc.debug(cclass, "Selector is a literal");         
      theReturn = ((Literal) sel).getValue();
      if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
        tc.exit(cclass, "evalInternal", theReturn);  
      return theReturn;
    }

    // If sel is an Identifier, we let the MatchSpaceKey evaluate it.  The MatchSpaceKey is
    // given explicit type information unless the evaluation mode is permissive, in which
    // case the value is retrieved regardless and the permissive casts are applied.

    if (sel instanceof Identifier)
    {
      if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
        tc.debug(cclass, "Selector is an Identifier");        
      Identifier id = (Identifier) sel;
      if (permissive && id.getType() != Selector.UNKNOWN)
      {
        // Result may require permissive mode casts.  First, get the value, whatever it
        // is.
        boolean returnList = true;
        if(id.getType() == Selector.BOOLEAN)
          returnList = false;
        Object idVal = 
          bind.getIdentifierValue(id,
                                  true,
                                  contextValue, 
                                  returnList); // true means return a nodelist
        if (idVal == null)
        {
          if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
            tc.exit(cclass, "evalInternal", null);            
          return null;
        }
        // Perform permissive casts
        switch (id.getType())
        {
          case Selector.NUMERIC :
            if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
              tc.debug(cclass, "Selector type is numeric");               
            if (idVal instanceof Number) // was NumericValue
            {
              if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
                tc.exit(cclass, "evalInternal", idVal);                
              return idVal;
            }
            else
            {
              if(idVal instanceof ArrayList)
              {
                theReturn = castToNumberList((ArrayList)idVal);
              }
              else
                theReturn = castToNumber(idVal);
              if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
                tc.exit(cclass, "evalInternal", theReturn);
              return theReturn;
            }
          case Selector.STRING :
            if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
              tc.debug(cclass, "Selector type is string");              
            if (idVal instanceof String)
            {
              if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
                tc.exit(cclass, "evalInternal", idVal);                
              return idVal;
            }
            else
            {
              if(idVal instanceof ArrayList)
              {
                theReturn = castToStringList((ArrayList)idVal);
              }
              else
                theReturn = idVal.toString();
              if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
                tc.exit(cclass, "evalInternal", theReturn);
              return theReturn;
            }            
          case Selector.BOOLEAN :
            if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
              tc.debug(cclass, "Selector type is boolean");              
            if (idVal instanceof Boolean) // was BooleanValue
            {
              if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
                tc.exit(cclass, "evalInternal", idVal);                
              return idVal;
            }
            else
            {
              theReturn = castToBoolean(idVal);
              if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
                tc.exit(cclass, "evalInternal", theReturn);            
              return theReturn;              
            }
          default :
            if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
              tc.debug(cclass, "Selector type is default");              
            // Normally, permissive mode evaluation would not apply to TOPIC and OBJECT
            // Identifiers.  But, in any case, there are no valid casts to those types.
            if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
              tc.exit(cclass, "evalInternal", null);              
            return null;
        }
      }
      else
      {
        // not permissive, or the type is UNKNOWN so no permissive mode casts apply
        boolean returnList = true;
        if(id.getType() == Selector.BOOLEAN)
          returnList = false;
        theReturn = 
          bind.getIdentifierValue(id,
                                  false,
                                  contextValue, 
                                  returnList); // true means return a nodelist
        if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
          tc.exit(cclass, "evalInternal", theReturn);         
        return theReturn;
      }
    }

    // Otherwise, it's an Operator
    Operator op = (Operator) sel;
    if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
      tc.debug(cclass, "Selector is an operator");  
    // Evaluate the operands to obtain the values needed to evaluate the operator
    Object val0 = eval(op.getOperands()[0], bind, cache, contextValue, permissive); // was false
    Object val1 =
      (op.getOperands().length == 1)
        ? null
        : eval(op.getOperands()[1], bind, cache, contextValue, permissive); // was false

    // Evaluate according to the operator
    switch (op.getOp())
    {
      case Selector.NOT :
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type is NOT");         
        if (val0 instanceof Boolean) 
        {
          theReturn = not((Boolean) val0);
          if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
            tc.exit(cclass, "evalInternal", theReturn);         
          return theReturn;          
        }
        else
          if (permissive && val0 != null)
          {
            theReturn = not(castToBoolean(val0));
            if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
              tc.exit(cclass, "evalInternal", theReturn);         
            return theReturn;            
          }
          else
          {
            if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
              tc.exit(cclass, "evalInternal", null);              
            return null; 
          }
      case Selector.NEG :
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type is NEG");         
        if (!(val0 instanceof Number)) // was NumericValue
          if (permissive && val0 != null)
          {
            val0 = castToNumber(val0);
            if (val0 == null)
            {
              if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
                tc.exit(cclass, "evalInternal", null);               
              return null;
            }
          }
          else
          {
            if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
              tc.exit(cclass, "evalInternal", null);             
            return null;
          }
        // val0 is now definitely a Number
        return neg((Number)val0);
      case Selector.ISNULL :
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type ISNULL");
        theReturn = Boolean.valueOf(val0 == null);
        if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
          tc.exit(cclass, "evalInternal", theReturn);         
        return theReturn;         
      case Selector.LIKE :
      case Selector.TOPIC_LIKE:
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type is LIKE");        
        if (!(val0 instanceof String))
          if (permissive && val0 != null)
            val0 = val0.toString();
          else
          {
            if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
              tc.exit(cclass, "evalInternal", null);              
            return null;
          }
        // val0 is a String
        theReturn = Boolean.valueOf(((LikeOperatorImpl) op)
            .getInternalPattern().match((String) val0));
        if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
          tc.exit(cclass, "evalInternal", theReturn);           
        return theReturn;
      case Selector.NE :
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type is NE");          
        if(val0 instanceof ArrayList)
          theReturn = compareList((ArrayList)val0, val1, false, permissive, false);
        else
          theReturn = not(compare(val0, val1, false, permissive));
        if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
          tc.exit(cclass, "evalInternal", theReturn);           
        return theReturn;        
      case Selector.EQ :
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type is EQ");          
        if(val0 instanceof ArrayList)
          theReturn = compareList((ArrayList)val0, val1, false, permissive, true);
        else        
          theReturn = compare(val0, val1, false, permissive);
        if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
          tc.exit(cclass, "evalInternal", theReturn); 
        return theReturn;
      case Selector.GT :
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type is GT");          
        if(val0 instanceof ArrayList)
          theReturn = compareList((ArrayList)val0, val1, false, permissive, true);
        else              
          theReturn = compare(val1, val0, true, permissive);
        if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
          tc.exit(cclass, "evalInternal", theReturn); 
        return theReturn;        
      case Selector.LT :
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type is LT");          
        if(val0 instanceof ArrayList)
          theReturn = compareList((ArrayList)val0, val1, false, permissive, true);
        else              
          theReturn = compare(val0, val1, true, permissive);
        if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
          tc.exit(cclass, "evalInternal", theReturn); 
        return theReturn;         
      case Selector.GE :
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type is GE");          
        if(val0 instanceof ArrayList)
          theReturn = compareList((ArrayList)val0, val1, false, permissive, false);
        else              
          theReturn = not(compare(val0, val1, true, permissive));
        if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
          tc.exit(cclass, "evalInternal", theReturn); 
        return theReturn;          
      case Selector.LE :
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type is LE");          
        if(val0 instanceof ArrayList)
          theReturn = compareList((ArrayList)val0, val1, false, permissive, false);
        else              
          theReturn = not(compare(val1, val0, true, permissive));
        if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
          tc.exit(cclass, "evalInternal", theReturn); 
        return theReturn;          
      case Selector.PLUS :
      case Selector.MINUS :
      case Selector.TIMES :
      case Selector.DIV :
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type is ARITHMETIC");          
        theReturn = promoteAndEvaluate(op.getOp(), val0, val1, permissive);
        if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
          tc.exit(cclass, "evalInternal", theReturn);         
        return theReturn;
      case Selector.AND :
      case Selector.OR :
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type is ANDOR");          
        if (!(val0 instanceof Boolean)) // was BooleanValue
          if (permissive && val0 != null)
            val0 = castToBoolean(val0);
        if (!(val1 instanceof Boolean)) // was BooleanValue
          if (permissive && val1 != null)
            val1 = castToBoolean(val1);
        if (op.getOp() == Operator.AND)
          theReturn = and((Boolean) val0, (Boolean) val1);
        else
          theReturn = or((Boolean) val0, (Boolean) val1);
        if (tc.isAnyTracingEnabled() && tc.isEntryEnabled())
          tc.exit(cclass, "evalInternal", theReturn);         
        return theReturn;        
      default :
        // Should not occur
        if (tc.isAnyTracingEnabled() && tc.isDebugEnabled())
          tc.debug(cclass, "Selector type is DEFAULT");          
        throw new IllegalStateException();
    }
  }
350546
function() {
      var t = this,
          newValue = t.eval_control(t.key, t.depth);

      // Set the new value if it has changed from the current value
      if (!_.isEqual(newValue, t.get('value'))) {
        t.set({value: newValue});
      }
    }
1113479
def evaluate(self, node: InstanceNode) -> XPathValue:
        
        return self._eval(XPathContext(node, node, 1, 1))
86247
def visit_Slice(self, node: ast.Slice) -> slice:
        """"""
        lower = None  # type: Optional[int]
        if node.lower is not None:
            lower = self.visit(node=node.lower)

        upper = None  # type: Optional[int]
        if node.upper is not None:
            upper = self.visit(node=node.upper)

        step = None  # type: Optional[int]
        if node.step is not None:
            step = self.visit(node=node.step)

        result = slice(lower, upper, step)

        self.recomputed_values[node] = result
        return result
400369
def _eval_unaryop(self, node):
        
        return self.operators[type(node.op)](self._eval(node.operand))
406435
private Node tryReplaceUndefined(Node n) {
    // TODO(johnlenz): consider doing this as a normalization.
    if (isASTNormalized()
        && NodeUtil.isUndefined(n)
        && !NodeUtil.isLValue(n)) {
      Node replacement = NodeUtil.newUndefinedNode(n);
      n.replaceWith(replacement);
      reportChangeToEnclosingScope(replacement);
      return replacement;
    }
    return n;
  }
1355008
function (value, node) {
        return (
               this.exec_spec(value, node.op1)  /*  RECURSION  */
            || this.exec_spec(value, node.op2)  /*  RECURSION  */
        );
    }
446271
function _walk(node) {
				var i,
					l,
					child,
					s,
					state,
					allSelected,
					someSelected,
					unselIgnore,
					unselState,
					children = node.children;

				if (children && children.length) {
					// check all children recursively
					allSelected = true;
					someSelected = false;

					for (i = 0, l = children.length; i < l; i++) {
						child = children[i];
						// the selection state of a node is not relevant; we need the end-nodes
						s = _walk(child);
						// if( !child.unselectableIgnore ) {
						unselIgnore = FT.evalOption(
							"unselectableIgnore",
							child,
							child,
							opts,
							false
						);
						if (!unselIgnore) {
							if (s !== false) {
								someSelected = true;
							}
							if (s !== true) {
								allSelected = false;
							}
						}
					}
					state = allSelected
						? true
						: someSelected
							? undefined
							: false;
				} else {
					// This is an end-node: simply report the status
					unselState = FT.evalOption(
						"unselectableStatus",
						node,
						node,
						opts,
						undefined
					);
					state = unselState == null ? !!node.selected : !!unselState;
				}
				node._changeSelectStatusAttrs(state);
				return state;
			}
478392
function mapLoops(node, path, down) {
        var depth = node.$depth;
        if (node.type === 'ForInStatement' && containsAwait(node)) {
            transformForIn(node, path);
        } else if (node.type === 'ForOfStatement' && containsAwait(node)) {
            iterizeForOf(node, path);
        }
        // Are we inside a loop that has already been asynchronized and is labelled?
        var inAsyncLoop = path.some(function (p) {
            return '$label' in p.self && p.self.type === 'ForStatement' && p.self.$mapped;
        });
        // Check if the loop contains an await, or a labelled exit if we're inside an async loop
        function mappableLoop(n) {
            return n.type === 'AwaitExpression' && !n.$hidden || inAsyncLoop && (n.type === 'BreakStatement' || n.type === 'ContinueStatement') && n.label;
        }
        
        if (!node.$mapped && examine(node).isLoop && contains(node, mappableLoop)) {
            path[0].self.$mapped = true;
            var p;
            var mapped = [];
            var init = node.init;
            var test = node.test || literal(true);
            var step = node.update;
            var body = node.body;
            var localised = init && init.type === 'VariableDeclaration' && (init.kind === 'let' || init.kind === 'const');
            if (localised) {
                init.kind = 'let';
            }
            if (step) {
                step = {
                    type: 'ExpressionStatement',
                    expression: step
                };
            }
            if (init) {
                if (!examine(init).isStatement) {
                    init = {
                        type: 'ExpressionStatement',
                        expression: init
                    };
                }
                if (!localised) 
                    mapped.push(init);
            }
            var ref, label;
            if (node.$label) {
                label = node.$label.name;
                ref = path[1];
            } else {
                label = generatedSymbol++;
                ref = path[0];
            }
            label = opts.generatedSymbolPrefix + "Loop_" + label;
            var idLocal = localised ? ident(label + "_local"):null ;
            var idTrampoline = ident(label + "_trampoline");
            var idIter = ident(label);
            var idStep = step ? ident(label + "_step") : idIter;
            var idContinuation = ident(label + "_exit");
            var idBounce = ident("q");
            var idCatchParam = ident("$exception");
            var continuation, deferredCode;
            if ('index' in ref) {
                var idx = ref.index;
                deferredCode = ref.parent[ref.field].splice(idx + 1, ref.parent[ref.field].length - (idx + 1));
            } else {
                deferredCode = [];
            }
            continuation = makeContinuation(idContinuation, deferredCode);
            var initIter = localised ? parsePart("$0.bind(this,$1)", [idIter,init ? init.declarations.map(function (d) {
                return d && d.init ? d.init : ident("undefined");
            }) : []]).expr : idIter;
            var returnStep = parsePart("return $0", [idStep]).body[0];
            var returnBreak = {
                type: 'ReturnStatement',
                argument: {
                    "type": "ArrayExpression",
                    "elements": [literal(1)]
                }
            };
            treeWalk(body, function mapExits(n, descend, subpath) {
                if (examine(n).isFunction || examine(n).isLoop) {
                    return true;
                } else if (n.type === 'BreakStatement' || n.type === 'ContinueStatement') {
                    if (n.label) {
                        var labelStack = subpath.filter(function (p) {
                            return '$label' in p.self;
                        }).map(function (p, idx) {
                            return p.self.$label && p.self.$label.name;
                        });
                        // Work out how many loops to exit by examining subpath.
                        var loops = [];
                        for (var l = 0;l < labelStack.length; l++) {
                            if (labelStack[l] === n.label.name) {
                                if (n.type === 'BreakStatement') 
                                    loops.push(literal(1));
                                subpath[0].replace({
                                    type: 'ReturnStatement',
                                    argument: {
                                        "type": "ArrayExpression",
                                        "elements": loops.reverse()
                                    }
                                });
                                break;
                            }
                            loops.push(literal(0));
                        }
                    } else {
                        if (n.type === 'BreakStatement') 
                            subpath[0].replace(returnBreak);
                         else 
                            subpath[0].replace(returnStep); //  continue;
                    }
                } else {
                    descend();
                }
            }, path);
            if (body.type === 'BlockStatement') 
                body = body.body.slice(0);
             else 
                body = [body];
            if (node.type === 'DoWhileStatement') {
                body = body.concat({
                    "type": "IfStatement",
                    "test": {
                        type: 'UnaryExpression',
                        argument: test,
                        prefix: true,
                        operator: '!'
                    },
                    "consequent": returnBreak,
                    alternate: returnStep
                });
            } else {
                body = [{
                    "type": "IfStatement",
                    "test": test,
                    "consequent": {
                        "type": "BlockStatement",
                        "body": body.concat(returnStep)
                    },
                    alternate: returnBreak
                }];
            }
            var decls = [];
            if (opts.noRuntime) 
                decls.push({
                "type": "VariableDeclarator",
                "id": idTrampoline
            });
            if (step && localised) 
                decls.push({
                "type": "VariableDeclarator",
                "id": idLocal
            });
            if (decls.length) 
                mapped.push({
                "type": "VariableDeclaration",
                "declarations": decls,
                "kind": "var"
            });
            var invokeIterate;
            var exit = getExit(path, [opts]).$error;
            if (opts.noRuntime) {
                invokeIterate = parsePart(
	                opts.es6target?
	                    "($idTrampoline = ((q) => { "+
	                    "    $$setMapped: while (q) { "+
	                    "         if (q.then)  "+
	                    (depth===1?
	                    "             return void q.then($idTrampoline, $exit); ":
	                    "             return q.then($idTrampoline, $exit); ")+
	                    "         try { "+
	                    "             if (q.pop)  "+
	                    "                 if (q.length)  "+
	                    "                 return q.pop() ? $idContinuation.call(this) : q; "+
	                    "              else  "+
	                    "                 q = $idStep; "+
	                    "              else  "+
	                    "                 q = q.call(this) "+
	                    "          } catch (_exception) { "+
	                    "             return $exit(_exception); "+
	                    "          } "+
	                    "     } "+
	                    "}))($idIter)":
	                    "($idTrampoline = (function (q) { "+
	                    "    $$setMapped: while (q) { "+
	                    "         if (q.then)  "+
	                    (depth===1?
	                    "             return void q.then($idTrampoline, $exit); ":
	                    "             return q.then($idTrampoline, $exit); ")+
	                    "         try { "+
	                    "             if (q.pop)  "+
	                    "                 if (q.length)  "+
	                    "                 return q.pop() ? $idContinuation.call(this) : q; "+
	                    "              else  "+
	                    "                 q = $idStep; "+
	                    "              else  "+
	                    "                 q = q.call(this) "+
	                    "          } catch (_exception) { "+
	                    "             return $exit(_exception); "+
	                    "          } "+
	                    "     } "+
	                    "}).bind(this))($idIter)",
                {
                    setMapped: function (n) {
                        n.$mapped = true;
                        return n;
                    },
                    idTrampoline: idTrampoline,
                    exit: exit,
                    idIter: initIter,
                    idContinuation: idContinuation,
                    idStep: idStep
                }).expr;
            } else {
                invokeIterate = parsePart("($0.$1.trampoline(this,$2,$3,$4,$6)($5))", [opts.$runtime ? genIdent.runtime : ident('Function'),
                    genIdent.asyncbind,idContinuation,idStep,
                    exit,initIter,literal(depth === 1)]).expr;
            }
            var iterDecls = init && init.declarations ? init.declarations.map(function (d) {
                return d.id;
            }) : [];
            if (step) {
                var stepArgs = {
                    idIter: idIter,
                    idStep: idStep,
                    step: step,
                    idLocal: idLocal,
                    decId: iterDecls
                };
                if (localised) {
                    stepArgs.iterDecls = iterDecls;
                    mapped.push(parsePart(step.expression.$EmptyExpression ? 
                    		(opts.es6target ? "function $idStep(){ return $idIter.bind(this,...$idLocal()) }" : "function $idStep(){ var [$decId] = $idLocal(); return $idIter.bind(this,$decId) }") :
                    		"function $idStep(){ var [$decId] = $idLocal(); $:step; return $idIter.bind(this,$decId) }", stepArgs).body[0]);
                    body.unshift(parsePart("$idLocal = function(){ return [$decId] }", stepArgs).body[0]);
                } else {
                    mapped.push(parsePart(step.expression.$EmptyExpression ? "function $idStep(){ return $idIter }" : "function $idStep(){ $:step; return $idIter }", stepArgs).body[0]);
                }
            }
            mapped.push({
                $label: node.$label,
                "type": "FunctionDeclaration",
                "id": idIter,
                "params": localised ? iterDecls : [],
                "body": {
                    "type": "BlockStatement",
                    "body": body
                }
            });
            mapped.push({
                type: 'ReturnStatement',
                argument: invokeIterate
            });
            mapped.push(continuation);
            path[0].replace(mapped.map(down));
        }
    }
527980
function(scope, defaultValue) {
            var val = evaluator(tree, scope);
            if( typeof defaultValue === 'undefined') {
                return val;
            } else {
                return (val === undefined || val === null || val != val) ? defaultValue : val;
            }
        }