Beispiel #1
0
    public Phrase(Expression function, params Expression[] inputs) : base(null)
    {
        if (inputs.Length > function.GetNumFreeArgs())
        {
            throw new ArgumentException("Too many arguments passed to a function expression");
        }

        Expression newExpression = function;

        int counter = 0;

        for (int i = 0; i < inputs.Length; i++)
        {
            if (inputs[i] == null)
            {
                counter++;
            }
            newExpression = new Phrase(newExpression, inputs[i], counter);
        }

        this.type       = newExpression.type;
        this.headString = newExpression.headString;
        this.headType   = newExpression.headType;
        this.args       = new Expression[newExpression.GetNumArgs()];

        for (int i = 0; i < newExpression.GetNumArgs(); i++)
        {
            this.args[i] = newExpression.GetArg(i);
        }
    }
    /**
     * returns false if 2 expressions shouldn't combine with each other
     */
    public bool CombineWith(ExpressionPiece inputExpression, int index)
    {
        Expression expr = null;

        //try to create new Expression
        try {
            expr = new Phrase(this.expression, inputExpression.expression, index);
        } catch (Exception e) {
            Debug.LogException(e);
            this.gameController.failure.Play();
            return(false);
        }

        // generate new Piece
        GameObject      exprPiece         = Resources.Load("Piece") as GameObject;
        GameObject      exprPieceInstance = Instantiate(exprPiece, GetSpawnPosition(), Quaternion.identity) as GameObject;
        ExpressionPiece exprPieceScript   = exprPieceInstance.GetComponent <ExpressionPiece>();

        exprPieceScript.expression = expr;
        exprPieceScript.arguments  = new ExpressionPiece[expr.GetNumArgs()];

        if (exprPieceScript.arguments.Length > 0)
        {
            exprPieceScript.heightInUnits = 2;
        }

        float originalPieceX = this.transform.position.x;
        float originalPieceY = this.transform.position.y;

        // exprPieceInstance.transform.position = new Vector3(originalPieceX, originalPieceY, 0);

        exprPieceScript.gameController = gameController;
        exprPieceScript.id             = expr.ToString();

        exprPieceScript.index = this.index;

        if (this.parentExpressionPiece != null)
        {
            exprPieceScript.SetParentExpressionPiece(this.parentExpressionPiece.DeepCopy()); // DeepCopy here bc 'this' will get destroyed
        }

        // int noArgInputWidth = 1;
        // int noArgInputHeight = 1;

        // for (int i = 0; i < inputExpression.arguments.Legth; i++) {
        //     if (!inputExpression[i].id.Equals("_")) {
        //         noArgInputWidth += inputExpression[i].widthInUnits;
        //         noArgInputHeight = Max(noArgInputHeight, inputExpression.heightInUnits + 1);
        //     }
        // }

        exprPieceScript.widthInUnits  = 1;
        exprPieceScript.widthInUnits += inputExpression.widthInUnits;

        exprPieceScript.heightInUnits = Max(exprPieceScript.heightInUnits, inputExpression.heightInUnits + 1);

        //Add the arguments to the new piece
        int counter = -1;

        for (int i = 0; i < arguments.Length; i++)
        {
            if (this.arguments[i] == null)
            {
                counter++;
                exprPieceScript.widthInUnits++;
            }
            else
            {
                // this happens to every argument, whether blank or filled
                float originalArgLocalX = this.arguments[i].transform.localPosition.x;
                float originalArgLocalY = this.arguments[i].transform.localPosition.y;

                // place a copy of the old argument in the same position in the new expression.
                exprPieceScript.arguments[i] = this.arguments[i].DeepCopy();
                exprPieceScript.arguments[i].transform.SetParent(exprPieceInstance.transform);
                exprPieceScript.arguments[i].gameObject.transform.localPosition = new Vector3(originalArgLocalX, originalArgLocalY, 0);

                // changing the width and height of the new expression
                exprPieceScript.widthInUnits += exprPieceScript.arguments[i].widthInUnits;
                exprPieceScript.heightInUnits = Max(exprPieceScript.heightInUnits, exprPieceScript.arguments[i].heightInUnits + 1);

                // if it's an empty argument slot, then move forward in the
                // argument index, and decrement the argument slot's index by 1 if
                // the argument has already been placed to preserve the new indexing.
                if (this.arguments[i].id.Equals("_"))
                {
                    if (counter > index)
                    {
                        exprPieceScript.arguments[i].index--;
                    }
                    counter++;
                }
            }

            // place the input expression in the appropriate argument position.
            if (counter == index)
            {
                float originalArgLocalX = this.arguments[i].transform.localPosition.x;
                float originalArgLocalY = this.arguments[i].transform.localPosition.y;

                //need to destroy the empty arg that this piece is replacing
                Destroy(exprPieceScript.arguments[i].gameObject, 0.0f);

                exprPieceScript.arguments[i] = inputExpression.DeepCopy();
                exprPieceScript.arguments[i].gameObject.transform.localPosition =
                    new Vector3(originalArgLocalX, originalArgLocalY, 0);
                exprPieceScript.arguments[i].transform.SetParent(exprPieceInstance.transform);

                counter++;
                exprPieceScript.widthInUnits--;
            }
        }

        int xPositionInUnits = 1;

        // this is setting the parentexpressionpiece and parent of all of the new
        // expression's arguments as the new expression. This doesn't happen in
        // deepcopy because deepcopy makes a new copy of the expression to set.
        for (int i = 0; i < arguments.Length; i++)
        {
            float argLocalX = exprPieceScript.arguments[i].transform.localPosition.x;
            float argLocalY = exprPieceScript.arguments[i].transform.localPosition.y;

            float changeY = ((exprPieceScript.heightInUnits - 2) / 2f) * PIXELS_PER_UNIT;

            if (exprPieceScript.arguments[i].id.Equals("_"))
            {
                exprPieceScript.arguments[i].gameObject.transform.localPosition =
                    new Vector3(
                        ((-0.5f * exprPieceScript.widthInUnits) + xPositionInUnits + 0.5f - BUFFER_IN_UNITS) * PIXELS_PER_UNIT,
                        argLocalY + changeY);
            }

            exprPieceScript.arguments[i].SetParentExpressionPiece(exprPieceScript);
            exprPieceInstance.transform.SetParent(this.transform.parent.transform);

            // Debug.Log(exprPieceScript.expression + "'s width is " + exprPieceScript.widthInUnits);
            // Debug.Log(exprPieceScript.expression + "[" + i + "]'s width is " + arguments[i].widthInUnits);
            xPositionInUnits += exprPieceScript.arguments[i].widthInUnits;
        }

        exprPieceInstance.transform.SetParent(this.transform.parent.transform);
        exprPieceScript.SetVisual(exprPieceScript.GenerateVisual());

        int indexToOccupy = this.gameObject.transform.GetSiblingIndex();

        // foreach (ExpressionPiece arg in this.arguments) {
        //     Destroy(arg.gameObject, 0.0f);
        // }

        Destroy(this.gameObject, 0.0f);
        // the arguments to the input expression aren't being destroyed properly. They're just floating around
        Destroy(inputExpression.gameObject, 0.0f);

        exprPiece.transform.SetSiblingIndex(indexToOccupy);

        return(true);
    }