public Empty Visit(DekiScriptGeneratorForeachKeyValue expr, DekiScriptGeneratorEvaluationState state)
        {
            DekiScriptLiteral collection = Eval(expr.Collection, state);

            // retrieve collection
            Dictionary <string, DekiScriptLiteral> map;

            if (collection is DekiScriptMap)
            {
                // loop over map key-value pairs
                map = ((DekiScriptMap)collection).Value;
            }
            else if (collection is DekiScriptNil)
            {
                // nothing to do
                map = new Dictionary <string, DekiScriptLiteral>();
            }
            else
            {
                throw new DekiScriptBadTypeException(expr.Location, collection.ScriptType, new[] { DekiScriptType.MAP, DekiScriptType.NIL });
            }

            // store state of variables
            var previousKey   = state.State.Env.Vars[expr.Key];
            var previousValue = state.State.Env.Vars[expr.Value];
            var previousIndex = state.State.Env.Vars[DekiScriptRuntime.INDEX_ID];

            try {
                // loop over collection
                int index = 0;
                foreach (KeyValuePair <string, DekiScriptLiteral> entry in map)
                {
                    // set the environment variable
                    state.State.Env.Vars.Add(expr.Key, DekiScriptExpression.Constant(entry.Key));
                    state.State.Env.Vars.Add(expr.Value, entry.Value);
                    state.State.Env.Vars.Add(DekiScriptRuntime.INDEX_ID, DekiScriptExpression.Constant(index));

                    // iterate over block statements
                    EvalNext(expr, state);
                    ++index;
                }
            } finally {
                state.State.Env.Vars.Add(expr.Key, previousKey);
                state.State.Env.Vars.Add(expr.Value, previousValue);
                state.State.Env.Vars.Add(DekiScriptRuntime.INDEX_ID, previousIndex);
            }
            return(Empty.Value);
        }
        public Empty Visit(DekiScriptGeneratorForeachKeyValue expr, DekiScriptGeneratorEvaluationState state)
        {
            DekiScriptLiteral collection = expr.Collection.VisitWith(DekiScriptExpressionEvaluation.Instance, state.Env);

            // retrieve collection
            Dictionary <string, DekiScriptLiteral> map;

            if (collection is DekiScriptMap)
            {
                // loop over map key-value pairs
                map = ((DekiScriptMap)collection).Value;
            }
            else if (collection is DekiScriptNil)
            {
                // nothing to do
                map = new Dictionary <string, DekiScriptLiteral>();
            }
            else
            {
                throw new DekiScriptBadTypeException(expr.Line, expr.Column, collection.ScriptType, new DekiScriptType[] { DekiScriptType.MAP, DekiScriptType.NIL });
            }

            // loop over collection
            int index = 0;

            foreach (KeyValuePair <string, DekiScriptLiteral> entry in map)
            {
                // set the environment variable
                state.Env.Locals.Add(expr.Key, DekiScriptString.New(entry.Key));
                state.Env.Locals.Add(expr.Value, entry.Value);
                state.Env.Locals.Add(DekiScriptRuntime.INDEX_ID, DekiScriptNumber.New(index));

                // iterate over block statements
                Generate(expr, state);
                ++index;
            }
            return(Empty.Value);
        }
	void GeneratorHead(out DekiScriptGenerator gen) {
		Location location = Location.None;
		Location wherelocation = Location.None;
		DekiScriptExpression where = null; 
		List<string> names = new List<string>(); 
		DekiScriptExpression expr = null; 
		string value = null;
		gen = null;
		
		Expect(19);
		location = t.Location; 
		Expect(1);
		names.Add(t.val); 
		if (la.kind == 31) {
			Get();
			Expect(1);
			value = t.val; 
			Expect(52);
			Expression(out expr);
			if (la.kind == 70) {
				Get();
				wherelocation = t.Location; 
				Expression(out where);
			}
		} else if (la.kind == 20 || la.kind == 52) {
			while (la.kind == 20) {
				Get();
				Expect(1);
				names.Add(t.val); 
			}
			Expect(52);
			Expression(out expr);
			if (la.kind == 70) {
				Get();
				wherelocation = t.Location; 
				Expression(out where);
			}
		} else SynErr(80);
		if (la.kind == 20) {
			Get();
			GeneratorNext(out gen);
		}
		if(where != null) gen = new DekiScriptGeneratorIf(wherelocation, where, gen);
		if(value == null) gen = new DekiScriptGeneratorForeachValue(location, names.ToArray(), expr, gen);
		else gen = new DekiScriptGeneratorForeachKeyValue(location, names[0], value, expr, gen);
		
	}