public override TypeNode InferTypeOfBinaryExpression(TypeNode t1, TypeNode t2, BinaryExpression binaryExpression) { // // For addition or subtraction operations involving a set (as either operand) // the result will be a set of the same type. Later, in the Checker, we'll // verify that the combination of operands is valid. Here, we can quickly infer // the type of the result. // switch (binaryExpression.NodeType) { case NodeType.Add: case NodeType.Sub: if (t1 is Set) return t1; else if (t2 is Set) return t2; break; case (NodeType)ZingNodeType.In: return SystemTypes.Boolean; default: break; } return base.InferTypeOfBinaryExpression(t1, t2, binaryExpression); }
public override Expression VisitBinaryExpression(BinaryExpression binaryExpression) { if (binaryExpression == null) return null; binaryExpression.Operand2 = this.VisitExpression(binaryExpression.Operand2); binaryExpression.Operand1 = this.VisitExpression(binaryExpression.Operand1); if (binaryExpression.Type == null) binaryExpression.Type = binaryExpression.Operand1.Type; //Hack: need proper inferencing return binaryExpression; }
public override Expression ImplicitCoercion(Expression source, TypeNode targetType, TypeViewer typeViewer) { // LJW: added third parameter "typeViewer" so we override the correct thing if (source == null || source.Type == null || targetType == null) return null; if (source.Type is EnumNode && targetType == SystemTypes.Int32) { return source; } if (source.Type == SystemTypes.Object) { if (targetType is Chan || targetType is Set || targetType is ZArray || targetType is Class) return source; else { this.HandleError(source, System.Compiler.Error.NoImplicitCoercion, "object", targetType.FullName); return null; } } if (targetType == SystemTypes.Object) { if (!(source.Type is Chan || source.Type is Set || source.Type is ZArray || source.Type is Class)) { this.HandleError(source, System.Compiler.Error.NoImplicitCoercion, source.Type.FullName, "object"); return null; } } if (source.Type == SystemTypes.Int32 && targetType == SystemTypes.UInt8) { BinaryExpression binExpr = new BinaryExpression(source, new MemberBinding(null, SystemTypes.UInt8), NodeType.Castclass, source.SourceContext); binExpr.Type = SystemTypes.UInt8; return binExpr; } if (source.Type == SystemTypes.UInt8 && targetType == SystemTypes.Int32) { BinaryExpression binExpr = new BinaryExpression(source, new MemberBinding(null, SystemTypes.Int32), NodeType.Castclass, source.SourceContext); binExpr.Type = SystemTypes.Int32; return binExpr; } return base.ImplicitCoercion(source, targetType, typeViewer); }
// // JoinStatement nodes can be traversed in two ways - to generate a "runnable" // expression, or to generate the body of their basic block. We separate out // the first kind of traversal into the following two methods. // public Expression GetRunnablePredicate(JoinStatement joinStatement) { Expression fullExpr = null; for (int i = 0, n = joinStatement.joinPatternList.Length; i < n; i++) { Expression jpExpr = (Expression)this.Visit(joinStatement.joinPatternList[i]); if (fullExpr == null) fullExpr = jpExpr; else fullExpr = new BinaryExpression(fullExpr, jpExpr, NodeType.LogicalAnd, joinStatement.SourceContext); } return fullExpr; }
public override Expression VisitBinaryExpression(BinaryExpression binaryExpression) { Expression result = base.VisitBinaryExpression(binaryExpression); SpecSharpCompilerOptions options = this.currentOptions as SpecSharpCompilerOptions; if (options != null && options.CheckContractAdmissibility) { if ((insideMethodContract || insideInvariant) && (binaryExpression.NodeType == NodeType.Eq || binaryExpression.NodeType == NodeType.Ne) && binaryExpression.Operand1 != null && binaryExpression.Operand1.Type != null && !binaryExpression.Operand1.Type.IsValueType) { MightReturnNewlyAllocatedObjectVisitor visitor = new MightReturnNewlyAllocatedObjectVisitor(this); this.TransferStateTo(visitor); visitor.CurrentMethod = this.currentMethod; visitor.VisitExpression(binaryExpression.Operand1); if (visitor.IsMRNAO) { visitor.IsMRNAO = false; visitor.VisitExpression(binaryExpression.Operand2); if (visitor.IsMRNAO) this.HandleError(binaryExpression, Error.BothOperandsOfReferenceComparisonMightBeNewlyAllocated); } } } return result; }
public override Expression VisitBinaryExpression(BinaryExpression binaryExpression) { if (binaryExpression == null) return null; Expression opnd1 = binaryExpression.Operand1 = this.VisitExpression(binaryExpression.Operand1); Expression opnd2 = binaryExpression.Operand2 = this.VisitExpression(binaryExpression.Operand2); if (opnd1 == null || opnd2 == null) return null; Set opnd1TypeAsSet = opnd1.Type as Set; Set opnd2TypeAsSet = opnd2.Type as Set; Literal lit1 = opnd1 as Literal; Literal lit2 = opnd2 as Literal; if ((opnd1TypeAsSet != null || opnd2TypeAsSet != null) && !this.validSetOperations.Contains(binaryExpression) && binaryExpression.NodeType != (NodeType)ZingNodeType.In) { this.HandleError(binaryExpression, Error.InvalidSetExpression); return null; } switch (binaryExpression.NodeType) { case NodeType.Add: case NodeType.Sub: if (opnd1TypeAsSet != null) { if (opnd1TypeAsSet.SetType != opnd2.Type && opnd1.Type != opnd2.Type) { if (opnd2TypeAsSet != null) this.HandleError(opnd1, Error.IncompatibleSetTypes); else this.HandleError(opnd2, Error.IncompatibleSetOperand); return null; } return binaryExpression; } break; case NodeType.LogicalAnd: { if (lit1 != null && lit1.Value is bool) { if (((bool)lit1.Value) == true) return opnd2; else return opnd1; } if (lit2 != null && lit2.Value is bool) { if (((bool)lit2.Value) == true) return opnd1; else return opnd2; } } break; case NodeType.LogicalOr: { if (lit1 != null && lit1.Value is bool) { if (((bool)lit1.Value) == false) return opnd2; else return opnd1; } if (lit2 != null && lit2.Value is bool) { if (((bool)lit2.Value) == false) return opnd1; else return opnd2; } } break; case (NodeType)ZingNodeType.In: if (opnd2TypeAsSet == null) { this.HandleError(opnd2, Error.ExpectedSetType); return null; } if (opnd2TypeAsSet.SetType != opnd1.Type) { this.HandleError(opnd1, Error.IncompatibleSetOperand); return null; } return binaryExpression; default: break; } return base.CoerceBinaryExpressionOperands(binaryExpression, opnd1, opnd2); }
private BinaryExpression VisitIn(BinaryExpression expr) { Write("("); this.Visit(expr.Operand1); Write(" in "); this.Visit(expr.Operand2); Write(")"); return expr; }
void AddReadAllGroup(Class serializer, Block block, TypeNode type, StatementList statements, Identifier reader, Expression target, Expression required, Expression result, ArrayList members, Member mixedMember) { // todo: keep track of which members have been read and report error on duplicates MethodCall read = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Read")), new ExpressionList()); Local sb = new Local(SystemTypes.StringBuilder); bool isMixed = mixedMember != null; if (isMixed) { statements.Add(new AssignmentStatement(sb, new Construct(new MemberBinding(null, SystemTypes.StringBuilder), new ExpressionList(), SystemTypes.StringBuilder))); } Block whileBody = new Block(new StatementList()); BinaryExpression notEndTag = new BinaryExpression( new QualifiedIdentifier(reader, Identifier.For("NodeType")) , new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("EndElement")), NodeType.Ne); BinaryExpression notEOF = new BinaryExpression( new QualifiedIdentifier(reader, Identifier.For("EOF")), Literal.True, NodeType.Ne); While w = new While(new BinaryExpression(notEndTag, notEOF, NodeType.And), whileBody); statements.Add(w); Local nameLocal = new Local(Identifier.For("name"),SystemTypes.String,block); Local nsLocal = new Local(Identifier.For("ns"),SystemTypes.String,block); Local nodeType = new Local(Identifier.For("nodeType"),Runtime.XmlNodeType,block); whileBody.Statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); whileBody.Statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI")))); whileBody.Statements.Add(new AssignmentStatement(nodeType, new QualifiedIdentifier(reader, Identifier.For("NodeType")))); Block childBlock = whileBody; if (isMixed) { // Append the text node to the current StringBuilder contents. childBlock = new Block(new StatementList()); If ifText = new If(IsTextNode(nodeType), new Block(new StatementList()), childBlock); whileBody.Statements.Add(ifText); ExpressionList args = new ExpressionList(); args.Add(new QualifiedIdentifier(reader, Identifier.For("Value"))); ifText.TrueBlock.Statements.Add(new ExpressionStatement(new MethodCall( new QualifiedIdentifier(sb, Identifier.For("Append")), args))); ifText.TrueBlock.Statements.Add(new ExpressionStatement(read)); // advance to next node } If ifElement = new If(new BinaryExpression(nodeType, new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("Element")), NodeType.Eq), new Block(new StatementList()), new Block(new StatementList())); childBlock.Statements.Add(ifElement); childBlock = ifElement.TrueBlock; //AddConsoleWrite(statements, new Literal("name=",SystemTypes.String)); //AddConsoleWriteLine(statements, nameLocal); //AddConsoleWrite(statements, new Literal("nodeType=",SystemTypes.String)); //AddConsoleWriteLine(statements, nodeType); foreach (NamedNode childNode in members) { if (!(childNode.Member is Field || childNode.Member is Property)) { AddError(statements, reader, RuntimeError.SerializationOfTypeNotSupported, new Literal(childNode.Member.GetType().FullName, SystemTypes.String)); } else { Expression mb = GetMemberBinding(target, childNode.Member); childBlock = AddReadChild(block, childBlock.Statements, childNode.Name, childNode.TypeNode, mb, reader, result, true, false).FalseBlock; // todo: throw error if child is required. (e.g. NonEmptyIEnumerable...) } } // if it isn't any of the expected elements then throw an error. AddError(childBlock.Statements, reader, RuntimeError.NoSuchMember, new Expression[2]{new Literal(tempChecker.GetTypeName(type),SystemTypes.String), nameLocal}); // If it's not an element then consume it anyway to keep the reader advancing. // Probably a comment or PI or something. ifElement.FalseBlock.Statements.Add(new ExpressionStatement(new MethodCall( new QualifiedIdentifier(reader, Identifier.For("Skip")), new ExpressionList()))); if (isMixed) { statements.Add(new AssignmentStatement(GetMemberBinding(target, mixedMember), new MethodCall(new QualifiedIdentifier(sb, Identifier.For("ToString")), new ExpressionList()))); } statements.Add(new AssignmentStatement(result, Literal.True)); }
void AddWriteChoice(TypeUnion tu, StatementList statements, TypeNode referringType, Expression src, Identifier writer) { // generate the following code: // Type srcType = src.GetType(); // if (choiceType.IsAssignableFrom(srcType)){ // XxxxSerializer s = new XxxxSerializer(); // s.Serialize((runtimeType)src, writer); // } else if (...) { // // and so on. // } // What we cannot do here is by creating nested XmlSerializers // based on runtime type because this could cause infinite recurrsion. // So we cannot serialize a type union where one of the choices is "object". TypeNodeList choices = tu.Types; MethodCall call = new MethodCall(); call.Callee = new QualifiedIdentifier(src, Identifier.For("GetType")); call.Operands = new ExpressionList(); Local local = new Local(SystemTypes.Type); statements.Add(new AssignmentStatement(local, call)); for (int i = 0, n = choices.Length; i < n; i++) { TypeNode choiceType = choices[i]; if (choiceType == null) continue; // type resolution error. // if (choiceType.IsAssignableFrom(srcType)){ BinaryExpression condition = new BinaryExpression( new MethodCall( new QualifiedIdentifier(new UnaryExpression(new MemberBinding(null, choiceType), NodeType.Typeof), Identifier.For("IsAssignableFrom")), new ExpressionList(new Expression[] { local })), Literal.True, NodeType.Eq); Block block = new Block(); block.Statements = new StatementList(); BinaryExpression cast = CastTo(src, choiceType); Expression name = null, ns = null; GetNameAndNamespace(choiceType, out name, out ns); Expression simplename = name, simplens = ns; // Check for choice of type: [string] and match this with XmlTextNode. TypeNode unwrapped = UnwrapSingletonTuple(choiceType, true); if (unwrapped == null) unwrapped = choiceType; if (unwrapped != null && unwrapped.IsPrimitive) { simplename = simplens = null; choiceType = unwrapped; } if (!AddWriteSimpleType(choiceType, block.Statements, referringType, writer, cast, simplename, simplens)) { AddCallSerializer(choiceType, block.Statements, cast, writer, name, ns); } If ifStatement = new If(condition, block, null); statements.Add(ifStatement); } }
BinaryExpression IsStartOf(Block block, TypeNode type, StatementList statements, Expression nameLocal, Expression nsLocal, StringBuilder expecting) { BinaryExpression result = null; if (IsStructuralType(type)) { SchemaElementDecl sd = SchemaElementDecl.Compile(this.module, type, Checker.GetCollectionElementType(type), this.errorHandler, schemaElementDeclCache); SchemaValidator validator = validator = sd.CreateValidator(this.errorHandler); ValidationState context = new ValidationState(); context.ErrorHandler = this.errorHandler; validator.validator.InitValidation(context); ArrayList members = validator.validator.ExpectedElements(context, false, false); foreach (TerminalNode node in members) { if (node is NamedNode) { NamedNode n = node as NamedNode; Identifier name = n.Name; if (expecting.Length>0) expecting.Append(" | "); expecting.Append(name.Name); BinaryExpression isName = new BinaryExpression(nameLocal, new Literal(name.Name, SystemTypes.String), NodeType.Eq); if (name.Prefix != null) { isName = new BinaryExpression(isName, new BinaryExpression(nsLocal, new Literal(name.Prefix.Name, SystemTypes.String), NodeType.Eq), NodeType.And); } if (result == null) result = isName; else result = new BinaryExpression(result, isName, NodeType.Or); } else if (node is WildcardNode) { // todo:??? } } } else { Identifier name = Checker.GetDefaultElementName(type); if (expecting.Length>0) expecting.Append(" | "); expecting.Append(name.Name); result = new BinaryExpression(nameLocal, new Literal(name.Name, SystemTypes.String), NodeType.Eq); if (name.Prefix != null) { result = new BinaryExpression(result, new BinaryExpression(nsLocal, new Literal(name.Prefix.Name, SystemTypes.String), NodeType.Eq), NodeType.And); } } return result; }
public override TypeNode InferTypeOfBinaryExpression(TypeNode t1, TypeNode t2, BinaryExpression binaryExpression){ if (binaryExpression == null) return SystemTypes.Object; bool eligible = false; switch (binaryExpression.NodeType){ case NodeType.Add: case NodeType.And: case NodeType.Ceq: case NodeType.Cgt: case NodeType.Cgt_Un: case NodeType.Clt: case NodeType.Clt_Un: case NodeType.Div: case NodeType.Ge: case NodeType.Gt: case NodeType.Mul: case NodeType.Le: case NodeType.Lt: case NodeType.Or: case NodeType.Rem: case NodeType.Sub: case NodeType.Xor: eligible = true; break; } bool opnd1IsNullLiteral = Literal.IsNullLiteral(binaryExpression.Operand1); bool opnd2IsNullLiteral = Literal.IsNullLiteral(binaryExpression.Operand2); if (eligible && opnd1IsNullLiteral && !opnd2IsNullLiteral) { TypeNode t = base.InferTypeOfBinaryExpression(t2, t2, binaryExpression); if (t != null && t.IsValueType && !this.typeSystem.IsNullableType(t)) return SystemTypes.GenericNullable.GetTemplateInstance(this.currentType, t); return t; }else if (eligible && !opnd1IsNullLiteral && opnd2IsNullLiteral){ TypeNode t = base.InferTypeOfBinaryExpression(t1, t1, binaryExpression); if (t != null && t.IsValueType && !this.typeSystem.IsNullableType(t)) return SystemTypes.GenericNullable.GetTemplateInstance(this.currentType, t); return t; }else{ return base.InferTypeOfBinaryExpression(t1, t2, binaryExpression); } }
private Expression ParseIndexerCallOrSelector(Expression expression, TokenSet followers){ TokenSet followersOrContinuers = followers|Token.LeftBracket|Token.LeftParenthesis|Token.Dot; for(;;){ switch (this.currentToken){ case Token.LeftBracket: SourceContext lbCtx = this.scanner.CurrentSourceContext; this.GetNextToken(); if (this.insideModifiesClause && this.currentToken == Token.Multiply){ // Handle code such as // // modifies myArray[*]; // // which means that the method may modify all elements of myArray. int savedStartPos = this.scanner.startPos; int savedEndPos = this.scanner.endPos; this.GetNextToken(); if (this.currentToken == Token.RightBracket){ SourceContext sctxt = this.scanner.CurrentSourceContext; sctxt.StartPos = lbCtx.StartPos; this.GetNextToken(); return new ModifiesArrayClause(expression, sctxt); } this.scanner.startPos = savedStartPos; this.scanner.endPos = savedEndPos; } int endCol; ExpressionList indices = this.ParseIndexList(followersOrContinuers, lbCtx, out endCol); Indexer indexer = new Indexer(expression, indices); indexer.SourceContext = expression.SourceContext; indexer.SourceContext.EndPos = endCol; indexer.ArgumentListIsIncomplete = this.scanner.GetChar(endCol-1) != ']'; expression = indexer; break; case Token.LessThan: SourceContext ltCtx = this.scanner.CurrentSourceContext; ScannerState ss = this.scanner.state; int arity; TypeNodeList typeArguments = this.ParseTypeArguments(true, false, followers|Token.LeftParenthesis, out endCol, out arity); if (typeArguments == null || (typeArguments.Count > 1 && Parser.TypeArgumentListNonFollower[this.currentToken])) { this.scanner.endPos = ltCtx.StartPos; this.scanner.state = ss; this.currentToken = Token.None; this.GetNextToken(); return expression; } TemplateInstance instance = new TemplateInstance(expression, typeArguments); instance.TypeArgumentExpressions = typeArguments == null ? null : typeArguments.Clone(); instance.SourceContext = expression.SourceContext; instance.SourceContext.EndPos = endCol; expression = instance; break; case Token.LeftParenthesis: SourceContext lpCtx = this.scanner.CurrentSourceContext; this.GetNextToken(); ExpressionList arguments = this.ParseArgumentList(followersOrContinuers, lpCtx, out endCol); if (expression == null) return null; if (expression is Identifier && arguments.Count == 1 && ((Identifier)expression).Name == "old" && InEnsuresContext){ OldExpression old = new OldExpression(arguments[0]); typeArguments = null; old.SourceContext = expression.SourceContext; old.SourceContext.EndPos = endCol; expression = old; break; } if (expression is TemplateInstance) ((TemplateInstance)expression).IsMethodTemplate = true; //HS D: a lambda hole... : make a linear comb of args for hole if (expression is Hole) { SourceContext sctx = expression.SourceContext; Expression res = expression; if (arguments.Count > 0) { res = new BinaryExpression(expression, arguments[0], NodeType.Mul, sctx); for (int i = 1; i < arguments.Count; i++) res = new BinaryExpression(res, new BinaryExpression(new Hole(sctx), arguments[i], NodeType.Mul, sctx), NodeType.Add, sctx); res = new LambdaHole(res, new Hole(sctx), NodeType.Add, sctx); } expression = res; break; } MethodCall mcall = new MethodCall(expression, arguments); typeArguments = null; mcall.GiveErrorIfSpecialNameMethod = true; mcall.SourceContext = expression.SourceContext; mcall.SourceContext.EndPos = endCol; mcall.ArgumentListIsIncomplete = this.scanner.GetChar(endCol-1) != ')'; expression = mcall; break; case Token.LeftBrace: if (this.compatibilityOn || this.scanner.TokenIsFirstAfterLineBreak) goto default; Expression quant = this.ParseComprehension(followers); if (quant == null) { break; } Block argBlock = new Block(new StatementList(new ExpressionStatement(quant)),quant.SourceContext, this.insideCheckedBlock, this.insideUncheckedBlock, this.inUnsafeCode); argBlock.IsUnsafe = this.inUnsafeCode; argBlock.SourceContext = quant.SourceContext; ExpressionList arguments2 = new ExpressionList(new AnonymousNestedFunction(new ParameterList(0), argBlock, quant.SourceContext)); MethodCall mcall2 = new MethodCall(expression, arguments2); typeArguments = null; mcall2.GiveErrorIfSpecialNameMethod = true; mcall2.SourceContext = expression.SourceContext; mcall2.SourceContext.EndPos = this.scanner.endPos; expression = mcall2; break; case Token.Dot: expression = this.ParseQualifiedIdentifier(expression, followersOrContinuers); break; case Token.RealLiteral: string tokStr = this.scanner.GetTokenSource(); if (this.insideModifiesClause && tokStr == ".0") { // this case is here only for parsing ".0" while parsing a modifies clause // e.g., "modifies this.0;" this.GetNextToken(); // eat the ".0" return new ModifiesNothingClause(expression, this.scanner.CurrentSourceContext); } else { return expression; } case Token.Arrow: if (!this.allowUnsafeCode){ this.HandleError(Error.IllegalUnsafe); this.allowUnsafeCode = true; } this.currentToken = Token.Dot; AddressDereference ad = new AddressDereference(); ad.Address = expression; ad.ExplicitOperator = AddressDereference.ExplicitOp.Arrow; ad.SourceContext = expression.SourceContext; expression = this.ParseQualifiedIdentifier(ad, followersOrContinuers); break; default: return expression; } } }
public override Expression VisitBinaryExpression(BinaryExpression binaryExpression) { binaryExpression = (BinaryExpression)binaryExpression.Clone(); if(binaryExpression.NodeType == NodeType.Ldvirtftn) { binaryExpression.Operand1 = simplify(binaryExpression.Operand1, true); return binaryExpression; } binaryExpression.Operand1 = simplify(binaryExpression.Operand1, true); binaryExpression.Operand2 = simplify(binaryExpression.Operand2, true); return binaryExpression; }
public override Expression VisitBinaryExpression(BinaryExpression binaryExpression) { if (binaryExpression == null) return null; binaryExpression = (BinaryExpression)binaryExpression.Clone(); binaryExpression.Operand1 = this.VisitExpression(binaryExpression.Operand1); binaryExpression.Operand2 = this.VisitExpression(binaryExpression.Operand2); return binaryExpression; }
public override Statement VisitExpressionStatement(ExpressionStatement statement) { // Check for statements that require special handling AssignmentExpression assignmentExpr = statement.Expression as AssignmentExpression; AssignmentStatement assignmentStatement = null; MethodCall methodCall = statement.Expression as MethodCall; SelfExpression selfAccess = statement.Expression as SelfExpression; UnaryExpression choose = null; if (assignmentExpr != null) { assignmentStatement = assignmentExpr.AssignmentStatement as AssignmentStatement; if (assignmentStatement != null && assignmentStatement.Source is MethodCall) methodCall = (MethodCall)assignmentStatement.Source; if (assignmentStatement != null && assignmentStatement.Source is UnaryExpression && assignmentStatement.Source.NodeType == (NodeType)ZingNodeType.Choose) choose = (UnaryExpression)assignmentStatement.Source; if (assignmentStatement != null && assignmentStatement.Source is BinaryExpression && assignmentStatement.Target.Type is Set) { BinaryExpression binaryExpression = (BinaryExpression)assignmentStatement.Source; this.validSetOperations.Add(binaryExpression, null); if (SameVariable(assignmentStatement.Target, binaryExpression.Operand1)) { // all is well } else if (SameVariable(assignmentStatement.Target, binaryExpression.Operand2)) { // swap operands to put the statement in its desired form Expression tmp = binaryExpression.Operand1; binaryExpression.Operand1 = binaryExpression.Operand2; binaryExpression.Operand2 = tmp; } else { this.HandleError(statement, Error.InvalidSetAssignment); return null; } } // // If the source and target types aren't equal, but both are numeric, then we // insert an implied cast to the target type. If & when we add an explicit cast // operator to Zing, then this can be removed. // if (assignmentStatement != null && assignmentStatement.Source != null && assignmentStatement.Source.Type != null && assignmentStatement.Target != null && assignmentStatement.Target.Type != null && assignmentStatement.Source.Type != assignmentStatement.Target.Type && assignmentStatement.Source.Type.IsPrimitiveNumeric && assignmentStatement.Target.Type.IsPrimitiveNumeric) { // Wrap a cast operator around the source expression BinaryExpression binExpr = new BinaryExpression(assignmentStatement.Source, new MemberBinding(null, assignmentStatement.Target.Type), NodeType.Castclass, assignmentStatement.Source.SourceContext); binExpr.Type = assignmentStatement.Target.Type; assignmentStatement.Source = binExpr; } } if (methodCall != null) this.validMethodCalls.Add(methodCall, null); if (selfAccess != null) this.validSelfAccess.Add(selfAccess, null); if (choose != null) this.validChooses.Add(choose, null); return base.VisitExpressionStatement(statement); }
public virtual Expression VisitBinaryExpression(BinaryExpression binaryExpression) { if (binaryExpression == null) return null; binaryExpression.Operand1 = this.VisitExpression(binaryExpression.Operand1); binaryExpression.Operand2 = this.VisitExpression(binaryExpression.Operand2); return binaryExpression; }
// // Re-write expressions to reference globals, locals, parameters, and the heap // in the appropriate way for our runtime. // public override Expression VisitBinaryExpression(BinaryExpression binaryExpression) { if (binaryExpression.NodeType == NodeType.ExplicitCoercion) { binaryExpression.NodeType = NodeType.Castclass; binaryExpression.Operand1 = this.VisitExpression(binaryExpression.Operand1); return binaryExpression; } else if (binaryExpression.NodeType == NodeType.Castclass) { if (binaryExpression.Operand1 is Literal) return this.VisitExpression(binaryExpression.Operand1); // For type-casts, we want to ignore the "type" operand since these were // inserted by the checker and needn't be examined here. The form of their // member bindings is not understood by the normalizer. binaryExpression.Operand1 = this.VisitExpression(binaryExpression.Operand1); return binaryExpression; } else return base.VisitBinaryExpression(binaryExpression); }
private Expression ParseParenthesizedExpression(TokenSet followers, bool keepParentheses){ SourceContext sctx = this.scanner.CurrentSourceContext; if (this.currentToken == Token.LeftBrace){ this.SkipTo(followers, Error.SyntaxError, "("); return null; } this.Skip(Token.LeftParenthesis); Expression result1 = this.ParseExpression(followers|Token.RightParenthesis|Token.Colon); if (this.currentToken == Token.Colon){ this.GetNextToken(); Expression result2 = this.ParseExpression(followers|Token.RightParenthesis); if (result2 == null) return null; result1 = new BinaryExpression(result1, new BinaryExpression(result2, new Literal(1, null, result2.SourceContext), NodeType.Sub), NodeType.Range); } int bracketPos = this.scanner.endPos; this.ParseBracket(sctx, Token.RightParenthesis, followers, Error.ExpectedRightParenthesis); if (keepParentheses){ sctx.EndPos = bracketPos; return new UnaryExpression(result1, NodeType.Parentheses, sctx); }else return result1; }
private Expression VisitIn(BinaryExpression expr) { if (expr.Operand1 == null || expr.Operand2 == null) return null; Expression inExpr = Templates.GetExpressionTemplate("SetMembershipTest"); Replacer.Replace(inExpr, "_setOperand", this.VisitExpression(expr.Operand2)); Replacer.Replace(inExpr, "_itemOperand", this.VisitExpression(expr.Operand1)); return inExpr; }
private Expression ParseBinaryExpression(Expression operand1, TokenSet followers){ TokenSet unaryFollowers = followers|Parser.InfixOperators; Expression expression; switch(this.currentToken){ case Token.Plus: case Token.As: case Token.BitwiseAnd: case Token.BitwiseOr: case Token.BitwiseXor: case Token.Divide: case Token.Equal: case Token.GreaterThan: case Token.GreaterThanOrEqual: case Token.Iff: case Token.In: case Token.Implies: case Token.Is: case Token.LeftShift: case Token.LessThan: case Token.LessThanOrEqual: case Token.LogicalAnd: case Token.LogicalOr: case Token.Maplet: case Token.Multiply: case Token.NotEqual: case Token.NullCoalescingOp: case Token.Range: case Token.Remainder: case Token.RightShift: case Token.Subtract: Token operator1 = this.currentToken; this.GetNextToken(); Expression operand2 = null; if (operator1 == Token.Is || operator1 == Token.As){ SourceContext ctx = this.scanner.CurrentSourceContext; TypeNode te = this.ParseTypeOrFunctionTypeExpression(unaryFollowers, false, true); operand2 = new MemberBinding(null, te); if (te is TypeExpression) operand2.SourceContext = te.SourceContext; else operand2.SourceContext = ctx; }else operand2 = this.ParseUnaryExpression(unaryFollowers); switch(this.currentToken){ case Token.Plus: case Token.As: case Token.BitwiseAnd: case Token.BitwiseOr: case Token.BitwiseXor: case Token.Divide: case Token.Equal: case Token.GreaterThan: case Token.GreaterThanOrEqual: case Token.Iff: case Token.Implies: case Token.In: case Token.Is: case Token.LeftShift: case Token.LessThan: case Token.LessThanOrEqual: case Token.LogicalAnd: case Token.LogicalOr: case Token.Maplet: case Token.Multiply: case Token.NotEqual: case Token.NullCoalescingOp: case Token.Range: case Token.Remainder: case Token.RightShift: case Token.Subtract: expression = this.ParseComplexExpression(Token.None, operand1, operator1, operand2, followers, unaryFollowers); break; default: expression = new BinaryExpression(operand1, operand2, Parser.ConvertToBinaryNodeType(operator1)); if (operand1 != null && operand2 != null){ expression.SourceContext = operand1.SourceContext; expression.SourceContext.EndPos = operand2.SourceContext.EndPos; }else expression = null; break; } break; default: expression = operand1; break; } return expression; }
void AddReadStream(Block block, TypeNode type, StatementList statements, Identifier reader, Expression target, Expression result){ // Read next element and figure out if it matches the stream element type, if so read it and add it to the list // If not, then return (throw an error if there are no items and the list is the non-empty type). // flexArray = new flexarray(); // while (reader.Read() && read.NodeType != XmlNodeType.EndElement) { // if (reader.NodeType == XmlNodeType.Element) { // readchild(flexarray); // } // } // target = flexArray; Local nameLocal = new Local(Identifier.For("name"),SystemTypes.String, block); Local nsLocal = new Local(Identifier.For("ns"),SystemTypes.String, block); Local nodeType = new Local(Identifier.For("nodeType"),Runtime.XmlNodeType, block); Local optional = new Local(Identifier.Empty, SystemTypes.Boolean, block); Local foundChild = new Local(Identifier.Empty, SystemTypes.Boolean, block); statements.Add(new AssignmentStatement(optional, Literal.False)); TypeNode eType = Checker.GetCollectionElementType(type); Local local = new Local(Identifier.Empty, eType, block); Method addMethod = null; Local localArray = null; if (type.Template == SystemTypes.GenericBoxed) { addMethod = null; // only needs one! } else if (Checker.IsGenericList(type)) { //TODO: this call is invalid if the eType is not public TypeNode flexArrayType = SystemTypes.GenericList.GetTemplateInstance(this.module, eType); localArray = new Local(Identifier.For("stream"+streamCount++), flexArrayType, block); statements.Add(new AssignmentStatement(localArray, new Construct(new MemberBinding(null, flexArrayType), new ExpressionList(), flexArrayType))); addMethod = flexArrayType.GetMethod(Identifier.For("Add"), eType); } else { TypeNode arrayType = SystemTypes.ArrayList; localArray = new Local(Identifier.Empty, arrayType, block); statements.Add(new AssignmentStatement(localArray, new Construct(new MemberBinding(null, arrayType), new ExpressionList(), arrayType))); addMethod = arrayType.GetMethod(Identifier.For("Add"), SystemTypes.Object); } Block whileBody = new Block(new StatementList()); MethodCall moveToContent = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToContent")), new ExpressionList()); BinaryExpression notAtEnd = new BinaryExpression(moveToContent, new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("EndElement")), NodeType.Ne); BinaryExpression notEOF = new BinaryExpression( new QualifiedIdentifier(reader, Identifier.For("EOF")), Literal.True, NodeType.Ne); While w = new While(new BinaryExpression(notAtEnd, notEOF, NodeType.And), whileBody); statements.Add(w); whileBody.Statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); whileBody.Statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI")))); whileBody.Statements.Add(new AssignmentStatement(nodeType, new QualifiedIdentifier(reader, Identifier.For("NodeType")))); StatementList trueStatements = whileBody.Statements; if (type.Template == SystemTypes.GenericBoxed){ type = Checker.GetCollectionElementType(type); } trueStatements.Add(new AssignmentStatement(foundChild, Literal.False)); if (eType is TupleType || eType is TypeUnion || IsStream(eType)) { AddCallDeserializer(eType, trueStatements, reader, local, optional, foundChild); } else { AddReadChild(whileBody, trueStatements, Checker.GetDefaultElementName(eType), eType, local, reader, foundChild, true, false); } If ifFound = new If(new BinaryExpression(foundChild, Literal.True, NodeType.Eq), new Block(new StatementList()), new Block(new StatementList())); ifFound.TrueBlock.Statements.Add(new AssignmentStatement(result, Literal.True)); // set our result to true then. ifFound.FalseBlock.Statements.Add(new Exit()); // break out of loop then. trueStatements.Add(ifFound); if (addMethod == null) { trueStatements.Add(new AssignmentStatement(target, CastTo(local, type))); // box the result. trueStatements.Add(new Exit()); // break out of loop we have it! } else { MemberBinding addCall = new MemberBinding(localArray, addMethod); trueStatements.Add(new ExpressionStatement(new MethodCall(addCall, new ExpressionList(new Expression[1] {local})))); } // clear out the local, it is a struct of some sort. if (local.Type.IsValueType && ! local.Type.IsPrimitive) { trueStatements.Add(new AssignmentStatement(local, new Construct(new MemberBinding(null,local.Type), new ExpressionList(), local.Type))); } // end while // assign resulting array to the target object (if we have anything to assign). If ifResult = new If(new BinaryExpression(result, Literal.True, NodeType.Eq), new Block(new StatementList()), null); statements.Add(ifResult); statements = ifResult.TrueBlock.Statements; if (addMethod != null) { if (type is ArrayType) { // target = (type)localArray.ToArray(etype); Method toArray = SystemTypes.ArrayList.GetMethod(Identifier.For("ToArray"), SystemTypes.Type); ExpressionList args = new ExpressionList(); args.Add(new UnaryExpression(new Literal(eType, SystemTypes.Type), NodeType.Typeof, SystemTypes.Type)); statements.Add(new AssignmentStatement(target, CastTo(new MethodCall(new MemberBinding(localArray, toArray), args, NodeType.Callvirt, SystemTypes.Array), type))); } else if (type.Template == SystemTypes.GenericNonEmptyIEnumerable) { // Explicit coercion of IEnumerable to NonEmptyIEnumerable requires constructing // the NonEmptyIEnumerable object passing in the IEnumerable as an argument. TypeNode ienumtype = Checker.GetIEnumerableTypeFromNonEmptyIEnumerableStruct(this.module, type); Debug.Assert(ienumtype!=null); //TODO: this call is invalid if the eType is not public TypeNode nonEmptyIEnum = SystemTypes.GenericNonEmptyIEnumerable.GetTemplateInstance(this.module, eType); InstanceInitializer ii = nonEmptyIEnum.GetConstructor(ienumtype); Construct c = new Construct(new MemberBinding(null, ii), new ExpressionList(localArray), nonEmptyIEnum); statements.Add(new AssignmentStatement(target, c)); } else { statements.Add(new AssignmentStatement(target, localArray)); } } }
private Expression ParseComplexExpression(Token operator0, Expression operand1, Token operator1, Expression operand2, TokenSet followers, TokenSet unaryFollowers){ restart: Token operator2 = this.currentToken; this.GetNextToken(); Expression expression = null; Expression operand3 = null; if (operator2 == Token.Is || operator2 == Token.As){ TypeNode type3 = this.ParseTypeExpression(Identifier.Empty, unaryFollowers); if (type3 != null) operand3 = new MemberBinding(null, type3, type3.SourceContext); }else operand3 = this.ParseUnaryExpression(unaryFollowers); if (Parser.LowerPriority(operator1, operator2)){ switch(this.currentToken){ case Token.Plus: case Token.As: case Token.BitwiseAnd: case Token.BitwiseOr: case Token.BitwiseXor: case Token.Divide: case Token.Equal: case Token.GreaterThan: case Token.GreaterThanOrEqual: case Token.Iff: case Token.Implies: case Token.In: case Token.Is: case Token.LeftShift: case Token.LessThan: case Token.LessThanOrEqual: case Token.LogicalAnd: case Token.LogicalOr: case Token.Maplet: case Token.Multiply: case Token.NotEqual: case Token.NullCoalescingOp: case Token.Range: case Token.Remainder: case Token.RightShift: case Token.Subtract: if (Parser.LowerPriority(operator2, this.currentToken)) //Can't reduce just operand2 op2 operand3 because there is an op3 with priority over op2 operand2 = this.ParseComplexExpression(operator1, operand2, operator2, operand3, followers, unaryFollowers); //reduce complex expression //Now either at the end of the entire expression, or at an operator that is at the same or lower priority than op1 //Either way, operand2 op2 operand3 op3 ... has been reduced to just operand2 and the code below will //either restart this procedure to parse the remaining expression or reduce operand1 op1 operand2 and return to the caller else goto default; break; default: //Reduce operand2 op2 operand3. There either is no further binary operator, or it does not take priority over op2. expression = new BinaryExpression(operand2, operand3, Parser.ConvertToBinaryNodeType(operator2)); if (operand2 != null && operand3 != null){ expression.SourceContext = operand2.SourceContext; expression.SourceContext.EndPos = operand3.SourceContext.EndPos; }else expression = null; operand2 = expression; //The code following this will reduce operand1 op1 operand2 and return to the caller break; } }else{ Expression opnd1 = new BinaryExpression(operand1, operand2, Parser.ConvertToBinaryNodeType(operator1)); if (operand1 != null && operand2 != null){ opnd1.SourceContext = operand1.SourceContext; opnd1.SourceContext.EndPos = operand2.SourceContext.EndPos; }else opnd1 = null; operand1 = opnd1; operand2 = operand3; operator1 = operator2; } //At this point either operand1 op1 operand2 has been reduced, or operand2 op2 operand3 .... has been reduced, so back to just two operands switch(this.currentToken){ case Token.Plus: case Token.As: case Token.BitwiseAnd: case Token.BitwiseOr: case Token.BitwiseXor: case Token.Divide: case Token.Equal: case Token.GreaterThan: case Token.GreaterThanOrEqual: case Token.In: case Token.Iff: case Token.Implies: case Token.Is: case Token.LeftShift: case Token.LessThan: case Token.LessThanOrEqual: case Token.LogicalAnd: case Token.LogicalOr: case Token.Maplet: case Token.Multiply: case Token.NotEqual: case Token.NullCoalescingOp: case Token.Range: case Token.Remainder: case Token.RightShift: case Token.Subtract: if (operator0 == Token.None || Parser.LowerPriority(operator0, this.currentToken)) //The caller is not prepared to deal with the current token, go back to the start of this routine and consume some more tokens goto restart; else goto default; //Let the caller deal with the current token default: //reduce operand1 op1 operand2 and return to caller expression = new BinaryExpression(operand1, operand2, Parser.ConvertToBinaryNodeType(operator1)); if (operand1 != null && operand2 != null){ expression.SourceContext = operand1.SourceContext; expression.SourceContext.EndPos = operand2.SourceContext.EndPos; }else expression = null; break; } return expression; }
//================= reader methods ========================================== void AddReadAttributes(TypeNode type, StatementList statements, Identifier reader, Expression target, SchemaValidator validator) { if (validator.Attributes != null) { Block whileBody = new Block(new StatementList()); Literal trueLit = Literal.True; MethodCall movenext = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToNextAttribute")), new ExpressionList()); BinaryExpression condition = new BinaryExpression(movenext, trueLit, NodeType.Eq); While w = new While(condition, whileBody); statements.Add(w); Block lastElseBlock = null; Local nameLocal = new Local(SystemTypes.String); whileBody.Statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); Local nsLocal = new Local(SystemTypes.String); whileBody.Statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI")))); foreach (SchemaAttDef ad in validator.Attributes) { // todo: any way to do tokenized compares? BinaryExpression nameEqual = new BinaryExpression(nameLocal, new Literal(ad.Name.Name, SystemTypes.String), NodeType.Eq); BinaryExpression nsEqual = new BinaryExpression(nsLocal, new Literal(ad.Name.Prefix != null ? ad.Name.Prefix.Name : "", SystemTypes.String), NodeType.Eq); Block elseBlock = new Block(new StatementList()); If ifExpr = new If(new BinaryExpression(nameEqual, nsEqual, NodeType.And), new Block(new StatementList()), elseBlock); if (lastElseBlock != null) { lastElseBlock.Statements.Add(ifExpr); } else { whileBody.Statements.Add(ifExpr); } lastElseBlock = elseBlock; // body of if test, parse the attribute value as the specified type. Debug.Assert(ad.Member is Field || ad.Member is Property); AddReadSimpleType(Checker.GetMemberType(ad.Member), ifExpr.TrueBlock.Statements, reader, GetMemberBinding(target, ad.Member), null, true); } //todo: report unknown attributes? } }
private Expression ParseCastExpression(TokenSet followers){ SourceContext sctx = this.scanner.CurrentSourceContext; ScannerState ss = this.scanner.state; Debug.Assert(this.currentToken == Token.LeftParenthesis); this.GetNextToken(); Token tok; TypeNode t; if (this.currentToken == Token.LogicalNot) { // non-null cast (!) this.GetNextToken(); t = TypeExpressionFor("Microsoft", "Contracts", "NonNullType"); tok = this.currentToken; }else{ t = this.ParseTypeExpression(null, followers|Token.RightParenthesis, true); tok = this.currentToken; } if (t != null && tok == Token.RightParenthesis){ this.GetNextToken(); //TODO: bracket matching bool wasCast = this.inUnsafeCode && (this.currentToken == Token.BitwiseAnd || this.currentToken == Token.Multiply) && t is PointerTypeExpression; if (wasCast || (this.currentToken == Token.Default || Parser.UnaryStart[this.currentToken]) && (!Parser.InfixOperators[this.currentToken] || this.TypeExpressionIsUnambiguous(t as TypeExpression))){ BinaryExpression result = new BinaryExpression(this.ParseUnaryExpression(followers), new MemberBinding(null, t, t.SourceContext), NodeType.ExplicitCoercion); result.SourceContext = sctx; if (result.Operand1 != null) result.SourceContext.EndPos = result.Operand1.SourceContext.EndPos; return result; } } //Tried to parse a parenthesized type expression followed by a unary expression, but failed. //Reset the scanner to the state at the start of this routine and parse as a parenthesized expression bool isLambda = this.currentToken == Token.Lambda; this.scanner.endPos = sctx.StartPos; this.scanner.state = ss; this.currentToken = Token.None; this.GetNextToken(); if (isLambda) return this.ParseLambdaExpression(followers); return this.ParsePrimaryExpression(followers); }
public override Expression VisitBinaryExpression(BinaryExpression binaryExpression) { Expression result = base.VisitBinaryExpression(binaryExpression); return result; }
public override Expression VisitBinaryExpression(BinaryExpression binaryExpression) { if (binaryExpression == null) return null; binaryExpression = (BinaryExpression)base.VisitBinaryExpression((BinaryExpression)binaryExpression.Clone()); return binaryExpression; }
private BinaryExpression VisitIn(BinaryExpression expr) { return (BinaryExpression)base.VisitBinaryExpression(expr); }
private BinaryExpression VisitIn(BinaryExpression expr) { if (expr == null) return null; BinaryExpression result = (BinaryExpression)base.VisitBinaryExpression(expr); return result; }
public override Expression VisitBinaryExpression(BinaryExpression binaryExpression) { Write("("); if ((binaryExpression.NodeType == NodeType.Castclass) || (binaryExpression.NodeType == NodeType.ExplicitCoercion)) { Write("("); this.VisitExpression(binaryExpression.Operand2); Write(") "); this.VisitExpression(binaryExpression.Operand1); } else { this.VisitExpression(binaryExpression.Operand1); Write(" {0} ", GetBinaryOperator(binaryExpression.NodeType)); this.VisitExpression(binaryExpression.Operand2); } Write(")"); return binaryExpression; }
public override Expression VisitBinaryExpression(BinaryExpression binaryExpression) { if (binaryExpression == null) return null; // comparison of reference-types and none of the operands is "null" if ( (binaryExpression.NodeType == NodeType.Eq || binaryExpression.NodeType == NodeType.Ne) && binaryExpression.Operand1 != null && binaryExpression.Operand1.Type != null && !binaryExpression.Operand1.Type.IsValueType) { Literal lit1 = (binaryExpression.Operand1 as Literal); Literal lit2 = (binaryExpression.Operand2 as Literal); if (! ( (lit1 != null && lit1.ToString().Equals(Literal.Null.ToString())) || (lit2 != null && lit2.ToString().Equals(Literal.Null.ToString())))) { noRefComparison = false; return binaryExpression; } } binaryExpression.Operand1 = this.VisitExpression(binaryExpression.Operand1); binaryExpression.Operand2 = this.VisitExpression(binaryExpression.Operand2); return binaryExpression; }