четверг, 7 апреля 2016 г.

#1215. Скрипты. Ещё о правилах

elem_iterator ConstantsEx
 Self .Constants
 
 RULES
  ( Self .IsTypedef )
   RULES
    ( Self .MainAncestor .IsEnum )
     RULES
      ( Self .Name Self .MainAncestor .Name == )
       (
        Self .Name Msg // - это просто отладочная печать, что попали в это место
       )
     ; // RULES
   ; // RULES
 ; // RULES
 
 >>> Result
; // ConstantsEx

По-моему - более чем читабельно и понятно.

#1214. Обработка ошибок открытия файлов через лямбды

PROCEDURE ForceDirectories
  STRING IN aPath
 aPath sysutils:ForceDirectories ?ASSURE [ 'Не удалось создать директорию ' aPath ]  
; // ForceDirectories

FILE FUNCTION TryOpen:
  STRING IN aFileName
  ^ IN aOpenLambda
 %SUMMARY 
  'Открывает файл aFileName методом aOpenLambda обрабатывая ошибки открытия' 
  'Пытается открыть файл повторно несколько раз.'
 ;
 VAR l_TryCount
 10 >>> l_TryCount
 
 while ( l_TryCount > 0 )
 begin
  TRY
   aFileName aOpenLambda DO >>> Result 
   0 >>> l_TryCount
  EXCEPT
   Dec l_TryCount
   nil >>> Result
   if ( l_TryCount 0 == ) then
    RAISE
   else
   begin
    [ 'Файл ' aFileName ' был занят. Ожидаем его освобождения. Попытка номер: ' l_TryCount IntToStr ] strings:Cat >>std::out
    500 SLEEP
   end // ( l_TryCount 0 == )
  END // TRY..EXCEPT
 end // ( l_TryCount > 0 )
; // TryOpen: 

FILE FUNCTION MakePathAndOpenWrite
  STRING IN aFileName
 %SUMMARY 
  'Открывает файл aFileName на запись.' 
  'Если надо - создаёт полный путь на файловой системе.'
 ;
 aFileName sysutils:ExtractFilePath ForceDirectories
 aFileName TryOpen: File:OpenWrite >>> Result
; // MakePathAndOpenWrite

...

PROCEDURE ReadUCFromFile
  STRING IN aFileName
  STRING IN aCurrentGeneratedElementPrefix
 if ( aFileName sysutils:FileExists ) then
 begin
  FILE VAR l_In
  aFileName TryOpen: File:OpenRead >>> l_In
  TRY
   VAR l_UCOpened
   ARRAY VAR l_Accumulated
   STRING VAR l_Key
   
   false >>> l_UCOpened
   l_In File:ReadLines (
     IN aStr
     
    VAR l_Pos
    
    : Has
     string:Pos >>> l_Pos
     l_Pos -1 !=
    ; // Has
     
    RULES 
     ( aStr cUCStart Has )
      ( 
       l_UCOpened ! ?ASSURE [ 'Секция кода уже открыта. Файл: ' aFileName ' строка:' aStr ]
       true >>> l_UCOpened
       aStr string:Trim >>> aStr
       [] >>> l_Accumulated
       
       aStr >>> l_Key
       '*' string:SplitTo! l_Key DROP
       
      )
     ( aStr cUCEnd Has )
      ( 
       l_UCOpened ?ASSURE [ 'Секция кода не открыта. Файл: ' aFileName ' строка:' aStr  ]
       false >>> l_UCOpened
       
       VAR l_Head
       if ( l_Pos > 0 ) then
       begin
        l_Pos 0 aStr string:Substring >>> l_Head
        if ( l_Head string:TrimLeft IsNil ! ) then
        begin
         l_Head array:AddTo l_Accumulated
         
         aStr string:Len l_Pos - 
         l_Pos 
         aStr 
         string:Substring >>> aStr
        end // ( l_Head IsNil ! )
       end // ( l_Pos > 0 )
       
       aStr string:Trim >>> aStr
       
       g_CurrentGenerator ->^ l_Key ^:= l_Accumulated
       g_CurrentGenerator ->^ ( aCurrentGeneratedElementPrefix l_Key Cat ) ^:= l_Accumulated
       
       nil >>> l_Accumulated
      )
     DEFAULT
      (
       l_UCOpened ? ( 
        aStr array:AddTo l_Accumulated
       ) // l_UCOpened ?
      ) 
    ; // RULES  
   ) // l_In File:ReadLines
  FINALLY
   nil >>> l_In
  END // TRY..FINALLY
 end // ( aFileName sysutils:FileExists )
; // ReadUCFromFile


среда, 6 апреля 2016 г.

#1213. Скрипты. Правила. Итераторы. Фильтрация

elem_iterator InterfaceOwnOperations
 Self .Operations 
 .filter> ( .IsStaticMethod ! )
 .joinWithLambded> ( Self .InterfaceForClassImplements ) .ElementToArray: .CastMethod
 >>> Result
; // InterfaceOwnOperations

elem_iterator InterfaceOperationsTotal
 Cached:
 (
  Self .InterfaceOwnOperations
  .joinWithLambded> ( Self .Implements .filter> .IsPureMixIn ) (
    IN anItem
   anItem call.me
   .joinWithLambded> ( anItem .Inherits .filter> .IsPureMixIn ) .InterfaceOwnOperations
  ) 
 ) 
 >>> Result
; // InterfaceOperationsTotal

ModelElement elem_func MainImplements
 Cached:
 (
  Self .Implements 
  .FirstElement
 )
 >>> Result
; // MainImplements

BOOLEAN elem_func ImplementsIterator
 Cached:
 (
  RULES
   ( Self .MainImplements IsNil )
    false
   ( Self .MainImplements .IsIterator )
    true 
   DEFAULT
    false
  ; // RULES
 )
 >>> Result
; // ImplementsIterator

BOOLEAN elem_func IsMethodAndImplementsIterator
 RULES
  ( Self .IsMethod ! )
   false
  ( Self .ImplementsIterator )
   true 
  DEFAULT
   false
 ; // RULES
 >>> Result
; // IsMethodAndImplementsIterator

BOOLEAN elem_func SomeMethodImplementsThisIterator
  ModelElement IN anIterator
 RULES
  (
   Self .Operations
   .filter> .IsMethodAndImplementsIterator
   .map> .MainImplements
   .filter> ( anIterator .IsSameModelElement )
   .CountIt > 0
  )
   true
  DEFAULT
   false
 ; // RULES
 >>> Result 
; // SomeMethodImplementsThisIterator

elem_iterator InterfaceOperationsTotalDeep
 Self .InterfaceOperationsTotal
 
 .joinWithLambded> ( Self .Inherits .filter> .IsClassImplementable ) call.me
 
 >>> Result
; // InterfaceOperationsTotalDeep

elem_iterator ImplementedEx
 Cached:
 (
  Self .Implemented
  
  if ( Self .IsClassOrMixIn ) then
  begin
   VAR l_OutedIterators
   [] >>> l_OutedIterators
   
   .joinWithLambded> ( Self .ClassImplements ) ( 
    .InterfaceOperationsTotalDeep 
    .filter> ( .IsFacetIterator ! )
    .filter> ( .IsIterator )
    .filter> ( Self SWAP .SomeMethodImplementsThisIterator ! )
    .filter> ( 
      IN anItem
     if ( anItem l_OutedIterators array:Has ! ) then
     begin
      anItem array:AddTo l_OutedIterators
      true
     end
     else
      false 
    )
    .filter> ( 
      IN anItem 
     Self .MainAncestor call.me .filter> ( anItem .IsSameModelElement ) .CountIt 0 ==
    )
    .map> (
     Self IsVoid ?FAIL 'Self IsVoid'
     Self SWAP .ImplementMethod 
    )
    array:Copy
   )
  end // ( Self .IsClassOrMixIn )
 )
 >>> Result
; // ImplementedEx

#1212. Ещё немножко из скриптов

Циклы, исключения, работа с файлами...

FILE FUNCTION MakePathAndOpenWrite
  STRING IN aFileName
 VAR l_Path 
 aFileName sysutils:ExtractFilePath >>> l_Path
 l_Path ForceDirectories
 
 VAR l_TryCount
 10 >>> l_TryCount
 
 while ( l_TryCount > 0 )
 begin
  TRY
   aFileName File:OpenWrite >>> Result 
   0 >>> l_TryCount
  EXCEPT
   Dec l_TryCount
   if ( l_TryCount 0 == ) then
    RAISE
   else
   begin
    500 SLEEP
   end // ( l_TryCount 0 == )
  END // TRY..EXCEPT
 end // ( l_TryCount > 0 )
; // MakePathAndOpenWrite

#1211. Ссылка. Обновление кодогенерации

#1210. "Продвинутый CASE". Только код

"Продвинутый CASE". Только код.

BOOLEAN elem_func IsUtilityPack
 Cached:
 (
  RULES
   ( Self .IsStereotype st_UtilityPack )
    true
   ( Self .IsScriptKeywordsPack ) 
    true
   DEFAULT
    false
  ; // RULES 
 ) 
 >>> Result
; // IsUtilityPack

...

BOOLEAN elem_func UseNewGenExcluded
 RULES
  ( Self .IsControllerInterfaces )
   true
  ( Self '_vcmData_' .InheritsFrom )
   true
  ( 
   ( Self 'Tl3Tag' .InheritsFrom )
   AND ( Self 'TtfwKeyWordPrim' .InheritsFrom ! )
   AND ( Self .IsUtilityPack ! )
  ) 
   true
  ( Self 'TddComboBoxConfigItem' .InheritsFrom )
   true
  ( Self 'Tl3ProtoObjectForTie' .InheritsFrom )
   true
  ( Self '_evdTagHolder_' .InheritsFrom )
   true
  DEFAULT
  begin
   if ( g_UseNewGenExcluded IsNil ) then
    Init_g_UseNewGenExcluded
    
   g_UseNewGenExcluded IsNil ?FAIL 'Не инициализирован g_UseNewGenExcluded'
   g_UseNewGenExcluded IsVoid ?FAIL 'Не инициализирован g_UseNewGenExcluded'
   
   g_UseNewGenExcluded
   .filter> ( Self .UID == )
   .CountIt > 0
  end // DEFAULT 
 ; // RULES  
 >>> Result
; // UseNewGenExcluded

...

BOOLEAN elem_func IsSimpleClass
 Cached:
 (
  RULES
   ( Self .IsUseCaseControllerImp )
    ( Self .Abstraction at_abstract != )
   ( Self .IsViewAreaControllerImp )
    ( Self .Abstraction at_abstract != )
   ( Self .IsStereotype st_SimpleClass ) 
    true
   ( Self .IsStereotype st_ObjStub ) 
    true
   ( Self .IsService ) 
    true
   ( Self .IsServiceImplementation ) 
    true
   ( Self .IsScriptKeyword ) 
    true
   ( Self .IsTestCase ) 
    true
   ( Self .IsGuiControl ) 
    true
   ( Self .IsVCMForm ) 
    true
   ( Self .IsStereotype st_VCMFinalForm ) 
    true
   ( Self .IsVCMContainer ) 
    true
   ( Self .IsStereotype st_VCMFinalContainer ) 
    true
   DEFAULT
    false 
  ; // RULES
 )  
 >>> Result
; // IsSimpleClass

...

BOOLEAN elem_func IsInterface
 Cached:
 (
  RULES
   ( Self .IsStereotype st_ObjStub ) 
    false
   ( Self .IsStereotype st_Facet )
    true
   ( Self .IsStereotype st_Interface )
    true
   ( Self .Name 'object' == )
    true
   ( Self .IsTypedef )
    RULES
     ( Self .IsPointer )
      false
     DEFAULT
      ( Self .MainAncestorPrim call.me )
    ; // RULES  
   DEFAULT
    false 
  ; // RULES 
 )  
 >>> Result
; // IsInterface

...

ModelElement elem_func DefaultAncestor
 Cached:
 (
  RULES
   ( Self .IsMixIn )
    nil
   ( Self .IsVCMFormSetFactory )
    GarantModel::TvcmFormSetFactory
   ( Self .IsVCMFormsPack )
    GarantModel::TvcmModule 
   ( Self .IsVCMContainer )
    GarantModel::TvcmContainerForm
   ( Self .IsVCMMainForm )
    GarantModel::TvcmMainForm
   ( Self .IsVCMDataModule )
    GarantModel::TDataModule
   ( Self .IsVCMCustomForm )
    GarantModel::TvcmEntityForm
   ( Self .Abstraction at_abstract == )
    nil
   ( Self .IsViewAreaController )
    GarantModel::IvcmViewAreaController
   ( Self .IsUseCaseController )
    GarantModel::IvcmUseCaseController
   DEFAULT
    nil
  ; // RULES
 ) 
 >>> Result
; // DefaultAncestor

...

ModelElement elem_func MainAncestor
 Cached:
 (
  RULES
   ( Self .IsPointer )
    ( Self .MainAncestorPrim )
   ( Self .IsTypedef )
    ( Self .MainAncestorPrim )
   ( Self .IsPureMixIn )
    ( Self .MainAncestorPrim )
   ( Self .IsInterface )
    (
     RULES
      (
       ( g_DefaultInterfaceAncestor IsNil ! )
       AND ( g_DefaultInterfaceAncestor Self != )
       AND ( Self .MainAncestorPrim IsNil )
      )
       g_DefaultInterfaceAncestor
      DEFAULT
       ( Self .MainAncestorPrim )
     ; // RULES 
    ) 
   DEFAULT
    ( Self .MainAncestorPrim )
  ; // RULES
   
  >>> Result
  
  RULES
   ( Result IsNil )
    ( Self .DefaultAncestor )
   DEFAULT
    Result 
  ; // RULES
 )
 >>> Result
; // MainAncestor

...

BOOLEAN elem_func IsRecord
 RULES
  ( Self .IsStereotype st_Struct )
   true
  ( Self .IsTypedef )
   RULES
    ( Self .IsPointer )
     false
    DEFAULT
     ( Self .MainAncestor call.me )
   ; // RULES  
  DEFAULT
   false 
 ; // RULES 
 >>> Result
; // IsRecord

...

BOOLEAN elem_func IsRecordOrUnion
 RULES
  ( Self .IsRecord )
   true
  ( Self .IsUnion )
   true
  DEFAULT
   false
 ; // RULES
 >>> Result
; // IsRecordOrUnion


Позже я напишу про это подробнее.

А также про "разорванные присваивания" и кеширование результатов выполнения.

вторник, 5 апреля 2016 г.

#1209. Идиотство. Узнаём - запущен ли процесс. "На батниках"

Узнаём - запущен ли процесс. "На батниках".

del hasgen.tmp
tasklist /FI "IMAGENAME eq callMSS.exe" /FO TABLE /NH >> hasgen.tmp
for /f %%i in (hasgen.tmp) do if /I %%i==callMSS.exe goto got

echo No gen running

goto exit

:got

echo Has gen running

:exit
del hasgen.tmp

Ну и как "должно быть":

https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms682623(v=vs.85).aspx
 

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <psapi.h>

// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
// and compile with -DPSAPI_VERSION=1

void PrintProcessNameAndID( DWORD processID )
{
    TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");

    // Get a handle to the process.

    HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
                                   PROCESS_VM_READ,
                                   FALSE, processID );

    // Get the process name.

    if (NULL != hProcess )
    {
        HMODULE hMod;
        DWORD cbNeeded;

        if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), 
             &cbNeeded) )
        {
            GetModuleBaseName( hProcess, hMod, szProcessName, 
                               sizeof(szProcessName)/sizeof(TCHAR) );
        }
    }

    // Print the process name and identifier.

    _tprintf( TEXT("%s  (PID: %u)\n"), szProcessName, processID );

    // Release the handle to the process.

    CloseHandle( hProcess );
}

int main( void )
{
    // Get the list of process identifiers.

    DWORD aProcesses[1024], cbNeeded, cProcesses;
    unsigned int i;

    if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
    {
        return 1;
    }


    // Calculate how many process identifiers were returned.

    cProcesses = cbNeeded / sizeof(DWORD);

    // Print the name and process identifier for each process.

    for ( i = 0; i < cProcesses; i++ )
    {
        if( aProcesses[i] != 0 )
        {
            PrintProcessNameAndID( aProcesses[i] );
        }
    }

    return 0;
}