private bool ParseExpression(TokenReader reader, out Expression result) { result = null; Token start = reader.Peek(); Expression firstTerm = null; if (!this.ParseSimpleExpression(reader, out firstTerm)) { return false; } Token tok = reader.Peek(); if (tok.IsRelationalOperator()) { reader.Read(); Expression term = null; if (!this.ParseSimpleExpression(reader, out term)) { return false; } result = new RelationalExpression(start, firstTerm, ((KeywordToken)tok).Value, term); } else { result = firstTerm; } return true; }
private bool TryEmitRelationExpresion( RelationalExpression relExpr, CompilerContext context, Scope scope, MethodImpl method, out TypeDefinition valueType) { context.TryFindTypeByName("boolean", out valueType); TypeDefinition rightSideType = null; if (!this.TryEmitExpression(relExpr.Right, context, scope, method, out rightSideType)) { return false; } this.PushResult(method, rightSideType); TypeDefinition leftSideType = null; if (!this.TryEmitExpression(relExpr.Left, context, scope, method, out leftSideType)) { return false; } if (rightSideType.IsFloatingPoint) { if (leftSideType.IsFloatingPoint) { switch (rightSideType.Size) { case 4: method.Statements.Add(new AsmStatement { Instruction = "fld dword ptr [esp]" }); break; case 8: method.Statements.Add(new AsmStatement { Instruction = "fld qword ptr [esp]" }); break; default: method.Statements.Add(new AsmStatement { Instruction = "fld tword ptr [esp]" }); break; } method.Statements.Add(new AsmStatement { Instruction = string.Format("add esp,{0}", rightSideType.Size) }); method.Statements.Add(new AsmStatement { Instruction = "fcompp" }); method.Statements.Add(new AsmStatement { Instruction = "fnstsw ax" }); method.Statements.Add(new AsmStatement { Instruction = "sahf" }); switch (relExpr.Operator) { case Keyword.Equals: { method.Statements.Add(new AsmStatement { Instruction = "sete al" }); } break; case Keyword.LessThan: { method.Statements.Add(new AsmStatement { Instruction = "seta al" }); } break; case Keyword.LessThanOrEquals: { method.Statements.Add(new AsmStatement { Instruction = "setae al" }); } break; case Keyword.GreaterThan: { method.Statements.Add(new AsmStatement { Instruction = "setb al" }); } break; case Keyword.GreaterThanOrEquals: { method.Statements.Add(new AsmStatement { Instruction = "setbe al" }); } break; case Keyword.NotEqual: { method.Statements.Add(new AsmStatement { Instruction = "setne al" }); } break; } } else { string message = string.Format( System.Globalization.CultureInfo.InvariantCulture, Properties.Resources.CodeGenerator_NoAutomaticConversion, leftSideType.FullName, rightSideType.FullName); this.log.Write(new Message( relExpr.Start.Path, relExpr.Start.Line, relExpr.Start.Column, Severity.Error, message)); return false; } } else if(leftSideType.IsFloatingPoint) { string message = string.Format( System.Globalization.CultureInfo.InvariantCulture, Properties.Resources.CodeGenerator_NoAutomaticConversion, leftSideType.FullName, rightSideType.FullName); this.log.Write(new Message( relExpr.Start.Path, relExpr.Start.Line, relExpr.Start.Column, Severity.Error, message)); return false; } else { if(leftSideType.Size <= 4 && rightSideType.Size <= 4) { method.Statements.Add(new AsmStatement { Instruction = "pop ecx"}); method.Statements.Add(new AsmStatement { Instruction = "cmp eax,ecx"}); switch (relExpr.Operator) { case Keyword.Equals: { method.Statements.Add(new AsmStatement { Instruction = "sete al" }); } break; case Keyword.LessThan: { method.Statements.Add(new AsmStatement { Instruction = "setl al" }); } break; case Keyword.LessThanOrEquals: { method.Statements.Add(new AsmStatement { Instruction = "setle al" }); } break; case Keyword.GreaterThan: { method.Statements.Add(new AsmStatement { Instruction = "setg al" }); } break; case Keyword.GreaterThanOrEquals: { method.Statements.Add(new AsmStatement { Instruction = "setge al" }); } break; case Keyword.NotEqual: { method.Statements.Add(new AsmStatement { Instruction = "setne al" }); } break; } } } return true; }