public SwitchStatementUnsafeBlotchy(SwitchStatement switchStatement, bool useExplicitMax, int explicitMax, Executable owner)
			: base(switchStatement.FirstToken, owner)
		{
			this.OriginalSwitchStatement = switchStatement;
			this.Condition = switchStatement.Condition;

			this.UsesStrings = switchStatement.UsesStrings;
			this.UseExplicitMax = useExplicitMax;
			this.ExplicitMax = explicitMax;
			if (this.UsesStrings)
			{
				this.StringUnsafeToSafeMapping = new Dictionary<string, int>();
			}
			else
			{
				this.IntegerUnsafeToSafeMapping = new Dictionary<int, int>();
			}
			this.codeMapping = new Dictionary<int, Executable[]>();
			this.tokenMapping = new Dictionary<int, Token>();

			this.max = switchStatement.Chunks.Length - 1;

			for (int i = 0; i < switchStatement.Chunks.Length; ++i)
			{
				SwitchStatement.Chunk chunk = switchStatement.Chunks[i];
				this.codeMapping[i] = chunk.Code;
				this.tokenMapping[i] = chunk.CaseOrDefaultToken;

				foreach (Expression expression in chunk.Cases)
				{
					if (expression == null)
					{
						this.DefaultCaseId = i;
					}
					else
					{
						IntegerConstant ic = expression as IntegerConstant;
						StringConstant sc = expression as StringConstant;
						if (ic == null && sc == null) throw new Exception("This shouldn't happen.");
						if (ic != null)
						{
							int c = ic.Value;
							this.IntegerUnsafeToSafeMapping[c] = i;
						}
						else
						{
							string s = sc.Value;
							this.StringUnsafeToSafeMapping[s] = i;
						}
					}
				}
			}

			if (useExplicitMax)
			{
				if (this.UsesStrings) throw new Exception("Cannot use explicit max on string switch statements.");
			}
		}
		public SwitchStatementContinuousSafe(SwitchStatement switchStatement, Executable owner)
			: base(switchStatement.FirstToken, owner)
		{
			this.OriginalSwitchStatement = switchStatement;
			this.Condition = switchStatement.Condition;
			this.codeByCondition = new Dictionary<int, Executable[]>();
			foreach (SwitchStatement.Chunk chunk in switchStatement.Chunks)
			{
				this.codeByCondition.Add(((IntegerConstant)chunk.Cases[0]).Value, chunk.Code);
			}
		}
		protected override void TranslateSwitchStatement(List<string> output, SwitchStatement switchStatement)
		{
			output.Add(this.CurrentTabIndention);
			output.Add(this.Shorten("switch ("));
			this.TranslateExpression(output, switchStatement.Condition);
			output.Add(this.Shorten(") {") + this.NL);
			this.CurrentIndention++;

			foreach (SwitchStatement.Chunk chunk in switchStatement.Chunks)
			{
				foreach (Expression caseExpr in chunk.Cases)
				{
					output.Add(this.CurrentTabIndention);
					if (caseExpr == null)
					{
						output.Add("default:" + this.NL);
					}
					else
					{
						output.Add("case ");
						TranslateExpression(output, caseExpr);
						output.Add(":" + this.NL);
					}

					this.CurrentIndention++;

					Translate(output, chunk.Code);

					this.CurrentIndention--;
				}
			}

			this.CurrentIndention--;
			output.Add(this.CurrentTabIndention);
			output.Add("}" + this.NL);
		}
Beispiel #4
0
		private void TranslateSwitchStatementAsElifChain(List<string> output, SwitchStatement switchStatement, int switchId)
		{
			output.Add(this.CurrentTabIndention);
			output.Add("switch_loopy_" + switchId + " = 1\r\n");
			output.Add(this.CurrentTabIndention);
			output.Add("while switch_loopy_" + switchId + " == 1:\r\n");
			this.CurrentIndention++;
			output.Add(this.CurrentTabIndention);
			output.Add("switch_loopy_" + switchId + " = 0\r\n");

			Expression firstCase = switchStatement.Chunks[0].Cases[0];
			if (firstCase == null)
			{
				// WAT
				throw new Exception("This should have been optimized out.");
			}
			else if (firstCase is IntegerConstant)
			{
				// TODO: do this for real
				// There are several optimziations that can be done.
				// if it's a small switch, just use if/elif/else
				// if it's all positive and condensed and ordered, use a binary search with if/else
				// if they're sparse, are they super sparse?
				// if they're chunked not in order, normalize them with a static int-to-int array
				// if there are any weird breaks that aren't at the end, you need to put the whole thing in a one-time loop. e.g. "for ignored in (1,):"
				// now I feel sad. Here's a big-ass if/elif/else chain.
				string varName = "switch_expr_" + switchId;

				output.Add(this.CurrentTabIndention);
				output.Add(varName);
				output.Add(" = ");
				TranslateExpression(output, switchStatement.Condition);
				output.Add("\r\n");

				/*
				 * This is probably best
				 * _switch_statement_lookup_27 = {
				 *   case_expr1: 1,
				 *   case_expr2a: 2,
				 *   case_expr2b: 2,
				 *   case_expr3: 3
				 * }
				 * ...
				 * _ignored_switch_loopy_thing_27 = 1
				 * while _ignored_switch_loopy_thing_27 == =1:
				 *   _ignored_switch_loopy_thing = 0
				 *   _switch_expr_27 = _switch_statement_lookup_27.get(arbitrary_expression, 4) # 4 is the default case
				 *   if _switch_expr_27 < 3:
				 *     if _switch_expr_27 < 2:
				 *       code for case 1
				 *     else:
				 *       code for case 2
				 *   else:
				 *     if _switch_expr_27 < 4:
				 *       code for case 3
				 *     else:
				 *       code for case 4 (default)
				 * 
				 * This way you just leave the breaks as they are. 
				 * Don't try to use an array instead of a dictionary, though. Because that will cause the switch to crash if a crazy value is passed in.
				 */


				// This isn't even right. If a default is first, this will blow up.
				for (int i = 0; i < switchStatement.Chunks.Length; ++i)
				{
					SwitchStatement.Chunk chunk = switchStatement.Chunks[i];
					bool conditionRequired = true;
					output.Add(this.CurrentTabIndention);
					if (i == 0)
					{
						output.Add("if ");
					}
					else if (chunk.Cases[chunk.Cases.Length - 1] == null)
					{
						output.Add("else:\r\n");
						conditionRequired = false;
					}
					else
					{
						output.Add("elif ");
					}

					if (conditionRequired)
					{
						bool parens = chunk.Cases.Length > 1;

						if (parens)
						{
							output.Add("(");
						}

						for (int j = 0; j < chunk.Cases.Length; ++j)
						{
							if (j > 0)
							{
								output.Add(") or (");
							}

							output.Add(varName);
							output.Add(" == ");
							TranslateExpression(output, chunk.Cases[j]);
						}

						if (parens)
						{
							output.Add(")");
						}

						output.Add(":\r\n");
						this.CurrentIndention++;

						Translate(output, chunk.Code);

						if (chunk.Code.Length == 0)
						{
							output.Add(this.CurrentTabIndention);
							output.Add("pass\r\n");
						}

						this.CurrentIndention--;
					}
					else
					{
						this.CurrentIndention++;

						Translate(output, chunk.Code);

						if (chunk.Code.Length == 0)
						{
							output.Add(this.CurrentTabIndention);
							output.Add("pass\r\n");
						}

						this.CurrentIndention--;
					}
				}


			}
			else if (firstCase is StringConstant)
			{
				throw new NotImplementedException("switch on string not implemented yet.");
			}
			else
			{
				throw new ParserException(firstCase.FirstToken, "Invalid value for a switch statement case.");
			}

			this.CurrentIndention--;
		}
Beispiel #5
0
		private void TranslateSwitchStatementAsBinaryDecisions(List<string> output, SwitchStatement switchStatement, int switchId, bool doSafeMapping)
		{

		}
Beispiel #6
0
		protected override void TranslateSwitchStatement(List<string> output, SwitchStatement switchStatement)
		{
			int switchId = this.GetNextInt();

			if (switchStatement.UsesStrings)
			{
				throw new NotImplementedException("Create a string dictionary lookup");
			}
			else if (switchStatement.IsSafe && switchStatement.IsContinuous)
			{
				this.TranslateSwitchStatementAsBinaryDecisions(output, switchStatement, switchId, false);
			}
			else
			{
				this.TranslateSwitchStatementAsElifChain(output, switchStatement, switchId);
			}
		}
Beispiel #7
0
        public SwitchStatementUnsafeBlotchy(SwitchStatement switchStatement, bool useExplicitMax, int explicitMax, Executable owner)
            : base(switchStatement.FirstToken, owner)
        {
            this.OriginalSwitchStatement = switchStatement;
            this.Condition = switchStatement.Condition;

            this.UsesStrings    = switchStatement.UsesStrings;
            this.UseExplicitMax = useExplicitMax;
            this.ExplicitMax    = explicitMax;
            if (this.UsesStrings)
            {
                this.StringUnsafeToSafeMapping = new Dictionary <string, int>();
            }
            else
            {
                this.IntegerUnsafeToSafeMapping = new Dictionary <int, int>();
            }
            this.codeMapping  = new Dictionary <int, Executable[]>();
            this.tokenMapping = new Dictionary <int, Token>();

            this.max = switchStatement.Chunks.Length - 1;

            for (int i = 0; i < switchStatement.Chunks.Length; ++i)
            {
                SwitchStatement.Chunk chunk = switchStatement.Chunks[i];
                this.codeMapping[i]  = chunk.Code;
                this.tokenMapping[i] = chunk.CaseOrDefaultToken;

                foreach (Expression expression in chunk.Cases)
                {
                    if (expression == null)
                    {
                        this.DefaultCaseId = i;
                    }
                    else
                    {
                        IntegerConstant ic = expression as IntegerConstant;
                        StringConstant  sc = expression as StringConstant;
                        if (ic == null && sc == null)
                        {
                            throw new Exception("This shouldn't happen.");
                        }
                        if (ic != null)
                        {
                            int c = ic.Value;
                            this.IntegerUnsafeToSafeMapping[c] = i;
                        }
                        else
                        {
                            string s = sc.Value;
                            this.StringUnsafeToSafeMapping[s] = i;
                        }
                    }
                }
            }

            if (useExplicitMax)
            {
                if (this.UsesStrings)
                {
                    throw new Exception("Cannot use explicit max on string switch statements.");
                }
            }
        }
Beispiel #8
0
		private void CompileSwitchStatement(Parser parser, ByteBuffer buffer, SwitchStatement switchStatement)
		{
			this.CompileExpression(parser, buffer, switchStatement.Condition, true);

			ByteBuffer chunkBuffer = new ByteBuffer();

			Dictionary<int, int> chunkIdsToOffsets = new Dictionary<int, int>();
			Dictionary<int, int> integersToChunkIds = new Dictionary<int,int>();
			Dictionary<string, int> stringsToChunkIds = new Dictionary<string,int>();

			int defaultChunkId = -1;
			foreach (SwitchStatement.Chunk chunk in switchStatement.Chunks)
			{
				int chunkId = chunk.ID;

				if (chunk.Cases.Length == 1 && chunk.Cases[0] == null)
				{
					defaultChunkId = chunkId;
				}
				else
				{
					foreach (Expression expression in chunk.Cases)
					{
						if (switchStatement.UsesIntegers)
						{
							integersToChunkIds[((IntegerConstant)expression).Value] = chunkId;
						}
						else
						{
							stringsToChunkIds[((StringConstant)expression).Value] = chunkId;
						}
					}
				}

				chunkIdsToOffsets[chunkId] = chunkBuffer.Size;

				this.Compile(parser, chunkBuffer, chunk.Code);
			}

			chunkBuffer.ResolveBreaks();

			int switchId = parser.RegisterByteCodeSwitch(switchStatement.FirstToken, chunkIdsToOffsets, integersToChunkIds, stringsToChunkIds, switchStatement.UsesIntegers);

			int defaultOffsetLength = defaultChunkId == -1
				? chunkBuffer.Size
				: chunkIdsToOffsets[defaultChunkId];

			buffer.Add(switchStatement.FirstToken, switchStatement.UsesIntegers ? OpCode.SWITCH_INT : OpCode.SWITCH_STRING, switchId, defaultOffsetLength);
			buffer.Concat(chunkBuffer);
		}
Beispiel #9
0
		protected abstract void TranslateSwitchStatement(List<string> output, SwitchStatement switchStatement);