UNIT Generation.ms.dict USES axiom_push.ms.dict ; USES core.ms.dict ; USES WordsRTTI.ms.dict ; USES ElementsRTTI.ms.dict ; USES CompileTimeVar.ms.dict ; USES SaveVarAndDo.ms.dict ; CONST GEN_PROPERTY_PREFIX 'gp' %REMARK 'Префикс имени свойства генератора' MACRO %GEN_PROPERTY Literal IN aName %SUMMARY 'Свойство генератора' ; this.method.addr Ctx:SetWordProducerForCompiledClass axiom:PushSymbol CONST GEN_PROPERTY_PREFIX (+) ( aName |N ) Ctx:Parser:PushSymbol ; // %GEN_PROPERTY USES RefDeepest.ms.dict FieldByNameDeepest.ms.dict ; MACRO %GP Literal IN aName %SUMMARY 'Метод получения свойства генератора' ; axiom:PushSymbol FieldByNameDeepest GEN_PROPERTY_PREFIX (+) ( aName |N ) Ctx:Parser:PushSymbol ; // %GP CONST cPathSep '\' FILE CompileTime-VAR g_OutFile nil %REMARK 'Текущий файл' INTEGER CompileTime-VAR g_Indent 0 %REMARK 'Текущий отступ' CONST cIndentChar ' ' STRING FUNCTION IndentStr g_Indent cIndentChar char:Dupe >>> Result ; // IndentStr OBJECT STRING INTEGER ARRAY BOOLEAN TYPE OUTABLE STRING FUNCTION ValueToString OUTABLE IN aValue if ( aValue IsArray ) then begin [ aValue .for> call.me ] strings:Cat >>> Result end else if ( aValue .IsWord ) then begin aValue |N >>> Result end else begin aValue ToPrintable >>> Result end ; // ValueToString STRING FUNCTION ValueToStringOrName OUTABLE IN aValue if ( aValue .IsWord ) then begin aValue .Name >>> Result if ( Result = '' ) then begin aValue pop:Word:Name >>> Result end end else begin aValue ValueToString >>> Result end ; // ValueToStringOrName CONST \n #13#10 BOOLEAN FUNCTION .Out? OUTABLE IN aValue VAR l_WasOut VAR l_NeedIndent PROCEDURE .OutValue OUTABLE IN aValue if ( aValue IsArray ) then begin aValue .for> call.me end // aValue IsArray else begin STRING VAR l_Value aValue ToPrintable >>> l_Value if ( l_WasOut ! ) then begin true >>> l_WasOut IndentStr g_OutFile File:WriteStr false >>> l_NeedIndent end // l_WasOut ! if ( l_NeedIndent ) then begin false >>> l_NeedIndent IndentStr g_OutFile File:WriteStr end // l_NeedIndent if ( l_Value \n == ) then begin l_Value g_OutFile File:WriteStr true >>> l_NeedIndent end // ( l_Value \n == ) else begin l_Value g_OutFile File:WriteStr end // ( l_Value \n == ) end // aValue IsArray ; // .OutValue false >>> l_WasOut false >>> l_NeedIndent aValue .OutValue if l_WasOut then begin \n g_OutFile File:WriteStr end // l_WasOut l_WasOut >>> Result ; // .Out? : .Out .Out? DROP ; // .Out PROCEDURE Indented: ^ IN aLambda TF g_Indent ( INC g_Indent aLambda DO ) ; // Indented: PROCEDURE Bracketed ^ IN aLambda '{' .Out Indented: ( aLambda DO ) '}' .Out ; // Bracketed USES axiom:SysUtils ; USES arrays.ms.dict ; TtfwWord FUNCTION .FindMemberRecur STRING IN aName TtfwWord IN aGen TtfwKeyWord VAR l_Member aName aGen pop:Word:FindMember >>> l_Member if ( l_Member IsNil ) then ( nil >>> Result ) else ( l_Member pop:KeyWord:Word >>> Result ) if ( Result IsNil ) then ( aGen .Inherited.Words .for> ( IN anItem VAR l_Found aName anItem call.me >>> l_Found ( Result IsNil ) OR ( l_Found IsNil ) OR ( Result = l_Found ) ?ASSURE [ 'Multiply inheritance. Word: ' aName ' generator ' aGen pop:Word:Name ' parent generator ' anItem pop:Word:Name ] l_Found >>> Result ) ) ; // .FindMemberRecur ARRAY CompileTime-VAR g_GeneratedFiles [] %REMARK 'Ранее сгенерированные файлы' TtfwWord VAR g_CurrentGenerator %REMARK 'Текущий генератор' WordAlias Cached: CacheMethod WordAlias GenCached: CacheMethod : .? ^ IN aWord VAR l_Word aWord |N g_CurrentGenerator .FindMemberRecur >>> l_Word if ( l_Word IsNil ) then ( aWord DO ) else ( l_Word DO ) ; // .? STRING FUNCTION Ext '.dump' >>> Result ; // Ext PROCEDURE .GenerateWordToFile ModelElement IN Self ^ IN aLambda TF g_Indent ( 0 >>> g_Indent STRING VAR l_FileName [ Self pop:Word:Name .? Ext ] strings:Cat >>> l_FileName STRING VAR l_TempPath 'C:\Temp\GenScripts\' >>> l_TempPath l_TempPath sysutils:ForceDirectories ?ASSURE [ 'Не удалось создать директорию ' l_TempPath ] STRING VAR l_RealPath 'W:\common\GenScripts\' >>> l_RealPath l_RealPath sysutils:ForceDirectories ?ASSURE [ 'Не удалось создать директорию ' l_RealPath ] STRING VAR l_TempFileName [ l_TempPath l_FileName ] cPathSep strings:CatSep >>> l_TempFileName STRING VAR l_RealFileName [ l_RealPath l_FileName ] cPathSep strings:CatSep >>> l_RealFileName if ( g_GeneratedFiles l_TempFileName array:HasText ! ) then begin l_TempFileName array:AddTo g_GeneratedFiles TF g_OutFile ( l_TempFileName File:OpenWrite >>> g_OutFile Self aLambda DO ) if ( ( l_RealFileName sysutils:FileExists ! ) OR ( '' l_RealFileName l_TempFileName CompareFiles ! ) ) then begin $20 l_RealFileName l_TempFileName CopyFile end end // g_GeneratedFiles l_TempFileName array:HasText ! ) ; // .GenerateWordToFile PROCEDURE .DeleteWordFile ModelElement IN Self STRING VAR l_FileName [ Self pop:Word:Name .? Ext ] strings:Cat >>> l_FileName STRING VAR l_RealPath 'W:\common\GenScripts\' >>> l_RealPath STRING VAR l_RealFileName [ l_RealPath l_FileName ] cPathSep strings:CatSep >>> l_RealFileName if ( l_RealFileName sysutils:FileExists ) then begin l_RealFileName DeleteFile DROP end ; // .DeleteWordFile BOOLEAN elem_func IsScriptKeyword Self .IsStereotype st_ScriptKeyword >>> Result ; // IsScriptKeyword BOOLEAN elem_func IsSimpleClass Cached: ( RULES ( Self .IsStereotype st_SimpleClass ) true ( Self .IsStereotype st_ObjStub ) true ( Self .IsStereotype st_Service ) true ( Self .IsStereotype st_ServiceImplementation ) true ( Self .IsScriptKeyword ) true ( Self .IsStereotype st_TestCase ) true ( Self .IsStereotype st_GuiControl ) true ( Self .IsStereotype st_VCMForm ) true ( Self .IsStereotype st_VCMFinalForm ) true ( Self .IsStereotype st_VCMContainer ) true ( Self .IsStereotype st_VCMFinalContainer ) true DEFAULT false ; // RULES ) >>> Result ; // IsSimpleClass BOOLEAN elem_func IsUtilityPack Cached: ( RULES ( Self .IsStereotype st_UtilityPack ) true ( Self .IsStereotype st_ScriptKeywordsPack ) true DEFAULT false ; // RULES ) >>> Result ; // IsUtilityPack BOOLEAN elem_func IsInterfaces Cached: ( RULES ( Self .IsStereotype st_Interfaces ) true ( Self .IsStereotype st_InternalInterfaces ) true DEFAULT false ; // RULES ) >>> Result ; // IsInterfaces BOOLEAN elem_func IsMixIn Self .IsStereotype st_Impurity >>> Result ; // IsMixIn BOOLEAN elem_func IsPureMixIn Self .IsStereotype st_PureMixIn >>> Result ; // IsPureMixIn BOOLEAN elem_func IsTypedef Self .IsStereotype st_Typedef >>> Result ; // IsTypedef BOOLEAN elem_func IsEnum Self .IsStereotype st_Enum >>> Result ; // IsEnum BOOLEAN elem_func IsFunction Self .IsStereotype st_Function >>> Result ; // IsFunction BOOLEAN elem_func IsRecord Self .IsStereotype st_Struct >>> Result ; // IsRecord BOOLEAN elem_func IsDefine Self .IsStereotype st_Define >>> Result ; // IsDefine BOOLEAN elem_func IsUndef Self .IsStereotype st_Undef >>> Result ; // IsUndef BOOLEAN elem_func IsUnion Self .IsStereotype st_Union >>> Result ; // IsUnion BOOLEAN elem_func IsStaticObject Self .IsStereotype st_StaticObject >>> Result ; // IsStaticObject BOOLEAN elem_func IsArray Self .IsStereotype st_Vector >>> Result ; // IsArray BOOLEAN elem_func IsElementProxy Self .IsStereotype st_ElementProxy >>> Result ; // IsElementProxy BOOLEAN elem_func IsSetOf Self .IsStereotype st_SetOf >>> Result ; // IsSetOf BOOLEAN elem_func IsException Self .IsStereotype st_Exception >>> Result ; // IsException BOOLEAN elem_func IsTagTable Self .IsStereotype st_TagTable >>> Result ; // IsTagTable BOOLEAN elem_func IsTarget Cached: ( RULES ( Self .IsStereotype st_ExeTarget ) true ( Self .IsStereotype st_AdapterTarget ) true ( Self .IsStereotype st_TestTarget ) true DEFAULT false ; // RULES ) >>> Result ; // IsTarget BOOLEAN elem_func IsEvdSchemaElement Self .IsStereotype st_Atom >>> Result ; // IsEvdSchemaElement BOOLEAN elem_func IsClassOrMixIn Cached: ( RULES ( Self .IsSimpleClass ) true ( Self .IsMixIn ) true DEFAULT false ; // RULES ) >>> Result ; // IsClassOrMixIn BOOLEAN FUNCTION NeedOwnFile ModelElement IN Self Cached: ( RULES ( Self .IsStereotype st_ScriptKeywords ) false ( Self .IsStereotype st_TestClass ) true ( Self .IsEvdSchemaElement ) true ( Self .IsTarget ) true ( Self .IsStereotype st_TestResults ) true ( Self .IsTagTable ) true ( Self .IsInterfaces ) true ( Self .IsUtilityPack ) true ( Self .IsMixIn ) true ( Self .IsElementProxy ) true ( Self .IsSimpleClass ) begin RULES ( Self .Visibility = ProtectedAccess ) false ( Self .Visibility = PrivateAccess ) false DEFAULT ( ModelElement VAR l_Parent Self .Parent >>> l_Parent if ( ( l_Parent .IsClassOrMixIn ) OR ( l_Parent .IsUtilityPack ) OR ( l_Parent .IsInterfaces ) ) then begin false end else begin true end ) ; // RULES end DEFAULT false ; // RULES ) >>> Result ; // NeedOwnFile PROCEDURE .CurrentGenerator ModelElement IN Self Self g_CurrentGenerator DO ; // .CurrentGenerator USES CallInherited.ms.dict ; USES classRelations.ms.dict ; BOOLEAN elem_func NeedOwnFile Self .? NeedOwnFile >>> Result ; // NeedOwnFile elem_proc dump Self .Out Bracketed ( Self MembersIterator .for> ( OBJECT IN aCode STRING VAR l_Out STRING VAR l_Name aCode pop:Word:Name >>> l_Name [ l_Name ' : ' ] strings:Cat >>> l_Out [ aCode DO ] .for> ( IN anItem if ( anItem .IsSequence ) then ( anItem .SequenceCode.It >>> anItem ) if ( anItem IsArray ) then begin if ( ( l_Name = 'Children' ) ) then begin '' >>> l_Out l_Name .Out Bracketed ( ARRAY VAR l_Items anItem .filter> ( .NeedOwnFile ! ) >>> l_Items l_Items .filter> ( .Visibility = PrivateAccess ) .for> call.me l_Items .filter> ( .Visibility = ProtectedAccess ) .for> call.me l_Items .filter> ( .Visibility = PublicAccess ) .for> call.me l_Items .filter> ( .Visibility = UnknownAccess ) .for> call.me ) // Bracketed end else if ( ( l_Name = 'Attributes' ) OR ( l_Name = 'Operations' ) OR ( l_Name = 'Constants' ) OR ( l_Name = 'Dependencies' ) OR ( l_Name = 'Parameters' ) ) then begin '' >>> l_Out l_Name .Out Bracketed ( ARRAY VAR l_Items anItem // .filter> ( .NeedOwnFile ! ) >>> l_Items l_Items .filter> ( .Visibility = PrivateAccess ) .for> call.me l_Items .filter> ( .Visibility = ProtectedAccess ) .for> call.me l_Items .filter> ( .Visibility = PublicAccess ) .for> call.me l_Items .filter> ( .Visibility = UnknownAccess ) .for> call.me ) // Bracketed end else begin l_Out [ anItem .for> ValueToStringOrName ] ' ' strings:CatSep Cat >>> l_Out end end // anItem IsArray else begin l_Out anItem ValueToStringOrName Cat >>> l_Out end // anItem IsArray if ( l_Out <> '' ) then begin l_Out .Out end // l_Out <> '' ) // [ aCode DO ] .for> ) // Self MembersIterator ) // Bracketed ; // dump PROCEDURE OutLn '' .Out ; // OutLn elem_proc WithDelim STRING IN aDelim TtfwWord IN aVar TtfwWord IN aLambda [ if ( aVar DO ! ) then begin true aVar pop:Word:SetValue end else begin aDelim end Self ] aLambda DO ; // WithDelim elem_proc WithComma: ^ IN aVar ^ IN aLambda Self ', ' aVar aLambda .WithDelim ; // WithComma: STRING FUNCTION .CutT STRING IN aName aName >>> Result if ( 'T' Result StartsStr ) then begin Result 'T' '' string:ReplaceFirst >>> Result end // 'T' Result StartsStr ; // .CutT STRING elem_func UnitNamePrim GenCached: ( STRING VAR l_Path Self .GetUP 'intf.pas:Path' >>> l_Path RULES ( l_Path <> '' ) ( 'w:\' // - это потому, что в пути нету диска, а для ExtractFileName он нужен l_Path Cat sysutils:ExtractFileName '' sysutils:ChangeFileExt ) ( Self IsNil ) '' ( Self .IsElementProxy ) ( Self .Name '_Proxy' Cat ) ( Self .IsTagTable ) ( Self .Name '_Schema' Cat ) ( Self .IsScriptKeyword ) ( Self .Name .CutT ) ( Self .IsSimpleClass ) ( Self .Name .CutT ) DEFAULT ( Self .Name ) ; // RULES ) >>> Result ; // UnitNamePrim STRING elem_func UnitName GenCached: ( Self .UnitNamePrim 'NOT_FINISHED_' '' string:ReplaceFirst ) >>> Result ; // UnitName ModelElement elem_func UnitProducer GenCached: ( RULES ( Self IsNil ) nil ( Self IsString ) Self ( Self .NeedOwnFile ) Self DEFAULT ( Self .Parent call.me ) ; // RULES ) >>> Result ; // UnitProducer ARRAY FUNCTION .filterNil> ARRAY IN anArray anArray .filter> ( IsNil ! ) >>> Result ; // .filterNil> ARRAY FUNCTION .filterMixIns> ARRAY IN anArray anArray .filter> ( .IsMixIn ! ) // .filter> ( .IsPureMixIn ! ) >>> Result ; // .filterMixIns> elem_proc OutUses: ^ IN aUsed ^ IN aLambda ARRAY VAR l_Used aUsed DO >>> l_Used ARRAY FUNCTION .filterUsed> ARRAY IN anArray anArray .filter> ( IN anItem if ( anItem l_Used array:Has ! ) then begin anItem array:AddTo l_Used true end else begin false end ) >>> Result ; // .filterUsed> 'uses' .Out VAR l_NeedComma false >>> l_NeedComma Indented: ( aLambda DO .map> .UnitProducer .filterNil> .filterMixIns> .filter> ( Self ?!= ) .filter> ( .UnitName Self .UnitName ?!= ) .filter> ( .UnitName 'System' ?!= ) .map> .UnitName .filterUsed> .for> ( .WithComma: l_NeedComma .Out ) ) // Indented: ';' .Out OutLn ; // OutUses: ARRAY FUNCTION .mapToTarget> ARRAY IN anArray anArray .map> .Target >>> Result ; // .mapToTarget> ARRAY FUNCTION .joinWithLambded> ARRAY IN anArrayToJoin ^ IN anArrayToIterate ^ IN aLambda anArrayToJoin anArrayToIterate DO .for> ( IN aChild .join> ( aChild aLambda DO ) ) >>> Result ; // .joinWithLambded> ARRAY FUNCTION .mapToTargetAndValueType> ARRAY IN anArray anArray .mapToTarget> .join> ( anArray .map> .ValueType ) >>> Result ; // .mapToTargetAndValueType> elem_iterator AttributesAndOperations Cached: ( Self .Attributes .join> ( Self .Operations ) ) >>> Result ; // AttributesAndOperations elem_iterator ChildrenWithoutOwnFile Cached: ( Self .Children .filter> ( .NeedOwnFile ! ) ) >>> Result ; // ChildrenWithoutOwnFile elem_iterator ConstantsAndChildrenWithoutOwnFile Cached: ( Self .Constants .join> ( Self .ChildrenWithoutOwnFile ) ) >>> Result ; // ConstantsAndChildrenWithoutOwnFile elem_iterator AllOwnChildren Cached: ( Self .ConstantsAndChildrenWithoutOwnFile .join> ( Self .AttributesAndOperations ) ) >>> Result ; // AllOwnChildren ARRAY FUNCTION .OperationsNeededElements ARRAY IN anArray anArray .mapToTargetAndValueType> .joinWithLambded> anArray ( .Parameters .mapToTargetAndValueType> ) .joinWithLambded> anArray ( .AttributesAndOperations call.me ) >>> Result ; // .OperationsNeededElements elem_iterator NeededElements ( Self .Inherits ) .join> ( Self .Implements ) .join> ( Self .AttributesAndOperations .OperationsNeededElements ) if ( Self .IsTypedef ! ) then begin .join> ( Self .Implemented .OperationsNeededElements ) .join> ( Self .Overridden .OperationsNeededElements ) end // Self .IsTypedef ! >>> Result ; // NeededElements elem_iterator NeededElementsTotal Self .NeededElements .joinWithLambded> ( Self .ConstantsAndChildrenWithoutOwnFile ) call.me >>> Result ; // NeededElementsTotal BOOLEAN elem_func IsForInterface Cached: ( RULES ( Self .Visibility PublicAccess == ) true ( Self .Visibility ProtectedAccess == ) true DEFAULT false ; // RULES ) >>> Result ; // IsForInterface BOOLEAN elem_func IsForImplementation Cached: ( Self .IsForInterface ! ) >>> Result ; // IsForImplementation elem_iterator IntfUses [ 'l3IntfUses' ] if ( Self .IsForInterface ) then begin .join> ( Self .NeededElementsTotal ) end // Self .IsForInterface >>> Result ; // IntfUses BOOLEAN elem_func IsInterface Cached: ( RULES ( Self .IsStereotype st_ObjStub ) false ( Self .IsStereotype st_Facet ) true DEFAULT false ; // RULES ) >>> Result ; // IsInterface elem_iterator InjectedElements Self .Injected .filter> ( .IsStereotype st_injects::Dependency ) .map> .Parent >>> Result ; // InjectedElements BOOLEAN elem_func IsClassImplementable Cached: ( RULES ( Self .IsPureMixIn ) false ( Self .IsMixIn ) false ( Self .IsEvdSchemaElement ) false ( Self .IsStereotype st_MixInMirror ) false ( Self .IsStereotype st_UseCase ) false DEFAULT true ; // RULES ) >>> Result ; // IsClassImplementable elem_iterator Used Cached: ( Self .Dependencies .filter> ( .IsStereotype st_uses::Dependency ) .mapToTarget> if ( Self .IsInterface ! ) then begin .join> ( Self .InjectedElements ) end // Self .IsInterface ! .joinWithLambded> ( Self .Inherits .filter> .IsMixIn ) call.me .joinWithLambded> ( Self .Implements .filter> .IsMixIn ) call.me ) >>> Result ; // Used elem_iterator UsedTotal Self .Used .joinWithLambded> ( Self .AllOwnChildren ) call.me >>> Result ; // UsedTotal elem_iterator ImplUses [ 'l3ImplUses' ] if ( Self .IsForImplementation ) then begin .join> ( Self .NeededElementsTotal ) end // Self .IsForImplementation .join> ( Self .UsedTotal ) >>> Result ; // ImplUses STRING elem_func TypeName Cached: ( STRING VAR l_ExtName Self .GetUP 'extprop:pas:TypeName' >>> l_ExtName RULES ( l_ExtName <> '' ) l_ExtName DEFAULT ( Self .Name ) ; // RULES ) >>> Result ; // TypeName BOOLEAN elem_func IsClass Self .IsSimpleClass >>> Result ; // IsClass : .FirstElement ARRAY IN anArray ModelElement VAR l_Found nil >>> l_Found anArray .trunc> ( DROP l_Found IsNil ) .for> ( >>> l_Found ) l_Found ; // .FirstElement ModelElement elem_func MainAncestor Cached: ( Self .Inherits .FirstElement ) >>> Result ; // MainAncestor ModelElement elem_func MainImplements Cached: ( Self .Implements .FirstElement ) >>> Result ; // MainImplements ModelElement elem_func FirstAttribute Cached: ( Self .Attributes .FirstElement ) >>> Result ; // FirstAttribute ModelElement elem_func FirstOperation Cached: ( Self .Operations .FirstElement ) >>> Result ; // FirstOperation : .With() OUTABLE IN aValue if ( aValue IsNil ! ) then [ '(' aValue ')' ] ; // .With() STRING elem_func FineDocumentation Self .Documentation >>> Result if ( Result IsNil ! ) then begin Result '{' '[' string:Replace >>> Result Result '}' ']' string:Replace >>> Result [ '{* ' Result ' }' ] strings:Cat >>> Result end // Result IsNil ! ; // FineDocumentation elem_proc OutDocumentation STRING VAR l_Doc Self .FineDocumentation >>> l_Doc if ( l_Doc IsNil ! ) then begin Indented: ( l_Doc .Out ) end // l_Doc IsNil ! ; // OutDocumentation ModelElement elem_func MethodType Cached: ( RULES ( Self .IsStereotype st_method ) ( Self .FirstOperation .Target ) ( Self .IsFunction ) ( Self .FirstOperation .Target ) DEFAULT ( Self .Target ) ; // RULES VAR l_Type >>> l_Type RULES ( l_Type IsNil ) begin RULES ( Self .IsStereotype st_factory::Operation ) ( Self .Parent .MainImplements ) ( Self .IsStereotype st_Factory ) ( Self .MainImplements ) DEFAULT l_Type ; // RULES end // ( l_Type IsNil ) DEFAULT l_Type ; // RULES >>> l_Type RULES ( l_Type IsNil ) begin RULES ( Self .IsStereotype st_factory::Operation ) ( 'BadFactoryType' ) ( Self .IsStereotype st_Factory ) ( Self .Parent .MainImplements ) DEFAULT l_Type ; // RULES end // ( l_Type IsNil ) DEFAULT l_Type ; // RULES ) >>> Result ; // MethodType ARRAY elem_func MethodParameters RULES ( Self .IsStereotype st_method ) ( Self .FirstOperation .Parameters ) ( Self .IsFunction ) ( Self .FirstOperation .Parameters ) DEFAULT ( Self .Parameters ) ; // RULES >>> Result ; // MethodParameters STRING elem_func MethodCallingConventions RULES DEFAULT ( Self .GetUP "calling conventions" ) ; // RULES >>> Result if ( Result 'none' == ) then begin '' >>> Result end // ( Result 'none' == ) if ( Result IsNil ! ) then begin ' ' Result ';' Cat Cat >>> Result end // ( Result IsNil ! ) ; // MethodCallingConventions CONST cConstPrefix 'const ' STRING elem_func InPrefix Cached: ( RULES ( Self .IsRecord ) cConstPrefix ( Self .IsUnion ) cConstPrefix ( Self .IsArray ) cConstPrefix ( Self .IsInterface ) cConstPrefix ( Self .IsTypedef ) RULES ( Self .UPisTrue "isPointer" ) '' DEFAULT ( Self .MainAncestor call.me ) ; // RULES ( Self .IsStereotype st_ImpurityParamType ) cConstPrefix ( Self .Name 'a-string' == ) cConstPrefix ( Self .Name 'a-wstring' == ) cConstPrefix ( Self .Name 'object' == ) cConstPrefix ( Self .Name 'void' == ) cConstPrefix DEFAULT '' ; // RULES ) >>> Result ; // InPrefix STRING elem_func ParamPrefix RULES ( Self .IsStereotype st_in ) ( Self .Target .InPrefix ) ( Self .IsStereotype st_const ) cConstPrefix ( Self .IsStereotype st_noconst ) '' ( Self .IsStereotype st_out ) 'out ' ( Self .IsStereotype st_inout ) 'var ' DEFAULT '' ; // RULES >>> Result ; // ParamPrefix STRING elem_func MethodName Self .Name >>> Result ; // MethodName BOOLEAN elem_func IsConstructor RULES ( Self .IsStereotype st_ctor::Operation ) true ( Self .IsStereotype st_Constructor ) true DEFAULT false ; //RULES >>> Result ; // IsConstructor BOOLEAN elem_func IsFactory RULES ( Self .IsStereotype st_factory::Operation ) true ( Self .IsStereotype st_Factory ) true DEFAULT false ; //RULES >>> Result ; // IsFactory BOOLEAN elem_func IsDestructor Self .MethodName 'Destroy' == >>> Result ; // IsDestructor OUTABLE elem_func MethodKeyword Cached: ( RULES ( Self .IsConstructor ) ( 'constructor' ) ( Self .IsFactory ) ( 'class function' ) ( Self .IsDestructor ) ( 'destructor' ) DEFAULT ( ModelElement VAR l_Type Self .MethodType >>> l_Type VAR l_IsFunc ( l_Type IsNil ! ) AND ( l_Type .TypeName IsNil ! ) >>> l_IsFunc [ RULES ( Self .IsStereotype st_static::Operation ) 'class ' ( Self .UPisTrue "is static" ) 'class ' ; // RULES if l_IsFunc then begin 'function' end // l_IsFunc else begin 'procedure' end // l_IsFunc ] ) // DEFAULT ; // RULES ) >>> Result ; // MethodKeyword BOOLEAN elem_func IsProperty Cached: ( RULES ( Self .IsStereotype st_property::Attribute ) true ( Self .IsStereotype st_readonly::Attribute ) true ( Self .IsStereotype st_writeonly::Attribute ) true DEFAULT false ; // RULES ) >>> Result ; // IsProperty BOOLEAN elem_func ParentIsInterface Cached: ( Self .Parent .IsInterface ) >>> Result ; // ParentIsInterface INTEGER elem_func MethodAbstraction Self .OpKind CASE opkind_Normal ( RULES ( Self .ParentIsInterface ) at_final ( Self .IsFunction ) at_final DEFAULT ( Self .Abstraction ) ; // RULES ) // opkind_Normal opkind_Implemented ( RULES ( Self .ParentIsInterface ) at_final ( Self .IsStereotype st_inline::Operation ) at_final DEFAULT at_override ; // RULES ) // opkind_Implemented opkind_Overridden at_override DEFAULT at_final END // CASE >>> Result ; // MethodAbstraction CONST opModifyNone 1 CONST opModifySetter 2 elem_iterator MethodInterfacePrim IN aOverload IN aOfObject IN aOpModify : OutOverloadAndCallingConventions aOverload DO Self .MethodCallingConventions ; // OutOverloadAndCallingConventions : OutReintroduce RULES ( Self .IsConstructor ) ( ' reintroduce;' ) ( Self .IsFactory ) ( ' reintroduce;' ) ; // RULES ; // OutReintroduce [ RULES ( ( Self .IsStereotype st_writeonly::Attribute ) AND ( aOpModify opModifySetter != ) ) () DEFAULT ( ModelElement VAR l_Type Self .MethodType >>> l_Type VAR l_IsFunc RULES ( aOpModify opModifySetter == ) ( false >>> l_IsFunc 'procedure' ) DEFAULT ( ( l_Type IsNil ! ) AND ( l_Type .TypeName IsNil ! ) >>> l_IsFunc Self .MethodKeyword ) ; // RULES if ( Self .IsFunction ! ) then begin ' ' RULES ( Self .IsProperty ) ( if l_IsFunc then begin if ( Self .UPisTrue "pm" ) then 'pm_Get' else 'Get_' end else begin if ( Self .UPisTrue "pm" ) then 'pm_Set' else 'Set_' end ) ; // RULES Self .MethodName end // ( Self .IsFunction ! ) VAR l_WasParam false >>> l_WasParam RULES ( Self .IsProperty ) ( Self .Attributes ) DEFAULT ( Self .MethodParameters ) ; // RULES .for> ( IN aParam if ( l_WasParam ) then begin ';' \n ' ' end else begin '(' true >>> l_WasParam end aParam .ParamPrefix aParam .Name VAR l_Type aParam .Target >>> l_Type if ( l_Type IsNil ! ) then begin ': ' l_Type .TypeName end // ( l_Type IsNil ! ) VAR l_Doc aParam .FineDocumentation >>> l_Doc if ( l_Doc IsNil ! ) then begin ' ' l_Doc end // ( l_Doc IsNil ! ) ) // Self .MethodParameters .for> if ( aOpModify opModifySetter == ) then begin if ( l_WasParam ) then begin ';' ' ' end else begin '(' true >>> l_WasParam end l_Type .InPrefix 'aValue' ': ' l_Type .TypeName end // ( aOpModify opModifySetter == ) if ( l_WasParam ) then ')' if l_IsFunc then begin ': ' l_Type .TypeName end // l_IsFunc aOfObject DO ';' Self .MethodAbstraction CASE at_final ( OutReintroduce OutOverloadAndCallingConventions ) at_virtual ( OutReintroduce OutOverloadAndCallingConventions ' virtual;' ) at_abstract ( OutReintroduce OutOverloadAndCallingConventions ' virtual; abstract;' ) at_override ' override;' END // CASE ) // DEFAULT ; // RULES ] >>> Result ; // MethodInterfacePrim BOOLEAN elem_func ReadsField Self .UPisTrue "reads field" >>> Result ; // elem_func ReadsField BOOLEAN elem_func WritesField Self .UPisTrue "writes field" >>> Result ; // elem_func WritesField elem_iterator MethodInterfaceEx IN aOverload IN aOfObject [ : NormalCall Self aOverload aOfObject opModifyNone .MethodInterfacePrim ; // NormalCall : CallAsSetter Self aOverload aOfObject opModifySetter .MethodInterfacePrim ; // CallAsSetter RULES ( Self .IsStereotype st_readonly::Attribute ) if ( Self .ReadsField ! ) then NormalCall ( Self .IsStereotype st_writeonly::Attribute ) if ( Self .WritesField ! ) then CallAsSetter ( Self .IsStereotype st_property::Attribute ) ( VAR l_NeedLN false >>> l_NeedLN if ( Self .ReadsField ! ) then begin true >>> l_NeedLN NormalCall end if ( Self .WritesField ! ) then begin if l_NeedLN then \n CallAsSetter end // ( Self .WritesField ! ) ) DEFAULT NormalCall ; // RULES ] >>> Result ; // MethodInterfaceEx elem_iterator MethodInterfaceEx: ^ IN aOverload ^ IN aOfObject Self aOverload aOfObject .MethodInterfaceEx >>> Result ; // MethodInterfaceEx: elem_iterator MethodInterface: ^ IN aOverload Self .MethodInterfaceEx: ( if ( Self .UPisTrue "force overload" ) then begin ' overload;' end // ( aMethod .UPisTrue "force overload" ) else begin aOverload DO end ) () >>> Result ; // MethodInterface: INTEGER FUNCTION .CountIt ARRAY IN anArray 0 >>> Result anArray .for> ( IN anItem Inc Result ) ; // .CountIt elem_iterator OwnOperations Self .Operations .filter> ( .IsStereotype st_static::Operation ! ) >>> Result ; // OwnOperations elem_iterator Properties Self .Attributes .filter> .IsProperty >>> Result ; // Properties elem_iterator InterfaceOperationsTotal Cached: ( Self .OwnOperations .joinWithLambded> ( Self .Implements .filter> .IsPureMixIn ) ( IN anItem anItem call.me .joinWithLambded> ( anItem .Inherits .filter> .IsPureMixIn ) .OwnOperations ) ) >>> Result ; // InterfaceOperationsTotal elem_iterator InterfacePropertiesTotal Cached: ( Self .Properties .joinWithLambded> ( Self .Implements .filter> .IsPureMixIn ) ( IN anItem anItem call.me .joinWithLambded> ( anItem .Inherits .filter> .IsPureMixIn ) .Properties ) ) >>> Result ; // InterfacePropertiesTotal elem_iterator InterfaceProperties Cached: ( RULES ( Self .IsPureMixIn ) ( Self .Properties ) DEFAULT ( Self .InterfacePropertiesTotal ) ; // RULES ) >>> Result ; // InterfaceProperties elem_iterator AllOperationsForOverload Cached: ( RULES ( Self .IsPureMixIn ) ( Self .OwnOperations ) ( Self .IsInterface ) ( Self .InterfaceOperationsTotal ) ( Self .IsClassOrMixIn ) ( Self .Operations .filter> ( .IsStereotype st_responsibility::Operation ! ) .filter> ( .IsStereotype st_ini::Operation ! ) .filter> ( .IsStereotype st_fini::Operation ! ) .join> ( Self .Implemented ) ) DEFAULT ( Self .Operations ) ; // RULES ) >>> Result ; // AllOperationsForOverload elem_iterator AllOperationsForDefine Cached: ( RULES ( Self .IsPureMixIn ) ( Self .Properties ) ( Self .IsInterface ) ( Self .InterfacePropertiesTotal ) ( Self .IsClassOrMixIn ) ( Self .Attributes .filter> .IsProperty .filter> ( IN anItem ( anItem .ReadsField ! ) OR ( anItem .WritesField ! ) ) ) DEFAULT ( [empty] ) ; // RULES .join> ( Self .AllOperationsForOverload ) RULES ( Self .IsClassOrMixIn ) ( .join> ( Self .Overridden ) .filter> ( .IsStereotype st_inline::Operation ! ) ) ; // RULES ) >>> Result ; // AllOperationsForDefine elem_iterator MethodInterfaceFor: ^ IN anOperations Self .MethodInterface: ( ARRAY VAR l_Ops anOperations DO >>> l_Ops if ( l_Ops .filter> ( .IsProperty ! ) .filter> ( .MethodName Self .MethodName == ) .CountIt > 1 ) then begin ' overload;' end ) // Self .MethodInterface: >>> Result ; // MethodInterfaceFor: elem_proc OutClass [ Self .TypeName ' = class' [ Self .MainAncestor ] .join> ( Self .Implements .filter> .IsClassImplementable ) .map> .TypeName ', ' strings:CatSep .With() ] .Out Self .OutDocumentation Indented: ( VAR l_AllOps Self .AllOperationsForOverload >>> l_AllOps Self .AllOperationsForDefine .for> ( IN aMethod aMethod .MethodInterfaceFor: l_AllOps .Out? ? ( aMethod .OutDocumentation ) // aMethod .MethodInterfaceFor: l_AllOps .Out? ? ) // .for> ) // Indented: [ 'end;//' Self .TypeName ] .Out ; // OutClass elem_proc OutInterfaceBody Indented: ( VAR l_Ops Self .AllOperationsForDefine >>> l_Ops VAR l_AllOps Self .AllOperationsForOverload >>> l_AllOps l_Ops .for> ( IN aMethod aMethod .MethodInterfaceFor: l_AllOps .Out? ? ( aMethod .OutDocumentation ) ) Self .InterfaceProperties .for> ( IN aProperty [ 'property ' aProperty .Name ': ' aProperty .Target .TypeName ';' ] .Out aProperty .OutDocumentation ) ) // Indented: ; // OutInterfaceBody elem_proc OutInterface [ Self .TypeName ' = interface' Self .MainAncestor .TypeName .With() ] .Out Self .OutDocumentation VAR l_GUID Self .GUID >>> l_GUID if ( l_GUID IsNil ! ) then begin Indented: ( [ '[''{' l_GUID '}'']' ] .Out ) end // ( l_GUID IsNil ! ) Self .OutInterfaceBody [ 'end;//' Self .TypeName ] .Out ; // OutInterface elem_proc OutRecord [ Self .TypeName ' = record' ] .Out Self .OutDocumentation [ 'end;//' Self .TypeName ] .Out ; // OutRecord elem_proc OutDefine [ '{$Define ' Self .Name '}' ] .Out ; // OutDefine elem_proc OutUndef [ '{$Undef ' Self .Name '}' ] .Out ; // OutUndef elem_proc OutStaticObject [ Self .TypeName ' = object' Self .MainAncestor .TypeName .With() ] .Out Self .OutDocumentation [ 'end;//' Self .TypeName ] .Out ; // OutStaticObject elem_proc OutPureMixIn '(*' .Out Self .OutInterface '*)' .Out ; // OutPureMixIn elem_proc OutTypedef ModelElement VAR l_MainAncestor Self .MainAncestor >>> l_MainAncestor [ Self .TypeName ' = ' if ( Self .UPisTrue "newRTTI" ) then 'type ' if ( Self .UPisTrue "isPointer" ) then '^' if ( Self .UPisTrue "isClassRef" ) then 'class of ' if ( Self .UPisTrue "isPointer" ! ) then begin STRING VAR l_OtherUnit l_MainAncestor .UnitProducer .UnitName >>> l_OtherUnit if ( l_OtherUnit '' != ) then begin if ( Self .TypeName l_MainAncestor .TypeName == ) then begin STRING VAR l_OurUnit Self .UnitProducer .UnitName >>> l_OurUnit if ( l_OurUnit l_OtherUnit != ) then begin l_OtherUnit '.' end // l_OurUnit l_OtherUnit != end // Self .TypeName l_MainAncestor .TypeName == end // l_OtherUnit '' != end // Self .UPisTrue "isPointer" ! l_MainAncestor .TypeName ';' ] .Out Self .OutDocumentation ; // OutTypedef elem_proc OutEnum [ Self .TypeName ' = (' ] .Out Self .OutDocumentation STRING VAR l_Prefix Self .GetUP 'extprop:pas:ElementPrefix' >>> l_Prefix VAR l_NeedComma false >>> l_NeedComma Indented: ( Self .Attributes .for> ( IN aChild l_Prefix aChild .Name Cat .WithComma: l_NeedComma .Out aChild .OutDocumentation ) // Self .Attributes .for> ) // Indented: [ ');//' Self .TypeName ] .Out ; // OutEnum elem_proc OutSetOf [ Self .TypeName ' = set of ' Self .MainAncestor .TypeName ';' ] .Out Self .OutDocumentation ; // OutSetOf elem_proc OutFunction [ Self .TypeName ' = ' Self .MethodInterfaceEx: () ( if ( Self .UPisTrue "of object" ) then begin ' of object' end // ( Self .UPisTrue "of object" ) ) ] .Out Self .OutDocumentation ; // OutFunction elem_proc OutArray if ( Self .GetUP "array type" 'open' != ) then begin [ Self .TypeName ' = array ' if ( Self .MainAncestor IsNil ! ) then begin '[' Self .MainAncestor .TypeName '] ' end // ( Self .MainAncestor IsNil ! ) 'of ' Self .FirstAttribute .Target .TypeName ';' ] .Out Self .OutDocumentation end // ( Self .GetUP "array type" 'open' != ) ; // OutArray ARRAY CompileTime-VAR g_OutedTypes [] elem_proc OutForward if ( Self g_OutedTypes array:Has ! ) then begin RULES ( Self .IsPureMixIn ) () ( Self .IsClass ) ( [ Self .TypeName ' = class;' ] .Out OutLn ) ( Self .IsInterface ) ( [ Self .TypeName ' = interface;' ] .Out OutLn ) ; // RULES end // ( Self g_OutedTypes array:Has ! ) ; // OutForward elem_proc OutType RULES ( Self .IsUtilityPack ) () ( Self .IsInterfaces ) () ( Self .IsTarget ) () ( ( Self .IsArray ) AND ( Self .GetUP "array type" 'open' == ) ) () DEFAULT ( if ( Self g_OutedTypes array:Has ! ) then begin Self array:AddTo g_OutedTypes Self .Forwarded .for> .OutForward RULES ( Self .IsSetOf ) ( Self .OutSetOf ) ( Self .IsArray ) ( Self .OutArray ) ( Self .IsEnum ) ( Self .OutEnum ) ( Self .IsTypedef ) ( Self .OutTypedef ) ( Self .IsException ) ( Self .OutClass ) ( Self .IsClass ) ( Self .OutClass ) ( Self .IsPureMixIn ) ( Self .OutPureMixIn ) ( Self .IsInterface ) ( Self .OutInterface ) ( Self .IsStaticObject ) ( Self .OutStaticObject ) ( Self .IsUnion ) ( Self .OutRecord ) ( Self .IsRecord ) ( Self .OutRecord ) ( Self .IsUndef ) ( Self .OutUndef ) ( Self .IsDefine ) ( Self .OutDefine ) ( Self .IsFunction ) ( Self .OutFunction ) DEFAULT ( [ '// ' Self .TypeName ] .Out ) ; // RULES OutLn end // ( Self g_OutedTypes array:Has ! ) ) // DEFAULT ; // RULES ; // OutType BOOLEAN elem_func IsType Cached: ( RULES ( Self .IsUtilityPack ) false ( Self .IsInterfaces ) false ( Self .IsTarget ) false ( Self .IsEvdSchemaElement ) false ( Self .IsPureMixIn ) false ( Self .IsDefine ) false DEFAULT true ; // RULES ) >>> Result ; // IsType elem_proc OutTypes ^ IN aValid VAR l_WasType false >>> l_WasType elem_proc DoOutTypes Self .ChildrenWithoutOwnFile .for> call.me if ( Self aValid DO ) then begin if ( Self .IsType ) then begin if ( l_WasType ! ) then begin 'type' .Out true >>> l_WasType end // l_WasType ! end // Self .IsType Indented: ( Self .OutType ) end ; // DoOutTypes Self .DoOutTypes ; // OutTypes elem_proc OutInterfaceSection Self .OutTypes .IsForInterface ; // OutInterfaceSection elem_proc OutImplementationSection Self .OutTypes .IsForImplementation ; // OutImplementationSection elem_proc OutUnit TF g_OutedTypes ( [ 'unit ' Self .UnitNamePrim ';' ] .Out OutLn 'interface' .Out OutLn ARRAY VAR l_Used [] >>> l_Used Self .OutUses: l_Used ( Self .IntfUses ) Self .OutInterfaceSection 'implementation' .Out OutLn Self .OutUses: l_Used ( Self .ImplUses ) Self .OutImplementationSection 'end.' .Out ) // TF g_OutedTypes ; // OutUnit elem_proc OutMixIn Self .OutUnit ; // OutMixIn elem_generator pas CONST Ext '.pas' RULES ( Self .IsMixIn ) ( Self .OutMixIn ) ( Self .IsInterfaces ) ( Self .OutUnit ) ( Self .IsEvdSchemaElement ) ( Self .OutUnit ) ( Self .IsSimpleClass ) ( Self .OutUnit ) ( Self .IsElementProxy ) ( Self .OutUnit ) ( Self .IsUtilityPack ) ( Self .OutUnit ) ( Self .IsStereotype st_TestClass ) ( Self .OutUnit ) ( Self .IsTarget ) ( Self .OutUnit ) ( Self .IsTagTable ) ( Self .OutUnit ) DEFAULT ( Self .dump ) ; // RULES ; // pas elem_generator res.cmd Inherits .pas CONST Ext '.res.cmd' BOOLEAN FUNCTION NeedOwnFile ModelElement IN Self Self .UPisTrue "needs script" >>> Result ; // NeedOwnFile [ 'MakeCo ' Self .Name '.rc.script' ] .Out [ 'brcc32 ' Self .Name '.rc' ] .Out //call.inherited ; // res.cmd elem_generator rc Inherits .res.cmd CONST Ext '.rc' [ Self .Name ' RCDATA LOADONCALL MOVEABLE DISCARDABLE ' Self .Name '.rc.script.co' ] .Out //call.inherited ; // rc ARRAY CompileTime-VAR g_GeneratedElements [] %REMARK 'Ранее сгенерированные элементы' PROCEDURE .GenerateWithChildren ModelElement IN Self Sequence IN aGenerators if ( Self g_GeneratedElements array:Has ! ) then begin Self array:AddTo g_GeneratedElements aGenerators CodeIterator .for> ( // - цикл по генераторам для Self TtfwWord IN aGenerator TF g_CurrentGenerator ( aGenerator >>> g_CurrentGenerator if ( Self .NeedOwnFile ) then ( Self .GenerateWordToFile .CurrentGenerator ) else ( Self .DeleteWordFile ) ) // TF g_CurrentGenerator ) // aGenerators CodeIterator .for> Self .Children // .filter> ( .NeedOwnFile ) .for> ( aGenerators call.me ) // - тут генерируем детей end // Self g_GeneratedElements array:Has ! ; // .GenerateWithChildren PROCEDURE .call.generators.in.list ModelElement IN Self Sequence ^ IN aGenerators Self aGenerators .GenerateWithChildren ; // .call.generators.in.list PROCEDURE .Generate ModelElement IN Self g_GeneratedFiles = nil ?FAIL 'Массив g_GeneratedFiles не инициализирован' g_GeneratedElements = nil ?FAIL 'Массив g_GeneratedElements не инициализирован' Self .call.generators.in.list ( .pas .res.cmd .rc ) ; // .Generate
Заметки о тестировании, программировании и прочий "поток сознания", который жалко писать "в стол"
Где можно почитать про WordWorker? Какие способы передачи аргументов существуют (слева, справа, справа без выполнения функции). Интересно стало. Буду благодарен, если ткнете пальцем =)
ОтветитьУдалитьА вообще хотелось бы полноценной документации, но понятно что не все сразу.
Для начала - https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=programmingmindstream+WordWorker
УдалитьДетальнее - напишу позже, если действительно интересно.
УдалитьНу и - http://programmingmindstream.blogspot.ru/2014/06/blog-post_4070.html
Удалить"Какие способы передачи аргументов существуют (слева, справа, справа без выполнения функции)"
УдалитьТочнее:
"Какие способы передачи аргументов существуют (слева, справа, СЛЕВА без выполнения функции)"
СПРАВА - всегда передаётся ссылка на слово.
А слева по-умолчанию - значение.
Коротко:
IN aValue // - значение СЛОВА слева
^@ IN aValue // - ссылка на СЛОВО слева
^ IN aValue // - ссылка на СЛОВО справа
Напишите пожалуйста, если будет время и желание. Интересно как это устроено изнутри.
УдалитьВ гугл я умею, а за ссылку спасибо, изучу. И за краткое описание.
Очень даже интересно. Впрочем, я только начинаю вникать в суть и вопросов у меня слишком много, что бы разжевывать ответ на каждый. Поизучаю глубже, возможно они отпадут сами собой. =)
Пишу статью.
УдалитьOn-line за процессом можно наблюдать тут - https://bitbucket.org/lulinalex/mindstream/commits/06bdae30e64f95e724702bd26baf014c9df1af58?at=B284_Inheritance_Try
Напишу. Обязательно напишу. Тем более - раз есть интерес.
ОтветитьУдалитьНаписал "Часть 1" - http://programmingmindstream.blogspot.ru/2015/12/1163-wordworker-operator.html
УдалитьНаписал "Часть 2" - http://programmingmindstream.blogspot.ru/2015/12/1167-procedure-function-2.html
Удалить