private SpokeMethodCall checkRunMacro(TokenEnumerator enumerator, int tabIndex, evalInformation inf)
		{
			//tm.


			for (int index = 0; ; index++)
			{
			gombo:
				if (index >= allMacros_.Count)
					break;
				var tokenMacroPiece = allMacros_[index];
				List<SpokeItem> parameters = new List<SpokeItem>();
				var tm = enumerator.Clone();
				var outs = tm.OutstandingLine;
				bool bad = false;
				for (int i = 0; i < tokenMacroPiece.Macro.Length; i++)
				{
					var mp = tokenMacroPiece.Macro[i];

					if (mp.Type == Token.Ampersand)
					{

						for (int j = i + 1; j < tokenMacroPiece.Macro.Length; j++)
						{
							var r = tokenMacroPiece.Macro[j];
							

							
							
							if (!outs.Any(a => r.Type == Token.Ampersand || (a.Type == r.Type && (a.Type == Token.Word && r.Type == Token.Word ? ((TokenWord)a).Word == ((TokenWord)r).Word : true))))
							{
								bad = true;
								break;
							}
						}
						if (bad)
						{
							break;
						}


						var frf = tokenMacroPiece.Macro.Length == i + 1 ? new TokenNewLine() : tokenMacroPiece.Macro[i + 1];

						int selectedLine = 0;

						IToken tp = null;
						int selectedToken = tm.tokenIndex;
						if (frf.Type != Token.NewLine)
						{
							for (int j = 0; j < tm.CurrentLines.Count; j++)
							{

								for (int ic = selectedToken; ic < tm.CurrentLines[j].Tokens.Count; ic++)
								{
									var a = tm.CurrentLines[j].Tokens[ic];

									if (tm.CurrentLines[j].Tokens[ic].Type == frf.Type &&
										(a.Type == frf.Type &&
										 (a.Type == Token.Word && frf.Type == Token.Word
											  ? ((TokenWord)a).Word == ((TokenWord)frf).Word
											  : true)))
									{
										tp = tm.CurrentLines[j].Tokens[ic];
										break;
									}
								}

								if (tp != null)
								{
									selectedLine = j;
									break;
								}
								else
								{
									selectedToken = 0;
								}
							}

							var bf = new TokenAmpersand();
							tm.CurrentLines[selectedLine].Tokens.Insert(tm.CurrentLines[selectedLine].Tokens.IndexOf(tp), bf);
							try
							{
								CurrentItem = null;
								var d = eval(tm, tabIndex, new evalInformation(inf) { CheckMacs = inf.CheckMacs + 1, DontEvalEquals = true, BreakBeforeEqual = true });
								parameters.Add((SpokeItem)d);
								if (d == null || (!(tm.Current.Type == Token.Ampersand || tokenMacroPiece.Macro.Length == i + 1)))
								{
									index++;
									goto gombo;
								}
							}
							catch (Exception e)
							{
								index++;
								goto gombo;
							}
							tm.CurrentLine.Tokens.Remove(bf);


						}
						else
						{
							try
							{
								CurrentItem = null;
								var d = eval(tm, tabIndex, new evalInformation(inf) { CheckMacs = inf.CheckMacs + 1, DontEvalEquals = true, BreakBeforeEqual = true });
								parameters.Add((SpokeItem)d);
								if (d == null)
								{
									index++;
									goto gombo;
								}
							}
							catch (Exception e)
							{
								index++;
								goto gombo;
							}

						}
					}
					else
					{
						if (mp.Type == tm.Current.Type && (mp.Type == Token.Word && tm.Current.Type == Token.Word ? ((TokenWord)mp).Word == ((TokenWord)tm.Current).Word : true))
						{
							tm.MoveNext();
						}
						else
						{
							bad = true;
							break;
						}
					}
				}
				if (!bad)
				{
					SpokeMethodCall ambe = new SpokeMethodCall();
					SpokeAnonMethod me = new SpokeAnonMethod();
					me.SpecAnon = true;
					me.Parameters = tokenMacroPiece.Parameters;
					me.Lines = getLines(new TokenEnumerator(tokenMacroPiece.Lines.ToArray()), 1, inf).ToArray();

					me.HasYieldReturn = linesHave(me.Lines, ISpokeLine.YieldReturn);
					me.HasYield = linesHave(me.Lines, ISpokeLine.Yield);
					me.HasReturn = linesHave(me.Lines, ISpokeLine.Return);

					ambe.Parent = me;
					parameters.Insert(0, new SpokeCurrent());

					ambe.Parameters = parameters.ToArray();

					enumerator.Set(tm);
					return ambe;
				}
			}
			return null;
		}
		public Spoke eval(TokenEnumerator enumerator, int tabIndex, evalInformation inf)
		{
			if (inf.ResetCurrentVal)
			{
				CurrentItem = null;
			}
#if DEBUGs
			sb.AppendLine("Starting Eval " + enumerator.Current.Type);
#endif


			if (inf.CheckMacs < 2)
			{
				var df = CurrentItem;
				CurrentItem = null;
				var rm = checkRunMacro(enumerator, tabIndex, inf);
				if (rm != null)
				{
					CurrentItem = rm;
				}
				else CurrentItem = df;
			}




			



			switch (enumerator.Current.Type)
			{
				case Token.Word:

					if (((TokenWord)enumerator.Current).Word.ToLower() == "null")
					{
						CurrentItem = new SpokeNull();

					}
					else CurrentItem = new SpokeVariable() { Parent = CurrentItem, VariableName = ((TokenWord)enumerator.Current).Word }; 
					enumerator.MoveNext(); 
					break;
				case Token.Int:
					CurrentItem = new SpokeInt() { Value = ((TokenInt)enumerator.Current)._value };
					enumerator.MoveNext();
					break;
				case Token.Float:
					CurrentItem = new SpokeFloat() { Value = ((TokenFloat)enumerator.Current)._value };
					enumerator.MoveNext();
					break;
				case Token.String:
					CurrentItem = new SpokeString() { Value = ((TokenString)enumerator.Current)._value };
					enumerator.MoveNext();
					break;
				case Token.False:
					CurrentItem = new SpokeBool() { Value = false };
					enumerator.MoveNext();
					break;
				case Token.True:
					CurrentItem = new SpokeBool() { Value = true };
					enumerator.MoveNext();
					break;
				case Token.OpenParen:
					enumerator.MoveNext();

					CurrentItem = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf));


					if (enumerator.Current.Type == Token.Tab)
					{
						enumerator.MoveNext();

					}


					if (enumerator.Current.Type != Token.CloseParen)
					{
						throw new AbandonedMutexException();

					}
					enumerator.MoveNext();

					break;


				case Token.Switch:
					return (SpokeLine)evaluateSwitch(enumerator, tabIndex, inf);

				case Token.If:
					enumerator.MoveNext();

					var i_f = new SpokeIf() { Condition = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf)) };
					enumerator.MoveNext();
					i_f.IfLines = getLines(enumerator, tabIndex + 1, new evalInformation(inf)).ToArray();
					StaticMethods.Assert(enumerator.Current.Type == Token.NewLine || enumerator.Current.Type == Token.EndOfCodez, enumerator.Current.Type + " Isnt Newline");
					enumerator.MoveNext();

					if (enumerator.Current.Type == Token.Tab && enumerator.PeakNext().Type == Token.Else)
					{
						enumerator.MoveNext();
						enumerator.MoveNext();
						i_f.ElseLines = getLines(enumerator, tabIndex + 1, new evalInformation(inf)).ToArray();
						StaticMethods.Assert(enumerator.Current.Type == Token.NewLine || enumerator.Current.Type == Token.EndOfCodez, enumerator.Current.Type + " Isnt Newline");
						enumerator.MoveNext();

					}

					if (enumerator.Current.Type == Token.Tab && inf.EatTab)
						enumerator.MoveNext();
					return i_f;

					break;
				case Token.Bar:

					var an = new SpokeAnonMethod() { Parent = CurrentItem };
					enumerator.MoveNext();
					StaticMethods.Assert(enumerator.Current.Type == Token.OpenParen, enumerator.Current.Type + " Isnt OpenParen");
					List<ParamEter> parameters_ = new List<ParamEter>();
					enumerator.MoveNext();
					if (enumerator.Current.Type != Token.CloseParen)
					{
					pback2:
						bool byRe_f = false;

						if (((TokenWord)enumerator.Current).Word.ToLower() == "ref")
						{
							byRe_f = true;
							enumerator.MoveNext();

						}
						parameters_.Add(new ParamEter() { ByRef = byRe_f, Name = ((TokenWord)enumerator.Current).Word });

						enumerator.MoveNext();
						switch (enumerator.Current.Type)
						{
							case Token.CloseParen:
								enumerator.MoveNext();
								break;
							case Token.Comma:
								enumerator.MoveNext();
								goto pback2;
								break;
							default:
								throw new ArgumentOutOfRangeException();
						}
					}


					an.Parameters = parameters_.ToArray();


					StaticMethods.Assert(enumerator.Current.Type == Token.AnonMethodStart, enumerator.Current.Type + " Isnt anonmethodstart");
					enumerator.MoveNext();

					StaticMethods.Assert(enumerator.Current.Type == Token.NewLine, enumerator.Current.Type + " Isnt Newline");
					enumerator.MoveNext();
					an.Lines = getLines(enumerator, tabIndex + 1, new evalInformation(inf)).ToArray();
					StaticMethods.Assert(enumerator.Current.Type == Token.NewLine || enumerator.Current.Type == Token.EndOfCodez, enumerator.Current.Type + " Isnt Newline");
					enumerator.MoveNext();
					an.HasYield = linesHave(an.Lines, ISpokeLine.Yield);
					an.HasReturn = linesHave(an.Lines, ISpokeLine.Return);
					an.HasYieldReturn = linesHave(an.Lines, ISpokeLine.YieldReturn);


					StaticMethods.Assert(enumerator.Current.Type == Token.Tab && ((TokenTab)enumerator.Current).TabIndex == tabIndex, "Bad tabindex");
					if (enumerator.Current.Type == Token.Tab && inf.EatTab)
						enumerator.MoveNext();
					if (enumerator.PeakNext().Type != Token.CloseParen)
					{
						return an;
					}
					else
					{
						enumerator.MoveNext();
						CurrentItem = an;
					}


					break;

				case Token.OpenSquare:
					CurrentItem = dyanmicArray(enumerator, tabIndex, inf);
					break;

				case Token.OpenCurly:
					CurrentItem = new SpokeConstruct();
					CurrentItem = dynamicObject(enumerator, tabIndex, inf);
					break;
				case Token.Create:

					return createObject(enumerator, tabIndex, inf);
					break;
				case Token.Return:
					enumerator.MoveNext();

					var r = new SpokeReturn() { Return = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf)) };
					enumerator.MoveNext();
					return r;
				case Token.Yield:
					enumerator.MoveNext();
					if (enumerator.Current.Type == Token.Return)
					{
						enumerator.MoveNext();
						var y = new SpokeYieldReturn() { YieldReturn = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf)) };
						enumerator.MoveNext();
						return y;
					}
					else
					{
						var y = new SpokeYield() { Yield = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf)) };
						enumerator.MoveNext();
						return y;
					}
			}


#if DEBUGs
			sb.AppendLine("Checking Eval 1" + enumerator.Current.Type);
#endif

			switch (enumerator.Current.Type)
			{
				case Token.OpenSquare:
					var ar = new SpokeArrayIndex();
					ar.Parent = CurrentItem;

					enumerator.MoveNext();

					ar.Index = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEqual = false, ResetCurrentVal = true });

					StaticMethods.Assert(enumerator.Current.Type == Token.CloseSquare, enumerator.Current.Type + " Isnt closesquare");
					enumerator.MoveNext();

					if (enumerator.Current.Type == Token.OpenSquare)
					{

					}

					CurrentItem = ar;

					break;
				case Token.OpenParen:
					var meth = new SpokeMethodCall() { Parent = CurrentItem };
					enumerator.MoveNext();
					List<SpokeItem> param_ = new List<SpokeItem>();
					param_.Add(new SpokeCurrent());
					CurrentItem = null;
					if (enumerator.Current.Type != Token.CloseParen)
					{
					g:
						param_.Add((SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { ResetCurrentVal = true }));
						if (enumerator.Current.Type == Token.Comma)
						{
							enumerator.MoveNext();
							goto g;
						}

					}
					enumerator.MoveNext();//closeparen

					meth.Parameters = param_.ToArray();

					CurrentItem = meth;
					//loop params
					break;
				case Token.Period:
					var t = CurrentItem;
					enumerator.MoveNext();
					SpokeParent g;
					Spoke c;
					CurrentItem = g = (SpokeParent)(c = eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEvaler = true }));
					//g.Parent = t;

					//enumerator.MoveNext();
					break;

			}
			switch (enumerator.Current.Type)
			{
				case Token.Period:
					var t = CurrentItem;
					enumerator.MoveNext();
					SpokeParent g;
					Spoke c;
					CurrentItem = g = (SpokeParent)(c = eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEvaler = true }));
					//g.Parent = t;

					//enumerator.MoveNext();
					break;

			}

#if DEBUGs
			sb.AppendLine("Checking Eval 2" + enumerator.Current.Type);
#endif

		forMethods:
			switch (enumerator.Current.Type)
			{
				case Token.OpenParen:
					var meth = new SpokeMethodCall() { Parent = CurrentItem };
					enumerator.MoveNext();
					List<SpokeItem> param_ = new List<SpokeItem>();
					param_.Add(new SpokeCurrent());
				g:
					param_.Add((SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { ResetCurrentVal = true }));
					if (enumerator.Current.Type == Token.Comma)
					{
						enumerator.MoveNext();
						goto g;
					}

					enumerator.MoveNext();//closeparen

					meth.Parameters = param_.ToArray();

					CurrentItem = meth;


					goto forMethods;
			}

#if DEBUGs
			sb.AppendLine("Checking Eval 3" + enumerator.Current.Type);
#endif
			if (inf.BreakBeforeEvaler)
			{
				return CurrentItem;
			}


			if (!inf.DontEvalEquals)
			{
				if (enumerator.Current.Type == Token.Equal)
				{

					var equ = new SpokeEqual() { LeftSide = CurrentItem };
					enumerator.MoveNext();

					equ.RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { EatTab = false, ResetCurrentVal = true });

					if (enumerator.Current.Type == Token.NewLine)
					{
						//   enumerator.MoveNext();  //newline        
					}


					return equ;


				}

			}

			switch (enumerator.Current.Type)
			{
				case Token.AnonMethodStart:
					//checkparams
					//getlines
					var an = new SpokeAnonMethod() { Parent = CurrentItem };
					enumerator.MoveNext();
					if (enumerator.Current.Type == Token.Bar)
					{
						enumerator.MoveNext();
						StaticMethods.Assert(enumerator.Current.Type == Token.OpenParen, enumerator.Current.Type + " Isnt openparen");

						List<ParamEter> parameters_ = new List<ParamEter>();
						enumerator.MoveNext();
					pback2:

						bool byRe_f = false;

						if (((TokenWord)enumerator.Current).Word.ToLower() == "ref")
						{
							byRe_f = true;
							enumerator.MoveNext();

						}
						parameters_.Add(new ParamEter() { ByRef = byRe_f, Name = ((TokenWord)enumerator.Current).Word });
						enumerator.MoveNext();
						switch (enumerator.Current.Type)
						{
							case Token.CloseParen:
								enumerator.MoveNext();
								break;
							case Token.Comma:
								enumerator.MoveNext();
								goto pback2;
								break;
							default:
								throw new ArgumentOutOfRangeException();
						}
						an.Parameters = parameters_.ToArray();
					}
					else
					{
						an.RunOnVar = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { ResetCurrentVal = true, BreakBeforeEqual = false, BreakBeforeEvaler = true });
					}

					StaticMethods.Assert(enumerator.Current.Type == Token.NewLine, enumerator.Current.Type + " Isnt Newline");
					enumerator.MoveNext();
					CurrentItem = null;
					an.Lines = getLines(enumerator, tabIndex + 1, new evalInformation(inf)).ToArray();
					an.HasYield = linesHave(an.Lines, ISpokeLine.Yield);
					an.HasReturn = linesHave(an.Lines, ISpokeLine.Return);
					an.HasYieldReturn = linesHave(an.Lines, ISpokeLine.YieldReturn);
					StaticMethods.Assert(enumerator.Current.Type == Token.NewLine || enumerator.Current.Type == Token.EndOfCodez, enumerator.Current.Type + " Isnt Newline");
					enumerator.MoveNext();

					if (enumerator.Current.Type == Token.Tab && inf.EatTab)
						enumerator.MoveNext();

					CurrentItem = an;
					break;
			}
			//    5*6-7+8/9+10
			switch (enumerator.Current.Type)
			{
				case Token.Plus:

					enumerator.MoveNext();

					CurrentItem = new SpokeAddition() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEqual = true, ResetCurrentVal = true }) };

					break;
				case Token.Minus:
					enumerator.MoveNext();
					CurrentItem = new SpokeSubtraction() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEqual = true, ResetCurrentVal = true }) };

					break;
				case Token.Divide:
					enumerator.MoveNext();
					CurrentItem = new SpokeDivision() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEqual = true, ResetCurrentVal = true }) };

					break;
				case Token.Mulitply:
					enumerator.MoveNext();
					CurrentItem = new SpokeMultiplication() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEqual = true, ResetCurrentVal = true }) };

					break;
			}

			if (inf.BreakBeforeEqual)
			{
				return CurrentItem;
			}



			switch (enumerator.Current.Type)
			{
				case Token.DoubleOr:
					enumerator.MoveNext();
					CurrentItem = new SpokeOr() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { ResetCurrentVal = true }) };

					break;
				case Token.DoubleAnd:
					enumerator.MoveNext();
					CurrentItem = new SpokeAnd() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { ResetCurrentVal = true }) };

					break;

			}

#if DEBUGs
			sb.AppendLine("Checking Eval 4" + enumerator.Current.Type);
#endif
			SpokeItem e;
			switch (enumerator.Current.Type)
			{
				case Token.DoubleEqual:
					enumerator.MoveNext();
					e = new SpokeEquality() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEqual = true, ResetCurrentVal = true }) };

					CurrentItem = e;

					break;
				case Token.NotEqual:
					enumerator.MoveNext();
					e = new SpokeNotEqual() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEqual = true, ResetCurrentVal = true }) };

					CurrentItem = e;

					break;
				case Token.Less:
					enumerator.MoveNext();
					if (enumerator.Current.Type == Token.Equal)
					{
						enumerator.MoveNext();
						e = new SpokeLessThanOrEqual() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEqual = true, ResetCurrentVal = true }) };

						CurrentItem = e;
						break;
					}
					e = new SpokeLessThan() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEqual = true, ResetCurrentVal = true }) };

					CurrentItem = e;
					break;
				case Token.Greater:
					enumerator.MoveNext();
					if (enumerator.Current.Type == Token.Equal)
					{
						enumerator.MoveNext();
						e = new SpokeGreaterThanOrEqual() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEqual = true, ResetCurrentVal = true }) };

						CurrentItem = e;
						break;
					}
					e = new SpokeGreaterThan() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { BreakBeforeEqual = true, ResetCurrentVal = true }) };

					CurrentItem = e;
					break;

			}
			switch (enumerator.Current.Type)
			{
				case Token.DoubleOr:
					enumerator.MoveNext();
					CurrentItem = new SpokeOr() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { ResetCurrentVal = true }) };

					break;
				case Token.DoubleAnd:
					enumerator.MoveNext();
					CurrentItem = new SpokeAnd() { LeftSide = CurrentItem, RightSide = (SpokeItem)eval(enumerator, tabIndex, new evalInformation(inf) { ResetCurrentVal = true }) };

					break;

			}


			return CurrentItem;



		}