Wiki

Clone wiki

MindStream / Articles in English / Example of what we can do with the described with the described model

Original in Russian
The previous series was here – Short example of what we can do with the described model.

Now let us extend the example:

https://bitbucket.org/lulinalex/mindstream/src/1993baa5f2b16ac3f3e1bca85658740b3df8eb60/Examples/Scripts/CodeGeneration/CodeGen39.ms.script?at=B284

#!delphi 
USES
 metaMACRO.ms.dict
;

Test CodeGen
 REMARK
  '
  CodeGen - function to test functionality
  '

 REMARK
  '
  %SUMMARY is meta information that allows binding the documentation to the code elements. Consequently, the documentation is available from the script engine.
  '
 %SUMMARY '
 'That is where we test meta-model building, model building and then code generation.
 '
 ; // %SUMMARY

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

meta-meta-model-begin
 'That is where we determine axiomatic of meta-meta model and extract it in a separate dictionary later.
 '

StereotypeStereotypeProducer meta
 %SUMMARY '
 Base element of meta-model determined
 This is the element that allows us to pull the rest by hair out of the swamp
 Other primitives are derived from this one
 '
 ; // %SUMMARY 
; // meta

meta-meta-model-end

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

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

meta-model-begin
 'That is where we determine axiomatic of meta model and then separate it
  in a dictionary.

  Next we will determine the UML concepts 
  https://en.wikipedia.org/wiki/Unified_Modeling_Language

  There are CATEGORIES and CLASSES in it

  Actually, they merely differ from each other, however, let it be so 
  for it was so decided by some wise men

Lets start with them:
  '
<<@meta>> UMLCategory
 %SUMMARY '
 Category on UML
 ' 
 ; // %SUMMARY 
; // UMLCategory

<<@meta>> UMLClass
 %SUMMARY '
 Class on UML
 ' 
 ; // %SUMMARY 
; // UMLClass

meta-model-end

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

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

concrete-model-begin 'Templates model'
 ' This is where we determine axiomatic of the specific model.
  For now lets determine axiomatic of template model
  We will extract it in a separate dictionary later.
 '

<<UMLCategory>> Project
 %SUMMARY '
 We probably bump into projects here and there when developing.
 The Project is a stereotype describing our projects.
 '
 ; // %SUMMARY
; // Project

<<UMLCategory>> Library
 %SUMMARY '
 We probably bump into design libraries here and there when developing.
 The Library is a stereotype describing our libraries.
 '
 ; // %SUMMARY
; // Library

<<UMLCategory>> Programm
 %SUMMARY '
 We probably bump into programs here and there when developing.
 The Program is a stereotype describing our programs.
 '
 ; // %SUMMARY
; // Programm

<<UMLClass>> Class
 %SUMMARY '
 We probably bump into design classes here and there when developing.
 The Class is a stereotype describing our design classes.
 '
 ; // %SUMMARY
; // Class

REMARK
 '
 Some time later, when we start to use these we will find out whether
 the Library can be embedded in Project and, vise versa, the Project embedded
 in the Library or whether the Program can be embedded in the Class and, vise
 versa, the Class embedded in the Library as well as other relations between stereotypes.
 '

model-end

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

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

concrete-model-begin 'Model of the specific project'
 ' This is where we determine axiomatic of the specific model of the specific project.
  We will extract it in a separate dictionary later.
 '
<<Project>> Project1
 %SUMMARY '
 This is our first project - Project1
 '
 ; // %SUMMARY

 <<Library>> Library1
  %SUMMARY '
  Probably, there are design libraries in our project.
  The Library1 is our first design library.
  '
  ; // %SUMMARY
 ; // Library1

 <<Library>> Library2
  %SUMMARY '
  Our project is probably serious enough and has MORE THAN ONE library.
  The Library2 is our second design library.
  '
  ; // %SUMMARY
 ; // Library2

 <<Library>> Library3
  %SUMMARY '
  Our project is probably SO serious that it has even MORE THAN TWO libraries.
  The Library3 is our third design library.
  '
  ; // %SUMMARY
 ; // Library3

 <<Programm>> Programm1
  %SUMMARY '
  Our project probably implements some program.
  Otherwise, why would we need it?
  The Program1 is a program in our Project1.
  '
  ; // %SUMMARY

  <<Class>> Class1
   %SUMMARY '
  Our program probably has some implementation classes.
  Otherwise, how would we implement our functionality?
  The Class1 is our FIRST implementation class in our Program1.
   '
   ; // %SUMMARY
  ; // Class1

  <<Class>> Class2
   %SUMMARY '
   Our program probably is serious enough and has MORE THAN ONE implementation class.
  The Class2 is our second implementation class in Program1.
   '
   ; // %SUMMARY
  ; // Class2

 ; // Programm1

; // Project1

REMARK
 '
  These words should probably be based on requirements specification and UseCase.
  Well, we will talk it over later. 
 '  
model-end

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

USES
 CodeDump.ms.dict
 // - the CodeDump.ms.dict is loaded so we can “see” the DumpElement word
;

@SELF DumpElement
REMARK
 '
 - the CodeGen element and its contents are dumped in a standard output devise.
   We only do it to debug what weve written.
 '

help
REMARK
 '
 The available axiomatic is output to a standard output device.
 We only do it to debug what weve written.
 '

REMARK
 '
 Now, what can we do with our project?
 To begin with, let us output its name to a standard device.
 '

TtfwWord TYPE ModelElement
REMARK 'Model element'

BOOLEAN FUNCTION IsSummary
 ModelElement IN aWord
 %SUMMARY 
 '
  Defines aWord as the documentation for the element
 '
 ; // %SUMMARY
 ( aWord |N ) = '%SUM' >>> Result
; // IsSummary

BOOLEAN FUNCTION IsModelElement
 ModelElement IN aWord
 %SUMMARY 
 '
  Defines aWord as the element of the model
 '
 ; // %SUMMARY
 aWord IsSummary ! >>> Result
; // IsModelElement

ARRAY FUNCTION Children
 ModelElement IN aWord
 %SUMMARY 
 '
 Returns child iterator aWord in terms of the specific model
 '
 ;
 ( aWord MembersIterator ) >filter> IsModelElement >>> Result
; // Children

INTEGER VAR g_Indent
REMARK 'Current indent'
g_Indent := 0

BOOLEAN FUNCTION IsElementNeedIndent
 ModelElement IN anElement
 %SUMMARY 'Defines that the indent is needed' ;
 true >>> Result
; // IsElementNeedIndent

PROCEDURE EnterElement
 ModelElement IN anElement
 %SUMMARY 'Begins element output' ;
 anElement IsElementNeedIndent ? INC g_Indent
; // EnterElement

PROCEDURE LeaveElement
 ModelElement IN anElement
 %SUMMARY 'Ends element output' ;
 anElement IsElementNeedIndent ? DEC g_Indent
; // LeaveElement

FILE VAR g_OutFile
g_OutFile := nil

PROCEDURE OutToFile
 STRING IN aString 
 %SUMMARY 
 '
 Outputs the value to the current output file and returns the carriage.
 '
 ; // %SUMMARY 
 [ g_Indent ' ' char:Dupe aString ] strings:Cat g_OutFile File:WriteLn
 REMARK '- outputs models elements to file instead of a standard device.'
; //OutToFile

FORWARD DumpModelElement
REMARK 'FORWARD DumpModelElement is used to call DumpModelElement recursively'

PROCEDURE DumpModelElement
 ModelElement IN aWord
 %SUMMARY 
 '
 Printing procedure for model element content, recursively.
 '
 ; // %SUMMARY
 aWord |S OutToFile
 REMARK 'Prints out the stereotype of the element'
 aWord |N OutToFile
 REMARK 'Prints out the element name'
 TRY
  for ( aWord Children ) (
   REMARK 'Outputs the elements children'
   ModelElement IN aWord
   aWord EnterElement 
   TRY
    aWord DumpModelElement
    REMARK 'Calls itself recursively'
   FINALLY
    aWord LeaveElement 
   END
  )
 FINALLY
  '; // ' (+) ( aWord |N ) OutToFile
  REMARK 'Prints the closing bracket of the element'
 END
; // DumpModelElement

STRING FUNCTION OutFileName
 %SUMMARY 'File name for output' ;
 script:FileName sysutils:ExtractFileName (+) '.dump' >>> Result
; // OutFileName

g_OutFile := ( OutFileName File:OpenWrite )
TRY
 @ Project1 DumpModelElement
 REMARK 'File name for output'
FINALLY
 g_OutFile := nil
END

OutFileName Print
REMARK 'Prints script file name for test'

; // CodeGen

CodeGen

Updated