123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657 |
- unit tcresolvegenerics;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils, testregistry, tcresolver, PasResolveEval, PParser;
- type
- { TTestResolveGenerics }
- TTestResolveGenerics = Class(TCustomTestResolver)
- Published
- // generic types
- procedure TestGen_MissingTemplateFail;
- procedure TestGen_VarTypeWithoutSpecializeFail;
- procedure TestGen_GenTypeWithWrongParamCountFail;
- procedure TestGen_GenericNotFoundFail;
- procedure TestGen_SameNameSameParamCountFail;
- // constraints
- procedure TestGen_ConstraintStringFail;
- procedure TestGen_ConstraintMultiClassFail;
- procedure TestGen_ConstraintRecordExpectedFail;
- procedure TestGen_ConstraintClassRecordFail;
- procedure TestGen_ConstraintRecordClassFail;
- procedure TestGen_ConstraintArrayFail;
- // ToDo: constraint constructor
- // ToDo: constraint T:Unit2.TBird
- // ToDo: constraint T:Unit2.TGen<word>
- procedure TestGen_TemplNameEqTypeNameFail;
- // generic record
- procedure TestGen_RecordLocalNameDuplicateFail;
- procedure TestGen_Record;
- procedure TestGen_RecordDelphi;
- procedure TestGen_RecordNestedSpecialized;
- procedure TestGen_Record_SpecializeSelfInsideFail;
- // ToDo: enums within generic
- procedure TestGen_RecordAnoArray;
- // ToDo: procedure TestGen_SpecializeArg_ArrayOf; type TBird = specialize<array of word>
- // ToDo: unitname.specialize TBird<word>.specialize
- // generic class
- procedure TestGen_Class;
- procedure TestGen_ClassDelphi;
- procedure TestGen_ClassForward;
- procedure TestGen_Class_Method;
- procedure TestGen_Class_SpecializeSelfInside;
- // ToDo: generic class forward (constraints must be repeated)
- // ToDo: generic class forward constraints mismatch fail
- // ToDo: generic class overload <T> <S,T>
- procedure TestGen_Class_GenAncestor;
- procedure TestGen_Class_AncestorSelfFail;
- // ToDo: ancestor cycle: TBird<T> = class(TBird<word>) fail
- // ToDo: class-of
- // ToDo: UnitA.impl uses UnitB.intf uses UnitA.intf, UnitB has specialize of UnitA
- // generic external class
- procedure TestGen_ExtClass_Array;
- // ToDo: generic interface
- // ToDo: generic array
- // ToDo: generic procedure type
- // ToDo: pointer of generic
- // ToDo: helpers for generics
- // generic functions
- // ToDo: generic class method overload <T> <S,T>
- procedure TestGen_GenericFunction; // ToDo
- // generic statements
- procedure TestGen_LocalVar;
- procedure TestGen_Statements;
- procedure TestGen_ForLoop;
- // ToDo: for-in
- // ToDo: if
- // ToDo: case
- // ToDo: while, repeat
- // ToDo: try finally/except
- // ToDo: call
- // ToDo: dot
- // ToDo: is as
- end;
- implementation
- { TTestResolveGenerics }
- procedure TTestResolveGenerics.TestGen_MissingTemplateFail;
- begin
- StartProgram(false);
- Add([
- 'type generic g< > = array of word;',
- 'begin',
- '']);
- CheckParserException('Expected "Identifier"',nParserExpectTokenError);
- end;
- procedure TTestResolveGenerics.TestGen_VarTypeWithoutSpecializeFail;
- begin
- StartProgram(false);
- Add([
- 'type generic TBird<T> = record end;',
- 'var b: TBird;',
- 'begin',
- '']);
- CheckResolverException('Generics without specialization cannot be used as a type for a variable',
- nGenericsWithoutSpecializationAsType);
- end;
- procedure TTestResolveGenerics.TestGen_GenTypeWithWrongParamCountFail;
- begin
- StartProgram(false);
- Add([
- 'type generic TBird<T> = record end;',
- 'var b: TBird<word, byte>;',
- 'begin',
- '']);
- CheckResolverException('identifier not found "TBird<,>"',
- nIdentifierNotFound);
- end;
- procedure TTestResolveGenerics.TestGen_GenericNotFoundFail;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TBird = specialize TAnimal<word>;',
- 'begin',
- '']);
- CheckResolverException('identifier not found "TAnimal<>"',
- nIdentifierNotFound);
- end;
- procedure TTestResolveGenerics.TestGen_SameNameSameParamCountFail;
- begin
- StartProgram(false);
- Add([
- '{$mode delphi}',
- 'type',
- ' TBird<S,T> = record w: T; end;',
- ' TBird<X,Y> = record f: X; end;',
- 'begin',
- '']);
- CheckResolverException('Duplicate identifier "TBird" at afile.pp(4,8)',
- nDuplicateIdentifier);
- end;
- procedure TTestResolveGenerics.TestGen_ConstraintStringFail;
- begin
- StartProgram(false);
- Add([
- 'generic function DoIt<T:string>(a: T): T;',
- 'begin',
- ' Result:=a;',
- 'end;',
- 'begin',
- '']);
- CheckResolverException('"string" is not a valid constraint',
- nXIsNotAValidConstraint);
- end;
- procedure TTestResolveGenerics.TestGen_ConstraintMultiClassFail;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TObject = class end;',
- ' TBird = class end;',
- ' TBear = class end;',
- 'generic function DoIt<T: TBird, TBear>(a: T): T;',
- 'begin',
- ' Result:=a;',
- 'end;',
- 'begin',
- '']);
- CheckResolverException('"TBird" constraint and "TBear" constraint cannot be specified together',
- nConstraintXAndConstraintYCannotBeTogether);
- end;
- procedure TTestResolveGenerics.TestGen_ConstraintRecordExpectedFail;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' generic TBird<T:record> = record v: T; end;',
- 'var r: specialize TBird<word>;',
- 'begin',
- '']);
- CheckResolverException('record type expected, but Word found',
- nXExpectedButYFound);
- end;
- procedure TTestResolveGenerics.TestGen_ConstraintClassRecordFail;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TRec = record end;',
- ' generic TBird<T:class> = record v: T; end;',
- 'var r: specialize TBird<TRec>;',
- 'begin',
- '']);
- CheckResolverException('class type expected, but TRec found',
- nXExpectedButYFound);
- end;
- procedure TTestResolveGenerics.TestGen_ConstraintRecordClassFail;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TObject = class end;',
- ' generic TBird<T:record> = record v: T; end;',
- 'var r: specialize TBird<TObject>;',
- 'begin',
- '']);
- CheckResolverException('record type expected, but TObject found',
- nXExpectedButYFound);
- end;
- procedure TTestResolveGenerics.TestGen_ConstraintArrayFail;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TArr = array of word;',
- ' generic TBird<T:TArr> = record v: T; end;',
- 'begin',
- '']);
- CheckResolverException('"TArr" is not a valid constraint',
- nXIsNotAValidConstraint);
- end;
- procedure TTestResolveGenerics.TestGen_TemplNameEqTypeNameFail;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' generic TBird<TBird> = record v: T; end;',
- 'var r: specialize TBird<word>;',
- 'begin',
- '']);
- CheckResolverException('Duplicate identifier "TBird" at afile.pp(4,16)',
- nDuplicateIdentifier);
- end;
- procedure TTestResolveGenerics.TestGen_RecordLocalNameDuplicateFail;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' generic TBird<T> = record T: word; end;',
- 'begin',
- '']);
- CheckResolverException('Duplicate identifier "T" at afile.pp(4,18)',
- nDuplicateIdentifier);
- end;
- procedure TTestResolveGenerics.TestGen_Record;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' {#Typ}T = word;',
- ' generic TRec<{#Templ}T> = record',
- ' {=Templ}v: T;',
- ' end;',
- 'var',
- ' r: specialize TRec<word>;',
- ' {=Typ}w: T;',
- 'begin',
- ' r.v:=w;',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_RecordDelphi;
- begin
- StartProgram(false);
- Add([
- '{$mode delphi}',
- 'type',
- ' {#Typ}T = word;',
- ' TRec<{#Templ}T> = record',
- ' {=Templ}v: T;',
- ' end;',
- 'var',
- ' r: TRec<word>;',
- ' {=Typ}w: T;',
- 'begin',
- ' r.v:=w;',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_RecordNestedSpecialized;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TObject = class end;',
- ' generic TBird<T> = class v: T; end;',
- ' generic TFish<T:class> = record v: T; end;',
- 'var f: specialize TFish<specialize TBird<word>>;',
- 'begin',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_Record_SpecializeSelfInsideFail;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' generic TBird<T> = record',
- ' v: specialize TBird<word>;',
- ' end;',
- 'begin',
- '']);
- CheckResolverException('type "TBird" is not yet completely defined',
- nTypeXIsNotYetCompletelyDefined);
- end;
- procedure TTestResolveGenerics.TestGen_RecordAnoArray;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' generic TBird<T> = record v: T; end;',
- 'var b: specialize TBird<array of word>;',
- 'begin',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_Class;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TObject = class end;',
- ' {#Typ}T = word;',
- ' generic TBird<{#Templ}T> = class',
- ' {=Templ}v: T;',
- ' end;',
- 'var',
- ' b: specialize TBird<word>;',
- ' {=Typ}w: T;',
- 'begin',
- ' b.v:=w;',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_ClassDelphi;
- begin
- StartProgram(false);
- Add([
- '{$mode delphi}',
- 'type',
- ' TObject = class end;',
- ' {#Typ}T = word;',
- ' TBird<{#Templ}T> = class',
- ' {=Templ}v: T;',
- ' end;',
- 'var',
- ' b: TBird<word>;',
- ' {=Typ}w: T;',
- 'begin',
- ' b.v:=w;',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_ClassForward;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TObject = class end;',
- ' {#Typ}T = word;',
- ' generic TBird<{#Templ_Forward}T> = class;',
- ' TRec = record',
- ' b: specialize TBird<T>;',
- ' end;',
- ' generic TBird<{#Templ}T> = class',
- ' {=Templ}v: T;',
- ' r: TRec;',
- ' end;',
- 'var',
- ' s: specialize TRec;',
- ' {=Typ}w: T;',
- 'begin',
- ' s.b.v:=w;',
- ' s.b.r:=s;',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_Class_Method;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TObject = class end;',
- ' {#Typ}T = word;',
- ' generic TBird<{#Templ}T> = class',
- ' function Fly(p:T): T; virtual; abstract;',
- ' function Run(p:T): T;',
- ' end;',
- 'function TBird.Run(p:T): T;',
- 'begin',
- 'end;',
- 'var',
- ' b: specialize TBird<word>;',
- ' {=Typ}w: T;',
- 'begin',
- ' w:=b.Fly(w);',
- ' w:=b.Run(w);',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_Class_SpecializeSelfInside;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TObject = class end;',
- ' generic TBird<T> = class',
- ' e: T;',
- ' v: TBird<boolean>;',
- ' end;',
- 'var',
- ' b: specialize TBird<word>;',
- ' w: word;',
- 'begin',
- ' b.e:=w;',
- ' if b.v.e then ;',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_Class_GenAncestor;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TObject = class end;',
- ' generic TBird<T> = class',
- ' i: T;',
- ' end;',
- ' generic TEagle<T> = class(TBird<T>)',
- ' j: T;',
- ' end;',
- 'var',
- ' e: specialize TEagle<word>;',
- 'begin',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_Class_AncestorSelfFail;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TObject = class end;',
- ' generic TBird<T> = class(TBird<word>)',
- ' e: T;',
- ' end;',
- 'var',
- ' b: specialize TBird<word>;',
- 'begin',
- '']);
- CheckResolverException('type "TBird" is not yet completely defined',nTypeXIsNotYetCompletelyDefined);
- end;
- procedure TTestResolveGenerics.TestGen_ExtClass_Array;
- begin
- StartProgram(false);
- Add([
- '{$mode delphi}',
- '{$ModeSwitch externalclass}',
- 'type',
- ' NativeInt = longint;',
- ' TJSGenArray<T> = Class external name ''Array''',
- ' private',
- ' function GetElements(Index: NativeInt): T; external name ''[]'';',
- ' procedure SetElements(Index: NativeInt; const AValue: T); external name ''[]'';',
- ' public',
- ' type TSelfType = TJSGenArray<T>;',
- ' public',
- ' FLength : NativeInt; external name ''length'';',
- ' constructor new; overload;',
- ' constructor new(aLength : NativeInt); overload;',
- ' class function _of() : TSelfType; varargs; external name ''of'';',
- ' function fill(aValue : T) : TSelfType; overload;',
- ' function fill(aValue : T; aStartIndex : NativeInt) : TSelfType; overload;',
- ' function fill(aValue : T; aStartIndex,aEndIndex : NativeInt) : TSelfType; overload;',
- ' property Length : NativeInt Read FLength Write FLength;',
- ' property Elements[Index: NativeInt]: T read GetElements write SetElements; default;',
- ' end;',
- ' TJSWordArray = TJSGenArray<word>;',
- 'var',
- ' wa: TJSWordArray;',
- ' w: word;',
- 'begin',
- ' wa:=TJSWordArray.new;',
- ' wa:=TJSWordArray.new(3);',
- ' wa:=TJSWordArray._of(4,5);',
- ' wa:=wa.fill(7);',
- ' wa:=wa.fill(7,8,9);',
- ' w:=wa.length;',
- ' wa.length:=10;',
- ' wa[11]:=w;',
- ' w:=wa[12];',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_GenericFunction;
- begin
- StartProgram(false);
- Add([
- 'generic function DoIt<T>(a: T): T;',
- 'var i: T;',
- 'begin',
- ' a:=i;',
- ' Result:=a;',
- 'end;',
- 'var w: word;',
- 'begin',
- //' w:=DoIt<word>(3);',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_LocalVar;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TObject = class end;',
- ' generic TBird<{#Templ}T> = class',
- ' function Fly(p:T): T;',
- ' end;',
- 'function TBird.Fly(p:T): T;',
- 'var l: T;',
- 'begin',
- ' l:=p;',
- ' p:=l;',
- ' Result:=p;',
- ' Result:=l;',
- ' l:=Result;',
- 'end;',
- 'var',
- ' b: specialize TBird<word>;',
- ' w: word;',
- 'begin',
- ' w:=b.Fly(w);',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_Statements;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TObject = class end;',
- ' generic TBird<{#Templ}T> = class',
- ' function Fly(p:T): T;',
- ' end;',
- 'function TBird.Fly(p:T): T;',
- 'var',
- ' v1,v2,v3:T;',
- 'begin',
- ' v1:=1;',
- ' v2:=v1+v1*v1+v1 div p;',
- ' v3:=-v1;',
- ' repeat',
- ' v1:=v1+1;',
- ' until v1>=5;',
- ' while v1>=0 do',
- ' v1:=v1-v2;',
- ' for v1:=v2 to v3 do v2:=v1;',
- ' if v1<v2 then v3:=v1 else v3:=v2;',
- ' if v1<v2 then else ;',
- ' case v1 of',
- ' 1: v3:=3;',
- ' end;',
- 'end;',
- 'var',
- ' b: specialize TBird<word>;',
- 'begin',
- ' b.Fly(2);',
- '']);
- ParseProgram;
- end;
- procedure TTestResolveGenerics.TestGen_ForLoop;
- begin
- StartProgram(false);
- Add([
- '{$mode objfpc}',
- 'type',
- ' TObject = class end;',
- ' generic TBird<{#Templ}T> = class',
- ' function Fly(p:T): T;',
- ' end;',
- 'function TBird.Fly(p:T): T;',
- 'var i: T;',
- 'begin',
- ' for i:=0 to 3 do Result:=i+p;',
- 'end;',
- 'var',
- ' b: specialize TBird<word>;',
- 'begin',
- ' b.Fly(2);',
- '']);
- ParseProgram;
- end;
- initialization
- RegisterTests([TTestResolveGenerics]);
- end.
|