function(helperOptions) {
	// lookup

	// TODO: remove in prod
	// make sure we got called with the right stuff
	if(helperOptions.exprData.argExprs.length !== 1) {
		throw new Error("for(of) broken syntax");
	}

	// TODO: check if an instance of helper;

	var helperExpr = helperOptions.exprData.argExprs[0].expr;
	var variableName, valueLookup, valueObservable;
	if(helperExpr instanceof expression.Lookup) {

		valueObservable = helperExpr.value(helperOptions.scope);

	} else if(helperExpr instanceof expression.Helper) {
		// TODO: remove in prod
		var inLookup = helperExpr.argExprs[0];
		if(inLookup.key !== "of") {
			throw new Error("for(of) broken syntax");
		}
		variableName = helperExpr.methodExpr.key;
		valueLookup = helperExpr.argExprs[1];
		valueObservable = valueLookup.value(helperOptions.scope);
	}

	var items =  valueObservable;

	var args = [].slice.call(arguments),
		options = args.pop(),
		resolved = bindAndRead(items);

	if(resolved && !canReflect.isListLike(resolved)) {
		return forOfObject(resolved,variableName, helperOptions);
	}
	if(options.stringOnly) {
		var parts = [];
		canReflect.eachIndex(resolved, function(value, index){
			var variableScope = {};
			if(variableName !== undefined){
				variableScope[variableName] = value;
			}
			parts.push(
				helperOptions.fn( options.scope
					.add({ index: index }, { special: true })
					.addLetContext(variableScope) )
			);
		});
		return parts.join("");
	} else {
		// Tells that a helper has been called, this function should be returned through
		// checking its value.
		options.metadata.rendered = true;
		return function(el){
			// make a child nodeList inside the can.view.live.html nodeList
			// so that if the html is re
			var nodeList = [el];
			nodeList.expression = "live.list";
			nodeLists.register(nodeList, null, options.nodeList, true);
			// runs nest replacements
			nodeLists.update(options.nodeList, [el]);


			var cb = function (item, index, parentNodeList) {
				var variableScope = {};
				if(variableName !== undefined){
					variableScope[variableName] = item;
				}
				return options.fn(
					options.scope
					.add({ index: index }, { special: true })
					.addLetContext(variableScope),
				options.options,
				parentNodeList
				);
			};

			live.list(el, items, cb, options.context, el.parentNode, nodeList, function(list, parentNodeList){
				return options.inverse(options.scope, options.options, parentNodeList);
			});
		};
	}
}
function(helperOptions) {
	

	
	
	if(helperOptions.exprData.argExprs.length !== 1) {
		throw new Error("for(of) broken syntax");
	}

	

	var helperExpr = helperOptions.exprData.argExprs[0].expr;
	var variableName, valueLookup, valueObservable;
	if(helperExpr instanceof expression.Lookup) {

		valueObservable = helperExpr.value(helperOptions.scope);

	} else if(helperExpr instanceof expression.Helper) {
		
		var inLookup = helperExpr.argExprs[0];
		if(inLookup.key !== "of") {
			throw new Error("for(of) broken syntax");
		}
		variableName = helperExpr.methodExpr.key;
		valueLookup = helperExpr.argExprs[1];
		valueObservable = valueLookup.value(helperOptions.scope);
	}

	var items =  valueObservable;

	var args = [].slice.call(arguments),
		options = args.pop(),
		resolved = bindAndRead(items);

	if(resolved && !canReflect.isListLike(resolved)) {
		return forOfObject(resolved,variableName, helperOptions);
	}
	if(options.stringOnly) {
		var parts = [];
		canReflect.eachIndex(resolved, function(value, index){
			var variableScope = {};
			if(variableName !== undefined){
				variableScope[variableName] = value;
			}
			parts.push(
				helperOptions.fn( options.scope
					.add({ index: index }, { special: true })
					.addLetContext(variableScope) )
			);
		});
		return parts.join("");
	} else {
		
		
		options.metadata.rendered = true;
		return function(el){
			
			
			var nodeList = [el];
			nodeList.expression = "live.list";
			nodeLists.register(nodeList, null, options.nodeList, true);
			
			nodeLists.update(options.nodeList, [el]);


			var cb = function (item, index, parentNodeList) {
				var variableScope = {};
				if(variableName !== undefined){
					variableScope[variableName] = item;
				}
				return options.fn(
					options.scope
					.add({ index: index }, { special: true })
					.addLetContext(variableScope),
				options.options,
				parentNodeList
				);
			};

			live.list(el, items, cb, options.context, el.parentNode, nodeList, function(list, parentNodeList){
				return options.inverse(options.scope, options.options, parentNodeList);
			});
		};
	}
}
function ( helperOptions ) { // lookup // TODO: remove in prod // make sure we got called with the right stuff if ( helperOptions . exprData . argExprs . length !== 1 ) { throw new Error ( "for(of) broken syntax" ) ; } // TODO: check if an instance of helper; var helperExpr = helperOptions . exprData . argExprs [ 0 ] . expr ; var variableName , valueLookup , valueObservable ; if ( helperExpr instanceof expression . Lookup ) { valueObservable = helperExpr . value ( helperOptions . scope ) ; } else if ( helperExpr instanceof expression . Helper ) { // TODO: remove in prod var inLookup = helperExpr . argExprs [ 0 ] ; if ( inLookup . key !== "of" ) { throw new Error ( "for(of) broken syntax" ) ; } variableName = helperExpr . methodExpr . key ; valueLookup = helperExpr . argExprs [ 1 ] ; valueObservable = valueLookup . value ( helperOptions . scope ) ; } var items = valueObservable ; var args = [ ] . slice . call ( arguments ) , options = args . pop ( ) , resolved = bindAndRead ( items ) ; if ( resolved && ! canReflect . isListLike ( resolved ) ) { return forOfObject ( resolved , variableName , helperOptions ) ; } if ( options . stringOnly ) { var parts = [ ] ; canReflect . eachIndex ( resolved , function ( value , index ) { var variableScope = { } ; if ( variableName !== undefined ) { variableScope [ variableName ] = value ; } parts . push ( helperOptions . fn ( options . scope . add ( { index : index } , { special : true } ) . addLetContext ( variableScope ) ) ) ; } ) ; return parts . join ( "" ) ; } else { // Tells that a helper has been called, this function should be returned through // checking its value. options . metadata . rendered = true ; return function ( el ) { // make a child nodeList inside the can.view.live.html nodeList // so that if the html is re var nodeList = [ el ] ; nodeList . expression = "live.list" ; nodeLists . register ( nodeList , null , options . nodeList , true ) ; // runs nest replacements nodeLists . update ( options . nodeList , [ el ] ) ; var cb = function ( item , index , parentNodeList ) { var variableScope = { } ; if ( variableName !== undefined ) { variableScope [ variableName ] = item ; } return options . fn ( options . scope . add ( { index : index } , { special : true } ) . addLetContext ( variableScope ) , options . options , parentNodeList ) ; } ; live . list ( el , items , cb , options . context , el . parentNode , nodeList , function ( list , parentNodeList ) { return options . inverse ( options . scope , options . options , parentNodeList ) ; } ) ; } ; } }
this is called with the ast ... we are going to use that to our advantage.
this is called with the ast ... we are going to use that to our advantage .