Browse Source

compiler: allow comparative operators to have result other than Boolean. Reasons:
1. It allows to use comparative operators in some unusual cases (issue #25004).
2. Regular type checking does not allow to use other than Boolean types in IF expressions anyway.
3. Delphi compatibility (although Delphi documentation states otherwise).

git-svn-id: trunk@25494 -

paul 12 years ago
parent
commit
99dadf2998
3 changed files with 152 additions and 4 deletions
  1. 1 0
      .gitattributes
  2. 0 4
      compiler/pdecsub.pas
  3. 151 0
      tests/webtbs/tw25004.pp

+ 1 - 0
.gitattributes

@@ -13573,6 +13573,7 @@ tests/webtbs/tw24871.pp svneol=native#text/pascal
 tests/webtbs/tw2492.pp svneol=native#text/plain
 tests/webtbs/tw2494.pp svneol=native#text/plain
 tests/webtbs/tw24953.pp svneol=native#text/pascal
+tests/webtbs/tw25004.pp svneol=native#text/pascal
 tests/webtbs/tw2503.pp svneol=native#text/plain
 tests/webtbs/tw2504.pp svneol=native#text/plain
 tests/webtbs/tw2514.pp svneol=native#text/plain

+ 0 - 4
compiler/pdecsub.pas

@@ -1286,10 +1286,6 @@ implementation
                            else
                              MessagePos(pd.fileinfo,type_e_type_id_expected);
                        end;
-                     if (optoken in [_EQ,_NE,_GT,_LT,_GTE,_LTE,_OP_IN]) and
-                        ((pd.returndef.typ<>orddef) or
-                         (torddef(pd.returndef).ordtype<>pasbool8)) then
-                        Message(parser_e_comparative_operator_return_boolean);
                      if (optoken in [_ASSIGNMENT,_OP_EXPLICIT]) and
                         equal_defs(pd.returndef,tparavarsym(pd.parast.SymList[0]).vardef) and
                         (pd.returndef.typ<>undefineddef) and (tparavarsym(pd.parast.SymList[0]).vardef.typ<>undefineddef) then

+ 151 - 0
tests/webtbs/tw25004.pp

@@ -0,0 +1,151 @@
+program tw25004;
+
+{$MODE DELPHI}
+
+uses
+  SysUtils;
+
+type
+  TExpression = class(TObject)
+  end;
+
+  TLiteralInteger = class(TExpression)
+  public
+    Value: integer;
+
+    constructor Create(Value: integer); virtual;
+    function ToString(): string; override;
+  end;
+
+  TVariableReference = class(TExpression)
+  public
+    Identifier: string;
+
+    constructor Create(const Identifier: string); virtual;
+    function ToString(): string; override;
+  end;
+
+  TBinaryOperator = (boAdd, boGreaterThan);
+
+  TBinaryOperatorExpression = class(TExpression)
+  protected
+    function OperatorToString(Operator_: TBinaryOperator): string;
+  public
+    Operator_: TBinaryOperator;
+    Left: TExpression;
+    Right: TExpression;
+
+    constructor Create(Operator_: TBinaryOperator; Left: TExpression; Right: TExpression); virtual;
+    destructor Destroy(); override;
+    function ToString(): string; override;
+  end;
+
+  TExpressionBuilder = record
+  public
+    Expression: TExpression;
+
+    class operator  Implicit(Operand: TExpression): TExpressionBuilder;
+    class operator  Implicit(Value: integer): TExpressionBuilder;
+    class operator  Add(const Left: TExpressionBuilder; const Right: TExpressionBuilder): TExpressionBuilder;
+    class operator  GreaterThan(const Left: TExpressionBuilder; const Right: TExpressionBuilder): TExpressionBuilder;
+  end;
+
+  { TLiteralInteger }
+
+  constructor TLiteralInteger.Create(Value: integer);
+  begin
+    inherited Create();
+
+    Self.Value := Value;
+  end;
+
+  function TLiteralInteger.ToString(): string;
+  begin
+    Result := IntToStr(Value);
+  end;
+
+  { TVariableReference }
+
+  constructor TVariableReference.Create(const Identifier: string);
+  begin
+    inherited Create();
+
+    Self.Identifier := Identifier;
+  end;
+
+  function TVariableReference.ToString(): string;
+  begin
+    Result := Identifier;
+  end;
+
+  { TBinaryOperatorExpression }
+
+  constructor TBinaryOperatorExpression.Create(Operator_: TBinaryOperator; Left, Right: TExpression);
+  begin
+    inherited Create();
+
+    Self.Operator_ := Operator_;
+    Self.Left := Left;
+    Self.Right := Right;
+  end;
+
+  destructor TBinaryOperatorExpression.Destroy();
+  begin
+    Left.Free();
+    Right.Free();
+
+    inherited Destroy();
+  end;
+
+  function TBinaryOperatorExpression.OperatorToString(Operator_: TBinaryOperator): string;
+  begin
+    case Operator_ of
+      boAdd:
+        Result := '+';
+      boGreaterThan:
+        Result := '>';
+      else
+        raise Exception.Create('Unknown operator');
+    end;
+  end;
+
+  function TBinaryOperatorExpression.ToString(): string;
+  begin
+    Result := Left.ToString() + ' ' + OperatorToString(Operator_) + ' ' + Right.ToString();
+  end;
+
+  { TExpressionBuilder }
+
+  class operator TExpressionBuilder.Add(const Left: TExpressionBuilder; const Right: TExpressionBuilder): TExpressionBuilder;
+  begin
+    Result := TBinaryOperatorExpression.Create(boAdd, Left.Expression, Right.Expression);
+  end;
+
+  class operator TExpressionBuilder.Implicit(Operand: TExpression): TExpressionBuilder;
+  begin
+    Result.Expression := Operand;
+  end;
+
+  class operator TExpressionBuilder.GreaterThan(const Left: TExpressionBuilder; const Right: TExpressionBuilder): TExpressionBuilder;
+  begin
+    Result := TBinaryOperatorExpression.Create(boGreaterThan, Left.Expression,
+      Right.Expression);
+  end;
+
+  class operator TExpressionBuilder.Implicit(Value: integer): TExpressionBuilder;
+  begin
+    Result := TLiteralInteger.Create(Value);
+  end;
+
+var
+  Variable1: TExpressionBuilder;
+  Variable2: TExpressionBuilder;
+  Formula: TExpressionBuilder;
+begin
+  Variable1 := TVariableReference.Create('a');
+  Variable2 := TVariableReference.Create('b');
+  Formula := Variable1 + 1 > 5 + Variable2;
+  if Formula.Expression.ToString() <> 'a + 1 > 5 + b' then
+    halt(1);
+  Formula.Expression.Free();
+end.