RomanYankovsky / DelphiAST

Abstract syntax tree builder for Delphi
Mozilla Public License 2.0
271 stars 116 forks source link

Double @@ (for procedural variables) is not recorded: #256

Open JBontes opened 6 years ago

JBontes commented 6 years ago

This snippet:

unit Test;

interface

implementation

procedure TScriptlet.InitControlData;
begin
  TControlData2(CControlData).FirstEventOfs := UIntPtr(@@FOnonscriptletevent) - UIntPtr(Self);
  TControlData2(CControlData).FirstEventOfs := UIntPtr(@FOnonscriptletevent) - UIntPtr(Self);
end;

end.

Is recorded as:

<?xml version="1.0"?>
<UNIT line="1" col="1" name="PlusIsTest">
  <INTERFACE begin_line="3" begin_col="1" end_line="5" end_col="1"/>
  <IMPLEMENTATION begin_line="5" begin_col="1" end_line="13" end_col="1">
    <METHOD begin_line="7" begin_col="1" end_line="13" end_col="1" kind="procedure">
      <NAME line="7" col="11" name="TScriptlet.InitControlData">
        <NAME line="7" col="11" name="TScriptlet"/>
        <NAME line="7" col="22" name="InitControlData"/>
      </NAME>
      <STATEMENTS begin_line="8" begin_col="1" end_line="11" end_col="4" kind="begin">
        <ASSIGN line="9" col="3">
          <LHS line="9" col="3">
            <DOT line="9" col="30">
              <CALL line="9" col="3">
                <IDENTIFIER line="9" col="3" name="TControlData2"/>
                <EXPRESSIONS line="9" col="17">
                  <EXPRESSION line="9" col="17">
                    <IDENTIFIER line="9" col="17" name="CControlData"/>
                  </EXPRESSION>
                </EXPRESSIONS>
              </CALL>
              <IDENTIFIER line="9" col="31" name="FirstEventOfs"/>
            </DOT>
          </LHS>
          <RHS line="9" col="48">
            <EXPRESSION line="9" col="48">
              <SUB line="9" col="79">
                <CALL line="9" col="48">
                  <IDENTIFIER line="9" col="48" name="UIntPtr"/>
                  <EXPRESSIONS line="9" col="56">
                    <EXPRESSION line="9" col="56"> //Incorrect, no ADDR nodes!
                      <IDENTIFIER line="9" col="58" name="FOnonscriptletevent"/>
                    </EXPRESSION>
                  </EXPRESSIONS>
                </CALL>
                <CALL line="9" col="48">
                  <IDENTIFIER line="9" col="81" name="UIntPtr"/>
                  <EXPRESSIONS line="9" col="89">
                    <EXPRESSION line="9" col="89">
                      <IDENTIFIER line="9" col="89" name="Self"/>
                    </EXPRESSION>
                  </EXPRESSIONS>
                </CALL>
              </SUB>
            </EXPRESSION>
          </RHS>
        </ASSIGN>
        <ASSIGN line="10" col="3">
          <LHS line="10" col="3">
            <DOT line="10" col="30">
              <CALL line="10" col="3">
                <IDENTIFIER line="10" col="3" name="TControlData2"/>
                <EXPRESSIONS line="10" col="17">
                  <EXPRESSION line="10" col="17">
                    <IDENTIFIER line="10" col="17" name="CControlData"/>
                  </EXPRESSION>
                </EXPRESSIONS>
              </CALL>
              <IDENTIFIER line="10" col="31" name="FirstEventOfs"/>
            </DOT>
          </LHS>
          <RHS line="10" col="48">
            <EXPRESSION line="10" col="48">
              <SUB line="10" col="78">
                <CALL line="10" col="48">
                  <IDENTIFIER line="10" col="48" name="UIntPtr"/>
                  <EXPRESSIONS line="10" col="56">
                    <EXPRESSION line="10" col="56">
                      <ADDR line="10" col="56">   ///Correct!
                        <IDENTIFIER line="10" col="57" name="FOnonscriptletevent"/>
                      </ADDR>
                    </EXPRESSION>
                  </EXPRESSIONS>
                </CALL>
                <CALL line="10" col="48">
                  <IDENTIFIER line="10" col="80" name="UIntPtr"/>
                  <EXPRESSIONS line="10" col="88">
                    <EXPRESSION line="10" col="88">
                      <IDENTIFIER line="10" col="88" name="Self"/>
                    </EXPRESSION>
                  </EXPRESSIONS>
                </CALL>
              </SUB>
            </EXPRESSION>
          </RHS>
        </ASSIGN>
      </STATEMENTS>
    </METHOD>
  </IMPLEMENTATION>
</UNIT>

The cast to UIntPtr in the first line with @@ is recorded as:

                <CALL line="9" col="48">
                  <IDENTIFIER line="9" col="48" name="UIntPtr"/>
                  <EXPRESSIONS line="9" col="56">
                    <EXPRESSION line="9" col="56"> //Incorrect, no ADDR nodes!
                      <IDENTIFIER line="9" col="58" name="FOnonscriptletevent"/>
                    </EXPRESSION>
                  </EXPRESSIONS>
                </CALL>

The <DOUBLEADDR> node is missing. There should be <DOUBLEADDR> node. (@@ is a distinct operator from @.)

The fix is to add @@ as an additional operator:

OperatorsInfo: array [0..28] of TOperatorInfo =
    ((Typ: ntAddr;         Priority: 1; Kind: okUnary;  AssocType: atRight),
     (Typ: ntDoubleAddr;   Priority: 1; Kind: okUnary;  AssocType: atRight),
     (Typ: ntDeref;        Priority: 1; Kind: okUnary;  AssocType: atLeft),
     (Typ: ntGeneric;      Priority: 1; Kind: okBinary; AssocType: atRight),
     (Typ: ntIndexed;      Priority: 1; Kind: okUnary;  AssocType: atLeft),
    ....

procedure TPasSyntaxTreeBuilder.DoubleAddressOp;
begin
  FStack.Push(ntDoubleAddr);
  try
    inherited;
  finally
    FStack.Pop;
  end;
end;

procedure TmwSimplePasPar.VariableReference;
begin
  case TokenID of
    ptRoundOpen:
    begin
      RoundOpen;
      Expression;
      RoundClose;
      VariableTail;
    end;
    ptSquareOpen:
    begin
      SetConstructor;
    end;
    ptAddressOp:
      begin
        AddressOp;
        VariableReference;
      end;
    ptDoubleAddressOp:
      begin
        DoubleAddressOp;
        VariableReference;
      end;
    ptInherited:
      begin
        InheritedVariableReference;
      end;
  else
    variable;
  end;
end;

procedure TmwSimplePasPar.DoubleAddressOp;
begin
  Expected(ptDoubleAddressOp);
end;