Exemple #1
0
        public override Expression VisitBasicExpression(BasicExpressionNode node)
        {
            // First, try to encode inline loop
            Expression result = this.EncodeInlinedLoop(node);

            if (result != null)
            {
                return(result);
            }
            // X3J20 definition: basic_expression ::= primary [messages cascaded_messages].
            PrimaryVisitor visitor = new PrimaryVisitor(this);

            result          = node.Primary.Accept(visitor);
            this.IsConstant = visitor.IsConstant;

            if (node.Messages != null)
            {
                MessageVisitor messageVisitor = new MessageVisitor(this, result, visitor.IsSuperSend, this.IsConstant, (node.CascadeMessages != null));
                result          = node.Messages.Accept(messageVisitor);
                this.IsConstant = false;    // After first message send, we are no longer a constant

                // Cascade messages ... this is handled by telling the message-visitor above that we have cascade messages
                // and need the receiver for cascade messages. The message-visitor has created a temporary variable for us
                // that contains the result of the next-last message (i.e. the receiver for cascade messages). It has
                // also noted if the send for that receiver was a super-send and if it is constant (for optimization).
                CascadeMessageSequenceNode cascade = node.CascadeMessages;
                if (cascade != null)
                {
                    List <Expression> cascadeExpressions = new List <Expression>();
                    cascadeExpressions.Add(result);
                    while (cascade != null)
                    {
                        // Loop and process each cascade in the cascade chain. There is nothing special here.
                        // The receiver, self/super send etc. is determined from the visitor of the original message send.
                        // We create new message-visitor for each cascade iteration, which has fresh receiver
                        // and other parameters. The result of the cascade messages is added to an expression list,
                        // which is converted to expression block. The block fulfills the semantics that the last
                        // expression in the list caries the result of the evaluation (same as required for sacsades).
                        MessageVisitor cascadeVisitor = new MessageVisitor(this,
                                                                           messageVisitor.CascadeReceiver, messageVisitor.CascadeSuperSend, messageVisitor.CascadeConstantReceiver, false);
                        cascadeExpressions.Add(cascade.Messages.Accept(cascadeVisitor));
                        cascade = cascade.NextCascade;
                    }
                    result = Expression.Block(typeof(object), new ParameterExpression[] { messageVisitor.CascadeReceiver }, cascadeExpressions);
                }
            }
            else if (visitor.IsSuperSend)
            {
                throw (new SemanticCodeGenerationException(CodeGenerationErrors.SuperNotFollowedByMessage)).SetErrorLocation(node);
            }

            return(result);
        }
Exemple #2
0
        protected virtual void ParseBaseicExpressionMessages(BasicExpressionNode expression, IPrimaryNode primary, Token token)
        {
            MessageSequenceNode messages = this.ParseMessages(expression, token);

            if (messages == null)
            {
                expression.SetContents(primary, null, null);
                return;
            }

            token = this.GetNextTokenxx(Preference.Default);
            CascadeMessageSequenceNode cascadeMessages = this.ParseCascadeMessageSequenceNode(expression, token);

            expression.SetContents(primary, messages, cascadeMessages);
        }
Exemple #3
0
        protected virtual BasicExpressionNode ParseBasicExpression(SemanticNode parent, Token token)
        {
            // PARSE: <basic expression> ::= <primary> [<messages> <cascaded messages>]
            BasicExpressionNode result = new BasicExpressionNode(parent);

            IPrimaryNode primary = this.ParsePrimary(result, token);

            if (primary == null)
            {
                this.ReportParserError(result, SemanticErrors.MissingPrimary, token);
                return(result);
            }

            token = this.GetNextTokenxx(Preference.Default);
            this.ParseBaseicExpressionMessages(result, primary, token);
            return(result);
        }
Exemple #4
0
        /// <summary>
        /// Visits the Basic Expression node.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public virtual TResult VisitBasicExpression(BasicExpressionNode node)
        {
            if (node.Primary != null)
            {
                node.Primary.Accept(this);
            }

            if (node.Messages != null)
            {
                node.Messages.Accept(this);
            }

            if (node.CascadeMessages != null)
            {
                node.CascadeMessages.Accept(this);
            }

            return(default(TResult));            // The default naive implementation
        }
Exemple #5
0
        /// <summary>
        /// Visits the Basic Expression node.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        public override bool VisitBasicExpression(BasicExpressionNode node)
        {
            if (node.Parent == null)
            {
                return(false);
            }

            if ((node.Primary == null) || !node.Primary.Accept(this))
            {
                return(false);
            }
            if ((node.Messages != null) && !node.Messages.Accept(this))
            {
                return(false);
            }
            if ((node.CascadeMessages != null) && !node.CascadeMessages.Accept(this))
            {
                return(false);
            }

            return(true);
        }
Exemple #6
0
        // <expression> ::=
        //      <assignment> |
        //      <basic expression>
        // <assignment> ::= <assignment target> assignmentOperator <expression>
        // <basic expression> ::= <primary> [<messages> <cascaded messages>]
        // <assignment target> := identifier
        // <primary> ::=
        //      identifier |
        //      <literal> |
        //      <block constructor> |
        //      ( '(' <expression> ')' )

        protected virtual ExpressionNode ParseExpression(SemanticNode parent, Token token)
        {
            // Tricky ... first try for <assignment>
            if (token is IdentifierToken)
            {
                // In here, we either have an <assignment target> or <primary> of a <basic expression>
                IdentifierToken identifier = (IdentifierToken)token;

                // Try to check for assignmentOperator
                token = this.GetNextTokenxx(Preference.Default);
                if (token is AssignmentOperatorToken)
                {
                    // OK, it's <assignment>
                    return(this.ParseAssignment(parent, identifier, (AssignmentOperatorToken)token));
                }

                // Must recover ... it is a <basic expression> anyway.
                // PARSE: identifier [<messages> <cascaded messages>]
                BasicExpressionNode result = new BasicExpressionNode(parent);
                this.ParseBaseicExpressionMessages(result, new VariableReferenceleNode(result, identifier), token);
                return(result);
            }
            return(this.ParseBasicExpression(parent, token));
        }
Exemple #7
0
 /// <summary>
 /// Visits the Basic Expression node.
 /// </summary>
 /// <param name="node">The node to visit.</param>
 public virtual TResult VisitBasicExpression(BasicExpressionNode node)
 {
     throw new NotImplementedException();
 }
Exemple #8
0
        private Expression EncodeInlinedLoop(BasicExpressionNode node)
        {
            if (node.CascadeMessages != null)
            {
                return(null);
            }
            if (node.Messages == null)
            {
                return(null);
            }
            BlockNode conditionBlock = node.Primary as BlockNode;

            if (conditionBlock == null)
            {
                return(null);
            }
            if (conditionBlock.Arguments.Count != 0)
            {
                return(null);
            }

            UnaryBinaryKeywordMessageSequenceNode unarySeq = node.Messages as UnaryBinaryKeywordMessageSequenceNode;

            if (unarySeq != null)
            {
                string selector = unarySeq.Message.SelectorToken.Value;
                if ((selector != "whileTrue") && (selector != "whileFalse"))
                {
                    return(null);
                }
                return(this.EncodeInlineWhile(conditionBlock, null, (selector == "whileFalse")));
            }
            KeywordMessageSequenceNode keywordSeq = node.Messages as KeywordMessageSequenceNode;

            if (keywordSeq != null)
            {
                if (keywordSeq.Message.SelectorTokens.Count != 1)
                {
                    return(null);
                }
                string selector = keywordSeq.Message.SelectorTokens[0].Value;
                if ((selector != "whileTrue:") && (selector != "whileFalse:"))
                {
                    return(null);
                }
                if (keywordSeq.Message.Arguments.Count != 1)
                {
                    return(null);
                }
                KeywordArgumentNode arg = keywordSeq.Message.Arguments[0];
                if (arg.Messages != null)
                {
                    return(null);
                }
                BlockNode valueBlock = arg.Primary as BlockNode;
                if (valueBlock == null)
                {
                    return(null);
                }
                if (valueBlock.Arguments.Count != 0)
                {
                    return(null);
                }
                return(this.EncodeInlineWhile(conditionBlock, valueBlock, (selector == "whileFalse:")));
            }
            return(null);
        }