dml

2018-10-18

Introduction

Diagram Make Language for Common Lisp.You can look DML as Domain Specific Language for drawing UML.

??????????????????

Install

DML is added to quicklisp, quicklisp automatically download it to local disk on the first loading.

(ql:quickload :dml)

Quick start by examples

To run examples, load dml system and change current package to 'dml'.

(ql:quickload :dml)
(use-package :dml) ;; or (in-package :dml)

Quick Start for Sequence Diagram

Call macro dml-create-sequence to create a sequnce diagram:

(dml-create-sequence "<diagram name>" (<attribute>...) <messages>

A synchronous message & retrun in a formated string :

"==><object name>.<message label>/<return label>"

A asynchronous message in a formated string:

"--><object name>.<message label>"

A new message in a fromated string :

"n-><object name>.<mesasge label>"

Any object name begin with '!' is a active object, that has a active bar at beginning.

A sequence list of messages in macro '&prog'

(&prog <message 1> <message 2> <message 3> ...)

A message with follwing sub-messages in mcaro '&chain'

(&chain <message> <sub-message> <sub-sub-message> ...)

A optional/alternative frame with guard condtion and messages in macro '&if'

(&if "<guard label(condtion)>" <then-message> [<else-message>]) 

A loop frame with guard and message in macro '&loop'

(&loop "<gurad label(conditon)>" <message in loop> )

Any macro ('&prog' ,'&chain', '&opt', '&if' and '&loop') return a messages, so it can be nested in each other

Evaluate follwing expression:

(dml-create-sequence "legend" ()
  (&prog "==>ObjectA.SyncMsg1()/ret1" 
         (&chain "==>ObjectA.SyncMsg2()/ret2"
                 "==>ObjectB.SyncMsg2.1()/ret2.1"
                 "-->!ActiveObjectC.AsyMesg2.2()")))

Wil output image(legend.ps and legend.png):

Evaluate Expression:

(dml-create-sequence "nested" ()
  (&chain "==>aComputer.play()/"
          (&prog (&chain "==>emacs.run()/"
                         "==>slime.load()/")
                 (&chain "==>slime.Hacking()/"
                         (&chain "==>slime.LookupHyperSpec()"
                                 (&prog "==>chrome:Explorer.Start()/"
                                        "==>chrome:Explorer.OpenSpec()/"))))))

Output image:

Evalate Expression:

(dml-create-sequence "control" ()
  (&chain "==>:PersonFile.LoadAllGoodMan()/"
          (&loop "[ hasNext ]"
                 (&prog "==>:PersonFile.readNext()/"
                        (&if "[ Is Good Man ]"
                             (&prog "n=>aManObj.new"
                                    "==>manPool.register()/"))))))

Output image:

Quick Start for Graph Diargam

Call macro dml-create-graph to create a graph diagram:

(dml-create-graph "<diagram name>" (<attribute>...) <node or edge>

Define nodes by call functions (node type as function name).:'full-class', 'simp-class', 'actor', 'pack', 'ucas', 'comp'

(<node type>  <node name>  [options])
  1. Define Graph by edges that linked nodes, define edges by functions (edge type as function name): '-dep-', '-com-', '-agg-', '-gen-by-'.

    (-<edge type>- <src node> <dest node>) ; link one-to-one
    (-<edge type>-* <src node> <dest node 1> <dest node 2> ...); link one-to-manny
    (-<edge type>-- <1st node> <2nd node> <3rd node> ...); link one-by-one
    
  2. Reference Predefined node by name '@name'.

    (@name <node name>)
    

Evaluate expression:

(dml-create-graph "dml-component" (:rankdir :LR)
  (-dep-- "use"
          (comp "DML")
          (comp "donuts")
          (comp "Graphviz")))

Output image:

Evalate expression:

(dml-create-graph "os-class" ()
  (with-method ("+ play () : Love" "+ work () : Hate")
    (-genby-*
     (full-class "OS"
                 "abstract"
                 (attributes "- name : String"
                             "- born : Date"))
     (full-class "Linux")
     (full-class "Android")
     (full-class "Apple")
     (full-class "Windows"))
    (-dep- "from"
           (@name "Android")
           (@name"Linux"))))

Output Image:

Evaluate expression:

(dml-create-graph "coder-case" (:rankdir :LR)
  (-point-* 
       (actor "coder")
       (ucas "Use Emacs")
       (ucas "Programing")
       (ucas "Play game"))
  (-dep- "extend"
         (@name "Programing")
         (@name "Use Emacs")))

lisp

Output image:

Evaluate expression:

(dml-create-graph "dom" ()
  (with-method ("+ calcPrice(): BigDecimal"
                "+ toJson(): String"
                "+ getValue(name:String) : Object")
    (-genby-* (full-class "TreeNode"
                          "Abstract"
                          nil
                          (methods "+ getParent(): TreeNode"
                                   "+ addChild(:TreeNode)"))
              (full-class "PriceCache" "Decorator"
                          (attributes "- theNode : TreeNode"))
              (full-class "Case")
              (full-class "Plan")
              (full-class "Categorization"
                          nil
                          (attributes "- fromAge : integer"
                                      "- toAge : integer"
                                      "- isSheBao : boolean"
                                      "- count : integer"))))
  (-dep- "Create"
         (full-class "CaseBuilder"
                     "Factory"
                     nil (methods "+ parseJson(: String) : Case"))                                  
         (@name "Case"))
  (-agg- (@name "TreeNode")
         (@name "TreeNode"))
  (-com- (@name "PriceCache")
         (@name "TreeNode"))
  (-com- (@name "Case")
         (@name "Plan"))
  (-com- (@name "Plan")
         (@name "Categorization"))  
  (-dep- "Usage"
         (@name "Categorization")
         (full-class "Calculator"
                     "Utility"
                     nil
                     (methods "+ calc(arg : TreeNode) : BigDecimal"
                              "- log2db() :")))

  (with-method ("+ loadFromdb()"
                "+ lookUp()")
    (-com- (@name "Calculator")
           (full-class "ArgumentTable"))
    (-dep- "Call"
           (@name "Calculator")
           (@name "TreeNode"))  
    (-genby-* (@name "ArgumentTable")
              (full-class "ByAgeScope")
              (full-class "ByAge")
              (full-class "ByID"))
    (-dep- "Usage" (@name "ArgumentTable")
           (pack "JDBC"))))

Output image:

Reference

Symbol for Sequence Diagram

Symbol name Type Description
dml-create-sequnce Macro Dump sequnce diagram to ps and png file
&prog Macro Define sequnce calls
&chain Macro Define a call with sub calls
&if Macro Define two alternative calls with a guard condition
&loop Macro Defile a call in a loop with a guard condition

Symbol for Graph Diagram

Symbol name Type Description
dml-create-graph Macro Dump graph diagram to ps and png file.
full-class Function (node type) Create a class node whih attributes and methods.
attributes, methods Function Define attribute/method list for the full-calss
simp-class Function (node type) Return a class node with a simple name in the box.
with-method Macro Create to define share methods for classes.
actor Function (node type) Create a stick man as actor.
pack Function (node type) Create a package node.
ucas Function (node type) Create use case node.
comp Function (node type) Create component node
@name Function Reference pre-defined node by name
-point-, -point-* Function (edge type) Define a arrow edge: 1-to-1, 1-to-n
-dep-, -dep-*, -dep-- Function (edge type) Define dependcy edge: 1-to-1, 1-to-n, 1-by-1
-com-, com-* Function (edge type) Define composition edge: 1-to-1, 1-to-n
-agg-, -agg-* Function (edge type) Define a aggregation edge: 1-to-1, 1-to-n
-genby-,genby-* Function (edge type) Define generalize edge: 1-to-1, 1-to-n
Author
cuic@chianre.com.cn
License
MIT License