📄 unamespaces.pas
字号:
FFileParser.CountUnitReference(fpMain, UnitIndex); //count the reference
end
else
begin
UnitIndex := FThisFile.UsedUnitList[fpInterface].IndexOf(IdentName);
if UnitIndex <> -1 then //is a used unit (not interface)
begin
SourceFile := TPascalFile(FThisFile.UsedUnitList[fpInterface].
Objects[UnitIndex]);
//count the reference
FFileParser.CountUnitReference(fpInterface, UnitIndex);
end
else
begin
//declared in a unit that is used in the interface?
Result := CheckUsedUnits(FThisFile.UsedUnitList[fpMain], fpMain);
if not assigned(Result) then //not found so far?
//declared in a unit that is used elsewhere(/implementation)?
Result := CheckUsedUnits(FThisFile.UsedUnitList[fpInterface],
fpInterface);
end;
end;
end;
end;
{ * * * *** * * * *** TWithNameSpace *** * * * *** * * * }
{Creates the namespace object and assigns the record-like type to be searched.
~param RecIdent the record-like identifier to be searched
~param CurrentFile the current file with the with-statement
~param IsOrHasInherited if the with-statement is used in the same file as
RecIdent is declared or in the class RecIdent
(if protected members should be returned) }
constructor TWithNameSpace.Create(RecIdent: TRecordType;
CurrentFile: TPascalFile;
IsOrHasInherited: Boolean);
begin
inherited Create; //create the object
FRecIdent := RecIdent; //save the parameters
FCurrentFile := CurrentFile;
FIsOrHasInherited := IsOrHasInherited;
end;
{Searches the identifier in the record-like identifier.
~param IdentName the name of the identifier to search
~param SourceFile if it is a file and not an identifier, it is returned through
this parameter
~result the identifier, if found, or nil }
function TWithNameSpace.FindIdent(const IdentName: String;
var SourceFile: TPascalFile): TIdentifier;
begin
if assigned(FRecIdent) then //has to be set for with-namespaces
begin //(but may be not for function-namespaces))
//search in the record-like identifier (and its parents)
Result := FRecIdent.FindMember(IdentName, FCurrentFile, FIsOrHasInherited);
if not assigned(Result) then //if not found, search previous namespace
Result := inherited FindIdent(IdentName, SourceFile)
else
SourceFile := nil; //do not also return the file
end
else //no with-identifier (for functions outside classes (no methods))
begin
assert(Self is TLocalFuncNameSpace); //search previous namespace
Result := inherited FindIdent(IdentName, SourceFile);
end;
end;
{ * * * *** * * * *** TLocalFuncNameSpace *** * * * *** * * * }
{Creates the namespace object and assigns the function-identifier.
~param FuncIdent the identifier of this function }
constructor TLocalFuncNameSpace.Create(FuncIdent: TFunction);
var SelfIdent :TVariable; //identifier for "Self" and result
begin
//create the object
inherited Create(FuncIdent.MemberOf, FuncIdent.InFile, True);
FFuncIdent := FuncIdent; //save function-identifier
FLocalIdents := TIdentifierList.Create; //create list for local identifiers
FSpecialList := TIdentifierList.Create; //and for "Self" and result
if assigned(FuncIdent.MemberOf) then //is a method?
begin
SelfIdent := TVariable.Create; //create "Self" as a variable
try
SelfIdent.Scope := sLocal;
SelfIdent.Name := 'Self';
SelfIdent.VarType := TIdentType.Create; //type is the class of the method
TIdentType(SelfIdent.VarType).DefIdent := FuncIdent.MemberOf.Name;
TIdentType(SelfIdent.VarType).TheType := FuncIdent.MemberOf;
FSpecialList.AddIdent(SelfIdent); //and add identifier
except
SelfIdent.Free;
raise;
end;
end;
FResultIdent := True; //assumption is, this is true, but will be set
if (FFuncIdent.FuncKind = fkFunction) {and
assigned(FFuncIdent.ReturnType)} then //if it is a function
begin
assert(assigned(FFuncIdent.ReturnType));
SelfIdent := TVariable.Create; //create variable "Result"
try
SelfIdent.Scope := sLocal;
SelfIdent.Name := FFuncIdent.Name; //alias for the name of the function
SelfIdent.VarType := TType(FFuncIdent.ReturnType.Clone);
SelfIdent.Position := FFuncIdent.ForwardDefPos;
FSpecialList.AddIdent(SelfIdent); //and add identifier
except
SelfIdent.Free;
raise;
end;
end;
FSubLocalIdents := TIdentifierList.Create; //list for internal identifiers
FUsedIdents := TIdentifierList.Create; //list for used global identifiers
end;
{Destroys the namespace object. }
destructor TLocalFuncNameSpace.Destroy;
begin
FSubLocalIdents.Free; //free list for internal identifiers
FSpecialList.Free; //free list for "Self" and result
FLocalIdents.Free; //free list for local identifiers
if assigned(FUsedIdents) then
FUsedIdents.RemoveAll(False); //don't free the used identifiers
FUsedIdents.Free; //free of used global identifiers
//(could be nil (if top-level it should))
inherited Destroy; //free the object
end;
{Searches the identifier in the (local) identifiers of the function.
~param IdentName the name of the identifier to search
~param SourceFile if it is a file and not an identifier, it is returned
through this parameter
~result the identifier, if found, or nil }
function TLocalFuncNameSpace.FindIdent(const IdentName: String;
var SourceFile: TPascalFile): TIdentifier;
var Name :String; //the effective name
begin
Name := IdentName; //use the name
//if it is a function and the searched identifier "Result"
if (FFuncIdent.FuncKind = fkFunction) {and
assigned(FFuncIdent.ReturnType)} and
FResultIdent and (LowerCase(Name) = 'result') then
begin
assert(assigned(FFuncIdent.ReturnType));
Name := FFuncIdent.Name; //use instead the function-name
end;
Result := FSpecialList.GetIdentByName(Name); //"Self" or "Result"?
if not assigned(Result) then
begin
Result := FFuncIdent.Params.GetIdentByName(Name); //a parameter?
if not assigned(Result) then
Result := FLocalIdents.GetIdentByName(Name); //locally defined?
end;
if not assigned(Result) then
//search in "Self" and in previous namespace
Result := inherited FindIdent(Name, SourceFile)
else
SourceFile := nil; //do not also return the file
end;
{Adds an identifier that is defined inside the function (in an
except-on-clause).
~param Ident the identifier defined inside the function }
procedure TLocalFuncNameSpace.AddSubLocalIdent(Ident: TIdentifier);
begin
FSubLocalIdents.AddIdent(Ident); //add the identifier to the internal list
FUsedIdents.RemoveIdent(Ident, False); //remove from the list; it's not global
end;
{Adds the identifier to the list of used global identifiers. The identifier is
only added if it's not local and not already in the list.
~param Ident the in this function used global identifier }
procedure TLocalFuncNameSpace.AddUsedIdent(Ident: TIdentifier);
begin
if not FSpecialList.RecursiveIsIn(Ident) and //not "Self" or "Result"?
not FSubLocalIdents.RecursiveIsIn(Ident) and //not an exception-variable?
not FLocalIdents.RecursiveIsIn(Ident) and //not a local identifier?
not FFuncIdent.Params.RecursiveIsIn(Ident) and //not a parameter?
not FUsedIdents.IsIn(Ident) then //not already in the list?
FUsedIdents.AddIdent(Ident); //add it to the list
end;
{Adds all in this (nested) function used global identifiers to the list of used
global identifiers of the given function-namespace (the namespace of the
function, this function is defined in).
~param NameSpace the namespace to which all used global identifiers should be
added }
procedure TLocalFuncNameSpace.MoveGlobalIdentsTo(NameSpace:
TLocalFuncNameSpace);
var i :Integer; //counter through the identifiers
begin
for i := 0 to FUsedIdents.Count - 1 do //for each used global identifier
NameSpace.AddUsedIdent(FUsedIdents[i]); //get and add it
end;
{Moves the list of used identifiers to the function-identifier. }
procedure TLocalFuncNameSpace.MoveGlobalsToFunction;
begin
assert(not assigned(FFuncIdent.UsedIdents));
FFuncIdent.SetUsedIdentsList(FUsedIdents); //move the list to the identifier
FUsedIdents := nil; //don't free it anymore
end;
{ * * * *** * * * *** TOnExceptNameSpace *** * * * *** * * * }
{Creates the namespace object and creates the exception-variable.
~param Name the name of the exception-variable
~param ThisFile the file of the exception-variable (of the function)
~param ExcName the name of the type of the exception
~param ExcIdent identifier of the type of the exception (or nil) }
constructor TOnExceptNameSpace.Create(const Name: String;
ThisFile: TPascalFile;
const ExcName: String;
ExcIdent: TRecordType);
begin
inherited Create; //create the object
FLCName := LowerCase(Name); //save for faster comparison
FVariable := TVariable.Create; //create the variable
FVariable.Name := Name; //assign the name
FVariable.InFile := ThisFile;
FVariable.VarType := TIdentType.Create; //create the type of the exception
with TIdentType(FVariable.VarType) do
begin
if assigned(ExcIdent) then //set the name of the type
DefIdent := ExcIdent.Name
else
DefIdent := ExcName;
TheType := ExcIdent; //set the type of the exception
end;
end;
{Destroys the namespace object and moves the exception-variable to the
function-namespace. This has to be done because there may be references to it
(shouldn't be, but possible anyway). }
destructor TOnExceptNameSpace.Destroy;
var NameSpace :TNameSpace; //to search the function-namespace
begin
NameSpace := FPreNameSpace; //search the next function-namespace
while assigned(NameSpace) and not (NameSpace is TLocalFuncNameSpace) do
NameSpace := NameSpace.PreNameSpace;
assert(assigned(NameSpace));
//add the exception-variable to the namespace (it won't be freed here)
TLocalFuncNameSpace(NameSpace).AddSubLocalIdent(FVariable);
inherited Destroy; //free the object
end;
{Searches the identifier by comparing it to the exception-variable.
~param IdentName the name of the identifier to search
~param SourceFile if it is a file and not an identifier, it is returned
through this parameter
~result the identifier, if found, or nil }
function TOnExceptNameSpace.FindIdent(const IdentName: String;
var SourceFile: TPascalFile): TIdentifier;
begin
if LowerCase(IdentName) = FLCName then //it's this exception-variable?
begin
SourceFile := nil; //not a file
Result := FVariable; //return the variable
end
else //search in previous namespace
Result := inherited FindIdent(IdentName, SourceFile);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -