public CodeExpression GetLoadExpression(InstructionForm frm, int argIdx)
		{
			int reqFldsPrev = 0;
			foreach (var val in Parent.Parameters.Values)
			{
				if (val == this)
					break;
				if (val.ArgType == this.ArgType)
				{
					reqFldsPrev++;
				}
			}
			return new CodeFieldReferenceExpression(
				new CodeThisReferenceExpression(),
				frm.GetArgName(ArgType, reqFldsPrev + 1, argIdx)
			);
		}
		public InstructionForm DeepCopy()
		{
			// Because of the way this is designed (awesomely in my opinion),
			// the only thing that has to be deep copied in the WriteOperation list.
			InstructionForm i = new InstructionForm(ParentInstruction);
			i.Arg1 = Arg1;
			i.Arg2 = Arg2;
			i.Arg3 = Arg3;
			i.Mnemonic = Mnemonic;
			i.DefaultSegment = DefaultSegment;
			i.ExcludeCondition = ExcludeCondition != null ? ExcludeCondition.DeepCopy() : null;
			foreach (WriteOperationArgument arg in WriteOperationArgs)
			{
				i.WriteOperationArgs.Add(arg.DeepCopy());
			}
			i.WriteOperations.AddRange(WriteOperations);
			return i;
		}
		public CodeExpression GetLoadExpression(InstructionForm frm)
		{
			if (Type == OperationSourceType.Constant)
			{
				return new CodePrimitiveExpression(Constant);
			}
			else
			{
				switch(frm[ParentArgIdx].ArgType.ID)
				{
					case InstructionArgType.Imm32_ID:
						return new CodeFieldReferenceExpression(
							new CodeThisReferenceExpression(),
							frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, ParentArgIdx)
						);
					case InstructionArgType.Imm16_ID:
						return new CodeCastExpression(
							StaticTypeReferences.UShort,
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, ParentArgIdx)
							)
						);
					case InstructionArgType.Imm8_ID:
						return new CodeCastExpression(
							StaticTypeReferences.Byte,
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, ParentArgIdx)
							)
						);

					default:
						if (frm[ParentArgIdx].ArgType.AsArgOperation == null)
							throw new Exception("The specified arg isn't valid as an argument to a write operation!");
						return frm[ParentArgIdx].ArgType.AsArgOperation.GetExpression(frm, ParentArgIdx, null);
				}
			}
		}
		public CodeExpression GetConditionExpression(InstructionForm parent)
		{
			CodeBinaryOperatorType cond;
			switch (Condition)
			{
				case ConditionType.Less:
					cond = CodeBinaryOperatorType.LessThan;
					break;
				case ConditionType.LessOrEqual:
					cond = CodeBinaryOperatorType.LessThanOrEqual;
					break;
				case ConditionType.Greater:
					cond = CodeBinaryOperatorType.GreaterThan;
					break;
				case ConditionType.GreaterOrEqual:
					cond = CodeBinaryOperatorType.GreaterThanOrEqual;
					break;
				case ConditionType.Equal:
					cond = CodeBinaryOperatorType.ValueEquality;
					break;
				case ConditionType.NotEqual:
					cond = CodeBinaryOperatorType.IdentityInequality;
					break;
				default:
					throw new Exception("Unknown condition!");
			}
			return new CodeBinaryOperatorExpression(
				new CodeFieldReferenceExpression(
					new CodeThisReferenceExpression(),
					parent.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgToExclude)
				),
				cond,
				new CodePrimitiveExpression(ConditionArg)
			);
		}
		public WriteOperation(Token[] toks, InstructionForm ParentForm)
		{
			// As a note, all operations should be 4 characters,
			// if they are unable to be 4 characters, then they
			// should be sets of 4 characters seperated in
			// some way. (this allows for the write operations to
			// be aligned in the cpud file)
			Token tok = toks[0];
			switch (toks.Length)
			{
				case 1:
					if (tok.Type == TokenType.Number)
					{
						this.Type = WriteOperationType.Byte;
						this.ByteValue = (byte)tok.NumberValue.Value;
					}
					else if (tok.Value.StartsWith("arg"))
					{
						this.ArgIdx = (byte)(Utils.SingleDigitParse(tok.Value[3]) - 1);
						if (!ParentForm[ArgIdx].ArgType.HasSize)
						{
							this.Type = WriteOperationType.Arg;
						}
						else
						{
							switch(ParentForm[ArgIdx].ArgType.Size)
							{
								case 1:
									this.Type = WriteOperationType.Imm8;
									break;
								case 2:
									this.Type = WriteOperationType.Imm16;
									break;
								case 4:
									this.Type = WriteOperationType.Imm32;
									break;
								default:
									throw new Exception("Unknown arg type!");
							}
						}
					}
					else // Prefix
					{
						this.Type = WriteOperationType.Prefix;
						this.SelectedPrefix = PrefixRegistry.GetPrefixName(tok.Value);
						if (this.SelectedPrefix == null)
							throw new Exception("Unknown write operation '" + tok.Value + "'!");
					}
					break;
				case 3:
					this.Type = WriteOperationType.BytePlusArg;
					this.ArgIdx = (byte)(Utils.SingleDigitParse(toks[2].Value[3]) - 1);
					this.ByteValue = (byte)tok.NumberValue.Value;
					break;
				case 4:
					if (tok.Value == "evil")
					{
						if (toks[1].Type != TokenType.LSqBracket)
							throw new Exception("Expected an opening square bracket before the exception's message!");
						if (toks[3].Type != TokenType.RSqBracket)
							throw new Exception("Expected the closing square bracket after the exception's message!");
						this.Type = WriteOperationType.Throw;
						this.MessageThrown = toks[2].Value;
					}
					else if (tok.Value.StartsWith("arg"))
					{
						if (toks[1].Type != TokenType.LSqBracket)
							throw new Exception("Expected an opening square bracket before the argument write operation!");
						if (toks[3].Type != TokenType.RSqBracket)
							throw new Exception("Expected the closing square bracket after the argument write operation!");
						this.ArgIdx = (byte)(Utils.SingleDigitParse(tok.Value[3]) - 1);
						this.Type = WriteOperationType.Arg;
						this.WriteArguments.Add(new WriteOperationArgument(toks[2]));
					}
					else
					{
						throw new Exception("Unknown write operation type!");
					}
					break;
				default:
					if (tok.Value.StartsWith("arg"))
					{
						if (toks[1].Type != TokenType.LSqBracket)
							throw new Exception("Expected an opening square bracket before the argument write operation!");
						this.Type = WriteOperationType.Arg;
						this.ArgIdx = (byte)(Utils.SingleDigitParse(tok.Value[3]) - 1);
						for (int i = 2; i < toks.Length - 1; i += 2)
						{
							this.WriteArguments.Add(new WriteOperationArgument(toks[i]));
							if (i + 1 < toks.Length - 1 && toks[i + 1].Type != TokenType.Comma)
								throw new Exception("Expected a comma!");
						}
						if (toks[toks.Length - 1].Type != TokenType.RSqBracket)
							throw new Exception("Expected the closing square bracket after the argument write operation!");
					}
					else
					{
						throw new Exception("Unknown number of tokens passed in!");
					}
					break;
			}
		}
		public void Write(CodeScopeStatement con, InstructionForm ParentForm)
		{
			switch (Type)
			{
				case WriteOperationType.Arg:
					con.Statements.Add(
						ParentForm[ArgIdx].ArgType.WriteOperation.GetExpression(ParentForm, ArgIdx, this)
					);
					break;
				case WriteOperationType.Prefix:
					con.Statements.Add(
						new CodeMethodInvokeExpression(
							StaticTypeReferences.Emit_Stream_WritePrefix,
							new CodeFieldReferenceExpression(StaticTypeReferences.PrefixExpression, SelectedPrefix)
						)
					);
					break;
				case WriteOperationType.Byte:
					con.Statements.Add(
						new CodeMethodInvokeExpression(
							StaticTypeReferences.Emit_Stream_WriteByte,
							new CodePrimitiveExpression(ByteValue)
						)
					);
					break;
				case WriteOperationType.BytePlusArg:
					con.Statements.Add(
						new CodeMethodInvokeExpression(
							StaticTypeReferences.Emit_Stream_WriteByte,
							new CodeCastExpression(
								StaticTypeReferences.Byte,
								new CodeBinaryOperatorExpression(
									new CodePrimitiveExpression(ByteValue),
									CodeBinaryOperatorType.Add,
									ParentForm[ArgIdx].ArgType.AsArgOperation.GetExpression(ParentForm, ArgIdx, this)
								)
							)
						)
					);
					break;
				case WriteOperationType.Imm8:
					con.Statements.Add(
						new CodeMethodInvokeExpression(
							StaticTypeReferences.Emit_Stream_WriteImm8,
							new CodeCastExpression(
								StaticTypeReferences.Byte,
								new CodeFieldReferenceExpression(
									new CodeThisReferenceExpression(),
									ParentForm.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgIdx)
								)
							)
						)
					);
					break;
				case WriteOperationType.Imm16:
					con.Statements.Add(
						new CodeMethodInvokeExpression(
							StaticTypeReferences.Emit_Stream_WriteImm16,
							new CodeCastExpression(
								StaticTypeReferences.UShort,
								new CodeFieldReferenceExpression(
									new CodeThisReferenceExpression(),
									ParentForm.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgIdx)
								)
							)
						)
					);
					break;
				case WriteOperationType.Imm32:
					con.Statements.Add(
						new CodeMethodInvokeExpression(
							StaticTypeReferences.Emit_Stream_WriteImm32,
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								ParentForm.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgIdx)
							)
						)
					);
					break;
				case WriteOperationType.Throw:
					con.Statements.Add(
						new CodeThrowExceptionStatement(
							new CodeObjectCreateExpression(
								StaticTypeReferences.Exception,
								new CodePrimitiveExpression(MessageThrown)
							)
						)
					);
					break;
				default:
					throw new Exception("Unsupported write operation type!");
			}
		}
			public CodeExpression GetConditionExpression(InExactInstructionOverrideDescription ParentDesc, InstructionForm formOverriding)
			{
				switch (Condition)
				{
					case ConditionType.Fits:
						switch(ParentDesc.NewForm[ArgIndexToCheck].ArgType.ID)
						{
							case InstructionArgType.Dis8_ID:
							case InstructionArgType.Imm8_ID:
								return new CodeMethodInvokeExpression(
									StaticTypeReferences.Stream_InSByteRange,
									new CodeCastExpression(
										StaticTypeReferences.Int,
										new CodeFieldReferenceExpression(
											new CodeThisReferenceExpression(),
											formOverriding.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgIndexToCheck)
										)
									)
								);
							case InstructionArgType.Dis16_ID:
							case InstructionArgType.Imm16_ID:
								return new CodeMethodInvokeExpression(
									StaticTypeReferences.Stream_InShortRange,
									new CodeCastExpression(
										StaticTypeReferences.Int,
										new CodeFieldReferenceExpression(
											new CodeThisReferenceExpression(),
											formOverriding.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgIndexToCheck)
										)
									)
								);

							default:
								throw new Exception("Unknown arg type!");
						}
					case ConditionType.Compare_Imm:
						if (ParentDesc.NewForm[ArgIndexToCheck].ArgType == InstructionArgType.Imm8)
						{
							return new CodeBinaryOperatorExpression(
								new CodeFieldReferenceExpression(
									new CodeThisReferenceExpression(),
									formOverriding.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgIndexToCheck)
								),
								CodeBinaryOperatorType.ValueEquality,
								new CodePrimitiveExpression(ImmValueToCompareTo)
							);
						}
						else
						{
							return new CodeBinaryOperatorExpression(
								ParentDesc.NewForm[ArgIndexToCheck].ArgType.AsArgOperation.GetExpression(ParentDesc.NewForm, ArgIndexToCheck, null),
								CodeBinaryOperatorType.ValueEquality,
								new CodePrimitiveExpression(ImmValueToCompareTo)
							);
						}
					case ConditionType.Compare_Reg:
						// Yikes....
						var enu = formOverriding[ArgIndexToCheck].ArgType.Parameters.Values.GetEnumerator();
						enu.MoveNext();
						int argType = enu.Current.ArgType;
						return new CodeBinaryOperatorExpression(
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								formOverriding.GetArgName(argType, 1, ArgIndexToCheck)
							),
							CodeBinaryOperatorType.ValueEquality,
							new CodeFieldReferenceExpression(
								new CodeTypeReferenceExpression(FieldTypeRegistry.Fields[argType].Name),
								RegisterToCompareTo
							)
						);
					case ConditionType.Compare_Segment:
						return new CodeBinaryOperatorExpression(
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								formOverriding.GetArgName(FieldTypeRegistry.Segment.ID, 1, ArgIndexToCheck)
							),
							CodeBinaryOperatorType.ValueEquality,
							new CodeFieldReferenceExpression(StaticTypeReferences.SegmentExpression, RegisterToCompareTo)
						);
					default:
						throw new Exception("Unknown Condition!");
				}
			}
		public void WriteConditionalEmit(CodeScopeStatement con, InstructionForm overridenForm, bool ignoreOtherOverrides = false)
		{
			if (Conditions.Count == 0)
				throw new Exception("There are no conditions to the override!");
			if (!ignoreOtherOverrides && CanGenSegmentSwitch(overridenForm))
			{
				CodeSwitchStatement sw = new CodeSwitchStatement(
					new CodeFieldReferenceExpression(
						new CodeThisReferenceExpression(),
						overridenForm.GetArgName(FieldTypeRegistry.Segment.ID, 1, Conditions[0].ArgIndexToCheck)
					)
				);
				for (int i = 0; i < overridenForm.Overrides.Count; i++)
				{
					CodeCaseStatement cs = new CodeCaseStatement(
						new CodeFieldReferenceExpression(
							StaticTypeReferences.SegmentExpression,
							overridenForm.Overrides[i].Conditions[0].RegisterToCompareTo
						)
					);
					CodeScopeStatement cst = new CodeScopeStatement();
					overridenForm.Overrides[i].NewForm.WriteEmit(cst, true);
					cst.Statements.Add(new CodeBreakStatement());
					cs.Statements.Add(cst);
					sw.Cases.Add(cs);
				}
				CodeDefaultCaseStatement defStat = new CodeDefaultCaseStatement();
				CodeScopeStatement defCont = new CodeScopeStatement();
				overridenForm.WriteEmit(defCont, true);
				defStat.Statements.Add(defCont);
				if (overridenForm.WriteOperations[0].Type != WriteOperationType.Throw)
				{
					defStat.Statements.Add(new CodeBreakStatement());
				}
				sw.Cases.Add(defStat);
				con.Statements.Add(sw);
			}
			else
			{
				CodeScopeStatement tCont = new CodeScopeStatement();
				CodeScopeStatement fCont = new CodeScopeStatement();
				CodeExpression condition = Conditions[0].GetConditionExpression(this, overridenForm);
				for (int i = 1; i < Conditions.Count; i++)
				{
					condition = new CodeBinaryOperatorExpression(
						condition, 
						CodeBinaryOperatorType.BooleanAnd, 
						Conditions[i].GetConditionExpression(this, overridenForm)
					);
				}
				CodeConditionStatement condStat = new CodeConditionStatement(condition, new CodeStatement[] { tCont });
				NewForm.WriteEmit(tCont, true);
				if (!ignoreOtherOverrides)
				{
					condStat.FalseStatements.Add(fCont);
					if (overridenForm.Overrides.Count > 1)
					{
						// If we've gotten here, we know that we are the override at index 0.
						for (int i = 1; i < overridenForm.Overrides.Count; i++)
						{
							CodeScopeStatement eICont = new CodeScopeStatement();
							overridenForm.Overrides[i].WriteConditionalEmit(eICont, overridenForm, true);
							fCont.Statements.Add(eICont);
							fCont = new CodeScopeStatement();
							((CodeConditionStatement)eICont.Statements[0]).FalseStatements.Add(fCont);
						}
					}
					overridenForm.WriteEmit(fCont, true);
				}
				con.Statements.Add(condStat);
			}
		}
		private bool CanGenSegmentSwitch(InstructionForm overridenForm)
		{
			if (overridenForm.Overrides.Count < 2)
				return false;
			for (int i = 0; i < overridenForm.Overrides.Count; i++)
			{
				var l = overridenForm.Overrides[i].Conditions;
				for (int i2 = 0; i2 < l.Count; i2++)
				{
					if (l[i2].Condition != OverrideCondition.ConditionType.Compare_Segment)
						return false;
				}
			}
			return true;
		}
Exemple #10
0
		public bool NeedsEmission(InstructionForm frm)
		{
			InstructionArgSet key = new InstructionArgSet()
			{
				Arg1 = InstructionArgTypeRegistry.GetType(frm.Arg1.ArgType.TrueName),
				Arg2 = InstructionArgTypeRegistry.GetType(frm.Arg2.ArgType.TrueName),
				Arg3 = InstructionArgTypeRegistry.GetType(frm.Arg3.ArgType.TrueName)
			};
			if (!FormsEmitted.ContainsKey(key))
			{
				FormsEmitted[key] = true;
				return true;
			}
			return false;
		}
Exemple #11
0
		private void ExpandSingleForm(InstructionForm f, int argIdx)
		{
			foreach (InstructionArgType tp in f[argIdx].ArgType.ExpandsTo)
			{
				InstructionForm f2 = f.DeepCopy();
				InstructionArg a = f2[argIdx];
				a.ArgType = tp;
				f2[argIdx] = a;
				FinalForms.Add(f2);
			}
		}
		public CodeExpression GetToStringForArg(InstructionForm frm, int argIdx)
		{
			InstructionArg arg = frm[argIdx];
			int padSize = 0;
			switch (arg.ArgType.ID)
			{
				case InstructionArgType.Dis8_ID:
				case InstructionArgType.Dis16_ID:
				case InstructionArgType.Dis32_ID:
					return new CodeMethodInvokeExpression(
						StaticTypeReferences.NamingHelper_NameDisplacement,
						StaticTypeReferences.ParentAssemblerExpression,
						new CodeThisReferenceExpression(),
						new CodeCastExpression(
							StaticTypeReferences.Int,
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, argIdx)
							)
						)
					);

				case InstructionArgType.Imm8_ID:
					padSize = 2;
					goto ImmCommon;
				case InstructionArgType.Imm16_ID:
					padSize = 4;
					goto ImmCommon;
				case InstructionArgType.Imm32_ID:
					padSize = 8;
					goto ImmCommon;
				default:
					return arg.ArgType.ReadOperation.GetExpression(frm, argIdx, null);
			}
		ImmCommon:
			if (arg.NumberFormat == ImmNumberFormat.Decimal)
			{
				return new CodeMethodInvokeExpression(
					new CodeFieldReferenceExpression(
						new CodeThisReferenceExpression(),
						frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, argIdx)
					),
					"ToString"
				);
			}
			else
			{
				return Generator.LanguageProvider.GetPaddedHexToString(
					new CodeFieldReferenceExpression(
						new CodeThisReferenceExpression(),
						frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, argIdx)
					),
					padSize
				);
			}
		}
		public void WriteConstructorBodyArgProcessing(InstructionForm frm, CodeConstructor c, int argIdx)
		{
			InstructionArg arg = frm[argIdx];
			switch (ID)
			{
				case None_ID:
					break;
				// Dis8 & Dis16 have to be sign-extended before being stored.
				// (this way they can be compared using the exact same code as
				// dis32 can)
				case Dis8_ID:
				case Dis16_ID:
					c.Statements.Add(
						new CodeAssignStatement(
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, argIdx)
							),
							new CodeCastExpression(
								StaticTypeReferences.UInt,
								new CodeCastExpression(
									StaticTypeReferences.Int,
									new CodeArgumentReferenceExpression(arg.Name + DisArgSuffix)
								)
							)
						)
					);
					break;
				// No sign extension needed.
				case Dis32_ID:
					c.Statements.Add(
						new CodeAssignStatement(
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, argIdx)
							),
							new CodeCastExpression(
								StaticTypeReferences.UInt,
								new CodeArgumentReferenceExpression(arg.Name + DisArgSuffix)
							)
						)
					);
					break;
				case Imm8_ID:
				case Imm16_ID:
				case Imm32_ID:
					c.Statements.Add(
						new CodeAssignStatement(
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, argIdx)
							),
							new CodeCastExpression(
								StaticTypeReferences.UInt,
								new CodeArgumentReferenceExpression(arg.Name + ImmArgSuffix)
							)
						)
					);
					break;

				default:
					int[] reqs = new int[FieldTypeRegistry.MaxFieldID + 1];
					foreach(CustomInstructionArgParameter p in mParameters.Values)
					{
						c.Statements.Add(
							new CodeAssignStatement(
								new CodeFieldReferenceExpression(
									new CodeThisReferenceExpression(),
									frm.GetArgName(p.ArgType, reqs[p.ArgType] + 1, argIdx)
								),
								new CodeArgumentReferenceExpression(arg.Name + p.ArgNameSuffix)
							)
						);
						reqs[p.ArgType]++;
					}
					break;
			}
		}
		public CodeExpression GetExpression(InstructionForm frm, int argIdx, WriteOperation wrOp)
		{
			int curIdx = 0;
			Token tok = toks[curIdx];
			if (tok.Type != TokenType.Identifier)
				throw new Exception("Expected an identifier!");

			if (tok.Value == "ToString")
			{
				curIdx++;

				tok = toks[curIdx];
				if (tok.Type != TokenType.LParen)
					throw new Exception("Expected an opening parenthesis!");
				curIdx++;

				tok = toks[curIdx];
				if (tok.Type != TokenType.Identifier)
					throw new Exception("Expected an identifier for the expression to convert to a string!");
				CodeExpression ldExpr = GetExpressionFromIdentifier(tok.Value, frm, argIdx, wrOp);
				curIdx++;

				tok = toks[curIdx];
				if (tok.Type != TokenType.RParen)
					throw new Exception("Expected the closing parenthesis!");
				curIdx++;

				return new CodeMethodInvokeExpression(
					ldExpr,
					"ToString"
				);
			}
			else if (tok.Value == "DirectCast")
			{
				curIdx++;

				tok = toks[curIdx];
				if (tok.Type != TokenType.LParen)
					throw new Exception("Expected an opening parenthesis!");
				curIdx++;

				tok = toks[curIdx];
				if (tok.Type != TokenType.Identifier)
					throw new Exception("Expected an identifier representing the argument to cast!");
				CustomInstructionArgParameter param;
				if (!ParentArg.Parameters.TryGetValue(tok.Value, out param))
					throw new Exception("Unknown parameter '" + tok.Value + "'!");
				CodeExpression argLoadExpression = param.GetLoadExpression(frm, argIdx);
				curIdx++;

				tok = toks[curIdx];
				if (tok.Type != TokenType.Comma)
					throw new Exception("Expected a comma before the destination type!");
				curIdx++;

				tok = toks[curIdx];
				if (tok.Type != TokenType.Identifier)
					throw new Exception("Expected an identifier representing the type to cast to!");
				CodeTypeReference destType;
				switch(tok.Value.ToLower())
				{
					case "byte":
						destType = StaticTypeReferences.Byte;
						break;
					case "sbyte":
						destType = StaticTypeReferences.SByte;
						break;
					case "ushort":
						destType = StaticTypeReferences.UShort;
						break;
					case "short":
						destType = StaticTypeReferences.Short;
						break;
					case "uint":
						destType = StaticTypeReferences.UInt;
						break;
					case "int":
						destType = StaticTypeReferences.Int;
						break;
					case "ulong":
						destType = StaticTypeReferences.ULong;
						break;
					case "long":
						destType = StaticTypeReferences.Long;
						break;
					default:
						destType = new CodeTypeReference(tok.Value);
						break;
				}
				curIdx++;

				tok = toks[curIdx];
				if (tok.Type != TokenType.RParen)
					throw new Exception("Expected closing parenthesis!");
				curIdx++;

				return new CodeCastExpression(
					destType,
					argLoadExpression
				);
			}
			else
			{
				CodeExpression sourceExpression;
				bool NamedArgNeedsCast = false;
				if (tok.Value == "Stream")
				{
					sourceExpression = StaticTypeReferences.Emit_StreamArg;
				}
				else
				{
					if (tok.Value == "BitPatterns")
						NamedArgNeedsCast = true;
					sourceExpression = new CodeTypeReferenceExpression(tok.Value);
				}
				curIdx++;
			
				tok = toks[curIdx];
				if (tok.Type != TokenType.Dot)
					throw new Exception("Expected a dot!");
				curIdx++;
			
				tok = toks[curIdx];
				if (tok.Type != TokenType.Identifier)
					throw new Exception("Expected an identifier!");
				CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression(
					sourceExpression,
					NamedArgNeedsCast ? BitPatternRegistry.GetPattern(tok.Value).Name : tok.Value
				);
				curIdx++;

				tok = toks[curIdx];
				if (tok.Type != TokenType.LParen)
					throw new Exception("Expected an opening parenthesis!");
				curIdx++;

				List<CodeExpression> parms = new List<CodeExpression>(8);
				tok = toks[curIdx];
				bool expectsAnotherArg = true;
				while (tok.Type != TokenType.RParen)
				{
					if (!expectsAnotherArg)
						throw new Exception("Didn't expect another arg!");
					switch (tok.Type)
					{
						case TokenType.Identifier:
							parms.Add(GetExpressionFromIdentifier(tok.Value, frm, argIdx, wrOp, NamedArgNeedsCast));
							break;
						case TokenType.Number:
							if (tok.NumberValue.Format == NumberFormat.Decimal)
							{
								parms.Add(new CodePrimitiveExpression((int)tok.NumberValue.Value));
							}
							else
							{
								parms.Add(new CodePrimitiveExpression(tok.NumberValue.Value));
							}
							break;
						default:
							throw new Exception("Unknown token type!");
					}
					curIdx++;

					tok = toks[curIdx];
					if (tok.Type != TokenType.Comma)
					{
						expectsAnotherArg = false;
					}
					else
					{
						curIdx++;
						tok = toks[curIdx];
					}
				}
				if (expectsAnotherArg)
					throw new Exception("Expected another arg!");

				return new CodeMethodInvokeExpression(
					methodRef,
					parms.ToArray()
				);
			}
		}
		private CodeExpression GetExpressionFromIdentifier(string val, InstructionForm frm, int argIdx, WriteOperation wrOp, bool namedParamNeedsCast = false)
		{
			CustomInstructionArgParameter param;
			if (ParentArg.Parameters.TryGetValue(val, out param))
			{
				if (namedParamNeedsCast)
				{
					return frm[argIdx].ArgType.AsArgOperation.GetExpression(frm, argIdx, wrOp);
				}
				else
				{
					return param.GetLoadExpression(frm, argIdx);
				}
			}
			else if (val == "Segment")
			{
				return new CodeFieldReferenceExpression(
					new CodeThisReferenceExpression(),
					frm.GetArgName(FieldTypeRegistry.Segment.ID, 1, InstructionArgSet.TotalArgs_Max)
				);
			}
			else if (val == "ParentAssembler")
			{
				return StaticTypeReferences.ParentAssemblerExpression;
			}
			else if (val == "Stream")
			{
				return StaticTypeReferences.Emit_StreamArg;
			}
			else if (val.StartsWith("arg"))
			{
				int fArg = Utils.SingleDigitParse(val[3]) - 1;
				return wrOp.WriteArguments[fArg].GetLoadExpression(frm);
			}
			else
			{
				return new CodeTypeReferenceExpression(val);
			}
		}