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); }
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); }
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); }
/// <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 }
/// <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); }
// <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)); }
/// <summary> /// Visits the Basic Expression node. /// </summary> /// <param name="node">The node to visit.</param> public virtual TResult VisitBasicExpression(BasicExpressionNode node) { throw new NotImplementedException(); }
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); }