Esempio n. 1
0
		/// <summary>Generate IR for a for..in loop.</summary>
		/// <remarks>Generate IR for a for..in loop.</remarks>
		private Node CreateForIn(int declType, Node loop, Node lhs, Node obj, Node body, bool isForEach)
		{
			int destructuring = -1;
			int destructuringLen = 0;
			Node lvalue;
			int type = lhs.GetType();
			if (type == Token.VAR || type == Token.LET)
			{
				Node kid = lhs.GetLastChild();
				int kidType = kid.GetType();
				if (kidType == Token.ARRAYLIT || kidType == Token.OBJECTLIT)
				{
					type = destructuring = kidType;
					lvalue = kid;
					destructuringLen = 0;
					if (kid is ArrayLiteral)
					{
						destructuringLen = ((ArrayLiteral)kid).GetDestructuringLength();
					}
				}
				else
				{
					if (kidType == Token.NAME)
					{
						lvalue = Node.NewString(Token.NAME, kid.GetString());
					}
					else
					{
						ReportError("msg.bad.for.in.lhs");
						return null;
					}
				}
			}
			else
			{
				if (type == Token.ARRAYLIT || type == Token.OBJECTLIT)
				{
					destructuring = type;
					lvalue = lhs;
					destructuringLen = 0;
					if (lhs is ArrayLiteral)
					{
						destructuringLen = ((ArrayLiteral)lhs).GetDestructuringLength();
					}
				}
				else
				{
					lvalue = MakeReference(lhs);
					if (lvalue == null)
					{
						ReportError("msg.bad.for.in.lhs");
						return null;
					}
				}
			}
			Node localBlock = new Node(Token.LOCAL_BLOCK);
			int initType = isForEach ? Token.ENUM_INIT_VALUES : (destructuring != -1 ? Token.ENUM_INIT_ARRAY : Token.ENUM_INIT_KEYS);
			Node init = new Node(initType, obj);
			init.PutProp(Node.LOCAL_BLOCK_PROP, localBlock);
			Node cond = new Node(Token.ENUM_NEXT);
			cond.PutProp(Node.LOCAL_BLOCK_PROP, localBlock);
			Node id = new Node(Token.ENUM_ID);
			id.PutProp(Node.LOCAL_BLOCK_PROP, localBlock);
			Node newBody = new Node(Token.BLOCK);
			Node assign;
			if (destructuring != -1)
			{
				assign = CreateDestructuringAssignment(declType, lvalue, id);
				if (!isForEach && (destructuring == Token.OBJECTLIT || destructuringLen != 2))
				{
					// destructuring assignment is only allowed in for..each or
					// with an array type of length 2 (to hold key and value)
					ReportError("msg.bad.for.in.destruct");
				}
			}
			else
			{
				assign = SimpleAssignment(lvalue, id);
			}
			newBody.AddChildToBack(new Node(Token.EXPR_VOID, assign));
			newBody.AddChildToBack(body);
			loop = CreateLoop((Jump)loop, LOOP_WHILE, newBody, cond, null, null);
			loop.AddChildToFront(init);
			if (type == Token.VAR || type == Token.LET)
			{
				loop.AddChildToFront(lhs);
			}
			localBlock.AddChildToBack(loop);
			return localBlock;
		}
Esempio n. 2
0
		private int RewriteForNumberVariables(Node n, int desired)
		{
			switch (n.GetType())
			{
				case Token.EXPR_VOID:
				{
					Node child = n.GetFirstChild();
					int type = RewriteForNumberVariables(child, NumberType);
					if (type == NumberType)
					{
						n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
					}
					return NoType;
				}

				case Token.NUMBER:
				{
					n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
					return NumberType;
				}

				case Token.GETVAR:
				{
					int varIndex = theFunction.GetVarIndex(n);
					if (inDirectCallFunction && theFunction.IsParameter(varIndex) && desired == NumberType)
					{
						n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
						return NumberType;
					}
					else
					{
						if (theFunction.IsNumberVar(varIndex))
						{
							n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							return NumberType;
						}
					}
					return NoType;
				}

				case Token.INC:
				case Token.DEC:
				{
					Node child = n.GetFirstChild();
					int type = RewriteForNumberVariables(child, NumberType);
					if (child.GetType() == Token.GETVAR)
					{
						if (type == NumberType && !ConvertParameter(child))
						{
							n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							MarkDCPNumberContext(child);
							return NumberType;
						}
						return NoType;
					}
					else
					{
						if (child.GetType() == Token.GETELEM || child.GetType() == Token.GETPROP)
						{
							return type;
						}
					}
					return NoType;
				}

				case Token.SETVAR:
				{
					Node lChild = n.GetFirstChild();
					Node rChild = lChild.GetNext();
					int rType = RewriteForNumberVariables(rChild, NumberType);
					int varIndex = theFunction.GetVarIndex(n);
					if (inDirectCallFunction && theFunction.IsParameter(varIndex))
					{
						if (rType == NumberType)
						{
							if (!ConvertParameter(rChild))
							{
								n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
								return NumberType;
							}
							MarkDCPNumberContext(rChild);
							return NoType;
						}
						else
						{
							return rType;
						}
					}
					else
					{
						if (theFunction.IsNumberVar(varIndex))
						{
							if (rType != NumberType)
							{
								n.RemoveChild(rChild);
								n.AddChildToBack(new Node(Token.TO_DOUBLE, rChild));
							}
							n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							MarkDCPNumberContext(rChild);
							return NumberType;
						}
						else
						{
							if (rType == NumberType)
							{
								if (!ConvertParameter(rChild))
								{
									n.RemoveChild(rChild);
									n.AddChildToBack(new Node(Token.TO_OBJECT, rChild));
								}
							}
							return NoType;
						}
					}
					goto case Token.LE;
				}

				case Token.LE:
				case Token.LT:
				case Token.GE:
				case Token.GT:
				{
					Node lChild = n.GetFirstChild();
					Node rChild = lChild.GetNext();
					int lType = RewriteForNumberVariables(lChild, NumberType);
					int rType = RewriteForNumberVariables(rChild, NumberType);
					MarkDCPNumberContext(lChild);
					MarkDCPNumberContext(rChild);
					if (ConvertParameter(lChild))
					{
						if (ConvertParameter(rChild))
						{
							return NoType;
						}
						else
						{
							if (rType == NumberType)
							{
								n.PutIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
							}
						}
					}
					else
					{
						if (ConvertParameter(rChild))
						{
							if (lType == NumberType)
							{
								n.PutIntProp(Node.ISNUMBER_PROP, Node.LEFT);
							}
						}
						else
						{
							if (lType == NumberType)
							{
								if (rType == NumberType)
								{
									n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
								}
								else
								{
									n.PutIntProp(Node.ISNUMBER_PROP, Node.LEFT);
								}
							}
							else
							{
								if (rType == NumberType)
								{
									n.PutIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
								}
							}
						}
					}
					// we actually build a boolean value
					return NoType;
				}

				case Token.ADD:
				{
					Node lChild = n.GetFirstChild();
					Node rChild = lChild.GetNext();
					int lType = RewriteForNumberVariables(lChild, NumberType);
					int rType = RewriteForNumberVariables(rChild, NumberType);
					if (ConvertParameter(lChild))
					{
						if (ConvertParameter(rChild))
						{
							return NoType;
						}
						else
						{
							if (rType == NumberType)
							{
								n.PutIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
							}
						}
					}
					else
					{
						if (ConvertParameter(rChild))
						{
							if (lType == NumberType)
							{
								n.PutIntProp(Node.ISNUMBER_PROP, Node.LEFT);
							}
						}
						else
						{
							if (lType == NumberType)
							{
								if (rType == NumberType)
								{
									n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
									return NumberType;
								}
								else
								{
									n.PutIntProp(Node.ISNUMBER_PROP, Node.LEFT);
								}
							}
							else
							{
								if (rType == NumberType)
								{
									n.PutIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
								}
							}
						}
					}
					return NoType;
				}

				case Token.BITXOR:
				case Token.BITOR:
				case Token.BITAND:
				case Token.RSH:
				case Token.LSH:
				case Token.SUB:
				case Token.MUL:
				case Token.DIV:
				case Token.MOD:
				{
					Node lChild = n.GetFirstChild();
					Node rChild = lChild.GetNext();
					int lType = RewriteForNumberVariables(lChild, NumberType);
					int rType = RewriteForNumberVariables(rChild, NumberType);
					MarkDCPNumberContext(lChild);
					MarkDCPNumberContext(rChild);
					if (lType == NumberType)
					{
						if (rType == NumberType)
						{
							n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							return NumberType;
						}
						else
						{
							if (!ConvertParameter(rChild))
							{
								n.RemoveChild(rChild);
								n.AddChildToBack(new Node(Token.TO_DOUBLE, rChild));
								n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							}
							return NumberType;
						}
					}
					else
					{
						if (rType == NumberType)
						{
							if (!ConvertParameter(lChild))
							{
								n.RemoveChild(lChild);
								n.AddChildToFront(new Node(Token.TO_DOUBLE, lChild));
								n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							}
							return NumberType;
						}
						else
						{
							if (!ConvertParameter(lChild))
							{
								n.RemoveChild(lChild);
								n.AddChildToFront(new Node(Token.TO_DOUBLE, lChild));
							}
							if (!ConvertParameter(rChild))
							{
								n.RemoveChild(rChild);
								n.AddChildToBack(new Node(Token.TO_DOUBLE, rChild));
							}
							n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							return NumberType;
						}
					}
					goto case Token.SETELEM;
				}

				case Token.SETELEM:
				case Token.SETELEM_OP:
				{
					Node arrayBase = n.GetFirstChild();
					Node arrayIndex = arrayBase.GetNext();
					Node rValue = arrayIndex.GetNext();
					int baseType = RewriteForNumberVariables(arrayBase, NumberType);
					if (baseType == NumberType)
					{
						if (!ConvertParameter(arrayBase))
						{
							n.RemoveChild(arrayBase);
							n.AddChildToFront(new Node(Token.TO_OBJECT, arrayBase));
						}
					}
					int indexType = RewriteForNumberVariables(arrayIndex, NumberType);
					if (indexType == NumberType)
					{
						if (!ConvertParameter(arrayIndex))
						{
							// setting the ISNUMBER_PROP signals the codegen
							// to use the OptRuntime.setObjectIndex that takes
							// a double index
							n.PutIntProp(Node.ISNUMBER_PROP, Node.LEFT);
						}
					}
					int rValueType = RewriteForNumberVariables(rValue, NumberType);
					if (rValueType == NumberType)
					{
						if (!ConvertParameter(rValue))
						{
							n.RemoveChild(rValue);
							n.AddChildToBack(new Node(Token.TO_OBJECT, rValue));
						}
					}
					return NoType;
				}

				case Token.GETELEM:
				{
					Node arrayBase = n.GetFirstChild();
					Node arrayIndex = arrayBase.GetNext();
					int baseType = RewriteForNumberVariables(arrayBase, NumberType);
					if (baseType == NumberType)
					{
						if (!ConvertParameter(arrayBase))
						{
							n.RemoveChild(arrayBase);
							n.AddChildToFront(new Node(Token.TO_OBJECT, arrayBase));
						}
					}
					int indexType = RewriteForNumberVariables(arrayIndex, NumberType);
					if (indexType == NumberType)
					{
						if (!ConvertParameter(arrayIndex))
						{
							// setting the ISNUMBER_PROP signals the codegen
							// to use the OptRuntime.getObjectIndex that takes
							// a double index
							n.PutIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
						}
					}
					return NoType;
				}

				case Token.CALL:
				{
					Node child = n.GetFirstChild();
					// the function node
					// must be an object
					RewriteAsObjectChildren(child, child.GetFirstChild());
					child = child.GetNext();
					// the first arg
					OptFunctionNode target = (OptFunctionNode)n.GetProp(Node.DIRECTCALL_PROP);
					if (target != null)
					{
						while (child != null)
						{
							int type = RewriteForNumberVariables(child, NumberType);
							if (type == NumberType)
							{
								MarkDCPNumberContext(child);
							}
							child = child.GetNext();
						}
					}
					else
					{
						RewriteAsObjectChildren(n, child);
					}
					return NoType;
				}

				default:
				{
					RewriteAsObjectChildren(n, n.GetFirstChild());
					return NoType;
				}
			}
		}
Esempio n. 3
0
		private static Node AddBeforeCurrent(Node parent, Node previous, Node current, Node toAdd)
		{
			if (previous == null)
			{
				if (!(current == parent.GetFirstChild()))
				{
					Kit.CodeBug();
				}
				parent.AddChildToFront(toAdd);
			}
			else
			{
				if (!(current == previous.GetNext()))
				{
					Kit.CodeBug();
				}
				parent.AddChildAfter(toAdd, previous);
			}
			return toAdd;
		}