unit tcresolvegenerics; {$mode objfpc}{$H+} interface uses Classes, SysUtils, testregistry, tcresolver, PasResolveEval, PParser; type { TTestResolveGenerics } TTestResolveGenerics = Class(TCustomTestResolver) Published // generic functions procedure TestGen_GenericFunction; // ToDo // generic types procedure TestGen_MissingTemplateFail; procedure TestGen_VarTypeWithoutSpecializeFail; procedure TestGen_ConstraintStringFail; procedure TestGen_ConstraintMultiClassFail; procedure TestGen_ConstraintRecordExpectedFail; // ToDo: constraints mismatch: TAnt; TBird = record v: TAnt end Fail // ToDo: constraint keyword record // ToDo: constraint keyword class, constructor, class+constructor // ToDo: constraint T:Unit2.TBird // ToDo: constraint T:Unit2.TGen procedure TestGen_GenericNotFoundFail; procedure TestGen_RecordLocalNameDuplicateFail; procedure TestGen_Record; // ToDo // ToDo: type TBird = record end; var b: TBird.T; fail // ToDo: enums within generic // ToDo: generic class // ToDo: generic class forward // ToDo: ancestor cycle: TBird = class(TBird) fail // ToDo: class-of // ToDo: UnitA.impl uses UnitB.intf uses UnitA.intf, UnitB has specialize of UnitA // ToDo: generic interface // ToDo: generic array // ToDo: generic procedure type // ToDo: pointer of generic // ToDo: generic helpers end; implementation { TTestResolveGenerics } procedure TTestResolveGenerics.TestGen_GenericFunction; begin StartProgram(false); Add([ 'generic function DoIt(a: T): T;', 'var i: T;', 'begin', ' a:=i;', ' Result:=a;', 'end;', 'var w: word;', 'begin', //' w:=DoIt(3);', '']); ParseProgram; end; 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 = record end;', 'var b: TBird;', 'begin', '']); CheckResolverException('Generics without specialization cannot be used as a type for a variable', nGenericsWithoutSpecializationAsType); end; procedure TTestResolveGenerics.TestGen_ConstraintStringFail; begin StartProgram(false); Add([ 'generic function DoIt(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(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 = record v: T; end;', 'var r: specialize TBird;', 'begin', '']); CheckResolverException('record type expected, but Word found', nXExpectedButYFound); end; procedure TTestResolveGenerics.TestGen_GenericNotFoundFail; begin StartProgram(false); Add([ '{$mode objfpc}', 'type', ' TBird = specialize TAnimal;', 'begin', '']); CheckResolverException('identifier not found "TAnimal"', nIdentifierNotFound); end; procedure TTestResolveGenerics.TestGen_RecordLocalNameDuplicateFail; begin StartProgram(false); Add([ '{$mode objfpc}', 'type', ' generic TBird = 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;', ' {=Typ}w: T;', 'begin', ' r.v:=w;', '']); ParseProgram; end; initialization RegisterTests([TTestResolveGenerics]); end.