четверг, 27 августа 2015 г.

#1129. Кодогенерация. Вынесем почти всё во внешние словари

Предыдущая серия была тут - Кодогенерация. Выводим каждый дочерний элемент в свой файл.

Вынесем почти всё, что касается мета-модели во внешние словари.

Оставим только то, что относится к конкретной модели и её генерации.

Вот что получается:

https://bitbucket.org/lulinalex/mindstream/src/ebbf27e8918717c982d0b756118a081620155d71/Examples/Scripts/CodeGeneration/CodeGen67.ms.script?at=B284

USES
 metaMACRO.ms.dict
 classRelations.ms.dict
 EngineTypes.ms.dict
 Object.ms.dict
;

Test CodeGen
 %REMARK
  '
  CodeGen - это функция в которой мы будем тестировать наш функционал
  '

 %REMARK
  '
  %SUMMARY это мета-информация, которая позволяет привязывать документацию
  к элементам кода. Эта документация доступна потом из скриптовой машины.
  '
 %SUMMARY '
 Тут будем тестировать построение сначала мета-модели, потом модели, а потом и
 кодогенерации
 '
 ; // %SUMMARY

USES
 Templates.ms.model
;

// ---------------------------------------------------------------------------

concrete-model-begin 'Модель конкретного проекта Project1'
 'Тут будем определять аксиоматику конкретной модели конкретного проекта.
  А потом вынесем её 
  в отдельный словарь.
 '
<<Project>> Project1
 %SUMMARY '
 Это наш первый проект - Project1
 '
 ; // %SUMMARY

 <<Library>> Library1
  %SUMMARY '
  Наверное наш проект содержит какие-то проектные библиотеки.
  Так вот Library1 - это наша первая проектная библиотека
  '
  ; // %SUMMARY
 ; // Library1

 <<Library>> Library2
  %SUMMARY '
  Наверное наш проект достаточно серьёзен и содержит НЕ ОДНУ библиотеку.
  Так вот Library2 - это наша вторая проектная библиотека.
  '
  ; // %SUMMARY
 ; // Library2

 <<Library>> Library3
  %SUMMARY '
  Наверное наш проект НАСТОЛЬКО серьёзен, что содержит даже НЕ ДВЕ библиотеки.
  Так вот Library3 - это наша третья проектная библиотека.
  '
  ; // %SUMMARY
 ; // Library3

 <<Program>> Program1
  %SUMMARY '
  Наверное наш проект реализует какую-то программу.
  Иначе - зачем бы он нам был бы нужен?
  Так вот Program1 - это программа внутри нашего проекта Project1.
  '
  ; // %SUMMARY

  <<Class>> Class1
   %SUMMARY '
   Наверное наша программа содержит какие-то классы реализации.
   Иначе - кто будет реализовывать наш функционал?
   Так вот Class1 - это наш ПЕРВЫЙ класс реализации внутри нашей программы Program1.
   '
   ; // %SUMMARY
  ; // Class1

  <<Interface>> Interface1
   %SUMMARY '
   Наверное наша программа настолько серьёзна, что реализует какие-то интерфейсы.
   Так вот Interface1 - это наш ПЕРВЫЙ интерфейс.
   '
   ; // %SUMMARY
  ; // Interface1

  <<Interface>> Interface2
   %SUMMARY '
   Наверное наша программа настолько серьёзна, что реализует НЕ ОДИН интерфейс, а несколько.
   Так вот Interface2 - это наш ВТОРОЙ интерфейс.
   '
   ; // %SUMMARY
  ; // Interface2

  <<Class>> Class2
   %SUMMARY '
   Наверное наша программа достаточно серьёзна и содержит НЕ ОДИН классы реализации.
   Так вот Class2 - это наш ВТОРОЙ класс реализации внутри нашей программы Program1.
   '
   ; // %SUMMARY
   %INHERITS
    Addr Class1
    %REMARK 'Возможно наш проектный класс Class2 наследуется от класса Class1'
   ; // %INHERITS
   %IMPLEMENTS
    Addr Interface1
    %REMARK 'Возможно наш проектный класс Class2 реализует интерфейс Interface1'
    Addr Interface2
    %REMARK 'Возможно наш проектный класс Class2 реализует ещё и интерфейс Interface2'
   ; // %IMPLEMENTS
  ; // Class2

  <<Class>> Class3
   %SUMMARY '
   Возможно, что у нас такая непростая программа, что в ней даже больше, чем ДВА класса реализации.
   Так вот Class3 - это наш ТРЕТИЙ класс реализации внутри нашей программы Program1.
   '
   ; // %SUMMARY
  ; // Class3

  <<Class>> Class4
   %SUMMARY '
   Возможно, что мы настолько офигенно круты, что у на даже НЕ ТРИ класса реализации.
   Так вот Class4 - это наш ЧЕТВЁРТЫЙ класс реализации внутри нашей программы Program1.
   '
   ; // %SUMMARY
   %INHERITS
    Addr Class2
    Addr Class3
    %REMARK 
     '
     Возможно, что мы нстолько ОФИГЕННЫЕ перцы, что используем МНОЖЕСТВЕННОЕ наследование.
     И даже ПОНИМАЕМ - ЗАЧЕМ это нужно.
     Так вот Class4 - наследуется от Class2 и Class3.  
     '
   ; // %INHERITS
  ; // Class4

 ; // Program1

; // Project1

%REMARK
 '
  РЕМАРКА.
  Все эти слова "наверное" вообще говоря должны проистекать из требований, ТЗ и UseCase
  Но мы про это позже поговорим.
 '  
model-end

// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------

concrete-model-begin 'Модель конкретного проекта Project2'
 'Тут будем определять аксиоматику конкретной модели конкретного проекта.
  А потом вынесем её 
  в отдельный словарь.
 '
<<Project>> Project2
 %SUMMARY '
 Это наш ВТОРОЙ проект - Project2
 '
 ; // %SUMMARY
; // Project2
model-end

// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------

concrete-model-begin 'Модель конкретного проекта Project3'
 'Тут будем определять аксиоматику конкретной модели конкретного проекта.
  А потом вынесем её 
  в отдельный словарь.
 '
<<Project>> Project3
 %SUMMARY '
 Это наш ТРЕТИЙ проект - Project3
 '
 ; // %SUMMARY
; // Project3
model-end

// ---------------------------------------------------------------------------

USES
 CodeDump.ms.dict
 // - тут подключаем словарь CodeDump.ms.dict, чтобы "увидеть" слово DumpElement
;

this.method.addr DumpElement
%REMARK
 '
 - тут дампим элемент CodeGen и его содержимое
   в стандартное устройство вывода.
   Чисто для отладки того, что мы сейчас написали.
 '

help
%REMARK
 '
 Выводим всю доступную аксиоматику в стандартное устройство вывода.
 Чисто для отладки того, что мы сейчас написали.
 '

USES
 Generation.ms.dict
;

elem_proc DumpAsIs
 %SUMMARY 'Процедура печатающая содержимое элемента модели. Рекурсивно.' ;

 [
  g_CurrentGeneratorName ':'
   %REMARK 'Выводим имя текущего генератора. Для отладки' 
  for ( Self LIST %ST Reverted ) .Name
   %REMARK 'Выводим стереотип элемента, рекурсивно'
  Self .Name 
   %REMARK 'Выводим имя элемента'
 ] ' ' strings:CatSep OutToFile
 [
  'Родители элемента '
  for ( Self .Parents >reverted> ) .Name
  %REMARK 'Выводим родителей элемента, рекурсивно'
 ] '::' strings:CatSep OutToFile
 for ( Self .Inherited ) ( .Name OutToFile )
 for ( Self .Implements ) ( .Name OutToFile )
 TRY
  Self .CallChildrenCurrentGen
  %REMARK 'Выводим детей элемента, тем же самым генератором'
 FINALLY
  [ '; // ' Self .Name ] OutToFile
  %REMARK 'Выводим закрывающую скобку элемента'
 END
; // DumpAsIs

elem_generator dump
 %SUMMARY 'Генератор выводящий дамп элемента модели.' ;
 %GEN_PROPERTY Name 'dump'
 %REMARK 'Имя генератора и расширение файла целевого языка. Потом мы сделаем так, чтобы они могли не совпадать'

 Self .DumpAsIs
 %REMARK 'Пока выводим всё "как есть", без трансформации в целевой язык'
; // dump

elem_generator pas
 %SUMMARY 'Генератор выводящий элементы модели в Паскаль.' ;
 %GEN_PROPERTY Name 'pas'
 %REMARK 'Имя генератора и расширение файла целевого языка. Потом мы сделаем так, чтобы они могли не совпадать'

 Self .DumpAsIs
 %REMARK 'Пока выводим всё "как есть", без трансформации в целевой язык'
; // pas

elem_generator script
 %SUMMARY 'Генератор выводящий элементы модели в ms.script.' ;
 %GEN_PROPERTY Name 'ms.script'
 %REMARK 'Имя генератора и расширение файла целевого языка. Потом мы сделаем так, чтобы они могли не совпадать'

 Self .DumpAsIs
 %REMARK 'Пока выводим всё "как есть", без трансформации в целевой язык'
; // script

elem_generator c++
 %SUMMARY '
 Генератор выводящий элементы модели в c++. 
 Про файлы *.h мы потом поговорим отдельно.
 ' ;
 %GEN_PROPERTY Name 'cpp'
 %REMARK 'Имя генератора и расширение файла целевого языка. Потом мы сделаем так, чтобы они могли не совпадать'

 Self .DumpAsIs
 %REMARK 'Пока выводим всё "как есть", без трансформации в целевой язык'
; // c++

elem_generator h
 %SUMMARY '
 Генератор выводящий элементы модели в *.h. 
 Про файлы *.h мы потом поговорим отдельно.
 ' ;
 %GEN_PROPERTY Name 'h'
 %REMARK 'Имя генератора и расширение файла целевого языка. Потом мы сделаем так, чтобы они могли не совпадать'

 Self .DumpAsIs
 %REMARK 'Пока выводим всё "как есть", без трансформации в целевой язык'
; // h

( Project1 Project2 Project3 )
%REMARK 'Список всех наших корневых элементов (проектов)'
 ( .dump .pas .c++ .h .script )
 %REMARK 'Список всех наших генераторов' 
  CallGensList
  %REMARK '- запускаем список генераторов на списке "рутовых элементов" модели.'

; // CodeGen

CodeGen

Комментариев нет:

Отправить комментарий