public override void Compile(CompiledStatement parent, string token, LinkedList <string> tokens, LinkedList <string> lines)
        {
            base.Compile(parent, token, tokens, lines);

            Debug.Assert(parent.ChildCount > 0, "No value found for the left hand side of operator: " + token);

            // Take the previous statement and add it as a sub statement of the newly created operator - we will check for validity in the Compile function
            parent.MoveChildAtIndex(parent.ChildCount - 1, this);

            // Add this operator to the tree
            parent.Add(this);

            // Now check that there is another element after our operator that we can act on
            Debug.Assert(tokens.Count > 0, "No value found for the right hand side of operator: " + token);

            // Get the next token that appears on the right hand side of this operator
            string rhsOfOperatorToken = CelesteCompiler.PopToken();

            // Parse the next token which we will act on
            if (CelesteCompiler.CompileToken(rhsOfOperatorToken, parent))
            {
                // Take the value that has been added to the root and add it under this operator instead
                parent.MoveChildAtIndex(parent.ChildCount - 1, this);
            }
            else
            {
                // Error message if we cannot parse the next token
                Debug.Fail("Could not compile token: " + token + " in operator " + token);
            }
        }
Example #2
0
        /// <summary>
        /// Call compile when you wish to implement the function.
        /// Process the actual variable names that have been passed into the function using the token.
        /// Create a variable underneath this for each variable we are passing in.
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="token"></param>
        /// <param name="tokens"></param>
        /// <param name="lines"></param>
        public override void Compile(CompiledStatement parent, string token, LinkedList <string> tokens, LinkedList <string> lines)
        {
            // We have invoked this function because we have parentheses
            if (tokens.Count > 0 && tokens.First.Value == OpenParenthesis.scriptToken)
            {
                // Group our inputs under this object so that we can store them underneath this function
                CompiledStatement thisCallsParams = new CompiledStatement();
                if (ParameterNames.Count > 0)
                {
                    // Only add our parameters if we have any.
                    // Otherwise this will just strip away the start and end parentheses
                    Add(thisCallsParams);
                }

                string openingParenthesis = CelesteCompiler.PopToken();
                Debug.Assert(openingParenthesis == OpenParenthesis.scriptToken, "No opening parenthesis found for function " + Name);

                string parameter = CelesteCompiler.PopToken();

                CompiledStatement tempContainer = new CompiledStatement();
                while (parameter != CloseParenthesis.scriptToken)
                {
                    Debug.Assert(CelesteCompiler.CompileToken(parameter, tempContainer),
                                 "Failed to compile input parameter " + parameter);
                    parameter = CelesteCompiler.PopToken();
                }

                // Add null references first for all of the parameters we are missing
                for (int i = tempContainer.ChildCount; i < ParameterNames.Count; i++)
                {
                    // This will push null onto the stack for every parameter we have not provided an input for
                    Reference refToNull = new Reference(null);
                    refToNull.Compile(thisCallsParams, "null", tokens, lines);
                }

                // Then add the actual parameters we have inputted
                for (int i = tempContainer.ChildCount - 1; i >= 0; i--)
                {
                    // Add our parameters in reverse order, so they get added to the stack in reverse order
                    tempContainer.MoveChildAtIndex(i, thisCallsParams);
                }

                // Add a reference to this function in our compile tree after we have added all of the inputs
                base.Compile(parent, token, tokens, lines);
            }
            else
            {
                // If we have no brackets, we are trying to compile the function as a reference rather than as a call (for use in equality for example)
                Reference funcRef = new Reference(this);
                funcRef.Compile(parent, Name, tokens, lines);
            }

            // Any local variable that is not set will be null
            // Any extra parameters will be added, but because we add them in reverse order, if they are not needed they will just be thrown away on the stack
        }
Example #3
0
        public override void Compile(CompiledStatement parent, string token, LinkedList <string> tokens, LinkedList <string> lines)
        {
            base.Compile(parent, token, tokens, lines);

            // Unary operators act on other variables/values and so they must be included in the same token as another token (e.g. !var for example)
            // We remove the script token for the operator and split the other token out
            Debug.Assert(token.Length > 1);
            string rest = token.Remove(0, 1); // Removing wrong thing here

            // Add this operator to the tree
            parent.Add(this);

            // Parse the rest of the token which we will act on
            if (CelesteCompiler.CompileToken(rest, parent))
            {
                // Take the value that has been added to the root and add it under this operator instead
                parent.MoveChildAtIndex(parent.ChildCount - 1, this);
            }
            else
            {
                // Error message if we cannot parse the next token
                Debug.Fail("Could not compile token: " + token + " in operator " + token);
            }
        }
        /// <summary>
        /// If our first child is a binary operator, we swap it with this binary operator.
        /// This has the effect of evaluating this before the child operator.
        /// Useful when you wish to evaluate this operator before an assignment operator for example.
        /// </summary>
        protected void SwapWithChildBinaryOperator(CompiledStatement parent)
        {
            Debug.Assert(ChildCount > 0);
            Debug.Assert(ChildCompiledStatements[0] is AssignmentOperator);

            CompiledStatement child = ChildCompiledStatements[0];

            // We start with:
            //
            //              parent
            //             /
            //          this
            //         /    \
            //      child    C
            //     /     \
            //    A       B

            MoveChildAtIndex(0, parent);
            // Move the child to the parent - we now have:
            //
            //         parent
            //        /    \
            //     this      child
            //    /         /     \
            //   C         A       B

            Debug.Assert(parent.ChildCompiledStatements[parent.ChildCount - 2] == this);
            parent.MoveChildAtIndex(parent.ChildCount - 2, child);
            // Move this to be underneath the child operator - we now have:
            //
            //         parent
            //             \
            //              child
            //             /  |   \
            //            A   B    this
            //                         \
            //                           C

            Debug.Assert(child.ChildCount == 3);
            child.MoveChildAtIndex(1, this);
            // Move the B to under this - we now have:
            //
            //         parent
            //             \
            //              child
            //             /     \
            //            A       this
            //                   /    \
            //                  C      B

            Debug.Assert(ChildCount == 2);
            MoveChildAtIndex(0, this);
            // Extract and then reinsert C into this - this swaps C and B to give:
            //
            //         parent
            //             \
            //              child
            //             /     \
            //            A       this
            //                   /    \
            //                  B      C
        }