Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Corrected a problem in micca with the embedded command, findRelatedWhere. The previous implementation failed to account for singular relationships and assumed there was always an iterative loop. Added test cases to demonstrate the fix. Preparing for new micca release. |
---|---|
Timelines: | family | ancestors | descendants | both | micca-develop |
Files: | files | file ages | folders |
SHA1: |
07d00e9b7cf6218f842c0ee3d648641f |
User & Date: | andrewm 2019-12-15 17:29:08 |
Context
2019-12-18
| ||
16:35 | Build of micca 1.1.7 for Linux. Preparing for new release. check-in: 3c2e02bd45 user: andrewm tags: micca-develop | |
2019-12-15
| ||
17:29 | Corrected a problem in micca with the embedded command, findRelatedWhere. The previous implementation failed to account for singular relationships and assumed there was always an iterative loop. Added test cases to demonstrate the fix. Preparing for new micca release. check-in: 07d00e9b7c user: andrewm tags: micca-develop | |
2019-06-16
| ||
17:20 | Build of micca 1.1.6 for macosx. Preparing for release. check-in: 90aaa1a63b user: andrewm tags: micca-develop | |
Changes
Changes to micca/code/tcl/teapot.txt.
1 2 3 4 5 6 7 8 |
Package micca 1.1.6
Meta category Model Translation
Meta description The micca package is an XUML translation scheme written
Meta description in Tcl.
Meta entrysource micca.tcl
Meta included micca.tcl typename/typeparser.tcl
Meta platform tcl
Meta require logger
|
| |
1 2 3 4 5 6 7 8 |
Package micca 1.1.7
Meta category Model Translation
Meta description The micca package is an XUML translation scheme written
Meta description in Tcl.
Meta entrysource micca.tcl
Meta included micca.tcl typename/typeparser.tcl
Meta platform tcl
Meta require logger
|
Changes to micca/doc/micca/config.man.
1 2 3 4 5 6 7 8 |
[vset version 1.1.6]
[manpage_begin micca-DSL n [vset version]]
[comment {
# This software is copyrighted 2015 - 2019 by G. Andrew Mangogna.
# The following terms apply to all files associated with the software unless
# explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
|
| |
1 2 3 4 5 6 7 8 |
[vset version 1.1.7]
[manpage_begin micca-DSL n [vset version]]
[comment {
# This software is copyrighted 2015 - 2019 by G. Andrew Mangogna.
# The following terms apply to all files associated with the software unless
# explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
|
Changes to micca/doc/micca/embedded.man.
1 2 3 4 5 6 7 8 |
[vset version 1.1.6]
[manpage_begin micca-Embedded n [vset version]]
[comment {
# This software is copyrighted 2015 - 2019 by G. Andrew Mangogna.
# The following terms apply to all files associated with the software unless
# explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
|
| |
1 2 3 4 5 6 7 8 |
[vset version 1.1.7]
[manpage_begin micca-Embedded n [vset version]]
[comment {
# This software is copyrighted 2015 - 2019 by G. Andrew Mangogna.
# The following terms apply to all files associated with the software unless
# explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
|
Changes to micca/doc/micca/micca.man.
1 2 3 4 5 6 7 8 |
[vset version 1.1.6]
[manpage_begin micca 1 [vset version]]
[comment {
# This software is copyrighted 2015 - 2019 by G. Andrew Mangogna.
# The following terms apply to all files associated with the software unless
# explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
|
| |
1 2 3 4 5 6 7 8 |
[vset version 1.1.7]
[manpage_begin micca 1 [vset version]]
[comment {
# This software is copyrighted 2015 - 2019 by G. Andrew Mangogna.
# The following terms apply to all files associated with the software unless
# explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
|
Changes to micca/doc/micca/portal.man.
1 2 3 4 5 6 7 8 |
[vset version 1.1.6]
[manpage_begin portal 3 [vset version]]
[comment {
# This software is copyrighted 2015 - 2019 by G. Andrew Mangogna.
# The following terms apply to all files associated with the software unless
# explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
|
| |
1 2 3 4 5 6 7 8 |
[vset version 1.1.7]
[manpage_begin portal 3 [vset version]]
[comment {
# This software is copyrighted 2015 - 2019 by G. Andrew Mangogna.
# The following terms apply to all files associated with the software unless
# explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
|
Changes to micca/src/Makefile.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
DOCDIR = ../doc TESTDIR = ../tests PKGDIR = ../../packages MODULEDIR = ../../modules IMAGEDIR = ./images CODEDIR = ../code VERSION=1.1.6 vpath %.pdf $(DOCDIR) vpath %.html $(DOCDIR) vpath %.test $(TESTDIR) vpath %.uxf $(IMAGEDIR) DOCSRC =\ ................................................................................ $(CODEDIR)/tcl/micca_main.tcl : $(DOCSRC) $(DOCPARTS) atangle $(ATANGLEOPTS) -root $(notdir $@) -output $@ $(DOCSRC) $(DOCDIR)/%.pdf : %.aweb a2x $(A2XOPTS) --doctype=book --format=pdf\ --destination-dir=$(DOCDIR)\ $(ASCIIDOC_OPTS) $(DBLATEX_OPTS) $< $(RM) $(DOCDIR)/*__[0-9].pdf %.test : %.aweb atangle $(ATANGLEOPTS) -root $(notdir $@) -output $(TESTDIR)/$@ $< $(IMAGEDIR)/platform-%.pdf : platform-%.uxf umlet -action=convert -format=pdf\ -filename=$< -output=$(basename $@)-cvt pdftk $(basename $@)-cvt.pdf cat 1left output $@ $(RM) $(basename $@)-cvt.pdf $(IMAGEDIR)/%-translation.pdf : %-translation.uxf umlet -action=convert -format=pdf\ -filename=$< -output=$(basename $@)-cvt pdftk $(basename $@)-cvt.pdf cat 1left output $@ $(RM) $(basename $@)-cvt.pdf $(IMAGEDIR)/%.pdf : %.uxf umlet -action=convert -format=pdf\ -filename=$< -output=$(basename $@) $(MANSRC) : $(DOCSRC) atangle $(ATANGLEOPTS) -root $(notdir $@) -output $@ $< |
|
|
>
>
|
|
|
>
>
|
|
|
|
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
DOCDIR = ../doc TESTDIR = ../tests PKGDIR = ../../packages MODULEDIR = ../../modules IMAGEDIR = ./images CODEDIR = ../code VERSION=1.1.7 vpath %.pdf $(DOCDIR) vpath %.html $(DOCDIR) vpath %.test $(TESTDIR) vpath %.uxf $(IMAGEDIR) DOCSRC =\ ................................................................................ $(CODEDIR)/tcl/micca_main.tcl : $(DOCSRC) $(DOCPARTS) atangle $(ATANGLEOPTS) -root $(notdir $@) -output $@ $(DOCSRC) $(DOCDIR)/%.pdf : %.aweb a2x $(A2XOPTS) --doctype=book --format=pdf\ --destination-dir=$(DOCDIR)\ $(ASCIIDOC_OPTS) $(DBLATEX_OPTS) $< $(RM) $(DOCDIR)/*__[0-9].* %.test : %.aweb atangle $(ATANGLEOPTS) -root $(notdir $@) -output $(TESTDIR)/$@ $< $(IMAGEDIR)/platform-%.pdf : platform-%.uxf umlet -action=convert -format=pdf\ -filename=$< -output=$(basename $@) #umlet -action=convert -format=pdf\ # -filename=$< -output=$(basename $@)-cvt #pdftk $(basename $@)-cvt.pdf cat 1left output $@ #$(RM) $(basename $@)-cvt.pdf $(IMAGEDIR)/%-translation.pdf : %-translation.uxf umlet -action=convert -format=pdf\ -filename=$< -output=$(basename $@) #umlet -action=convert -format=pdf\ # -filename=$< -output=$(basename $@)-cvt #pdftk $(basename $@)-cvt.pdf cat 1left output $@ #$(RM) $(basename $@)-cvt.pdf $(IMAGEDIR)/%.pdf : %.uxf umlet -action=convert -format=pdf\ -filename=$< -output=$(basename $@) $(MANSRC) : $(DOCSRC) atangle $(ATANGLEOPTS) -root $(notdir $@) -output $@ $< |
Changes to micca/src/codeorg.txt.
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
# terms specified in this license. ---- === Version Information ---- <<version info>>= Micca version: 1.1.6 ---- === Edit Warning ---- <<edit warning>>= # DO NOT EDIT THIS FILE! ................................................................................ domain micca { <<micca configuration>> } } rosea generate micca namespace eval ::micca { variable version 1.1.6 <<logger setup>> <<tclral imports>> namespace import ::ral::relvar <<micca constraints>> |
|
|
|
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
# terms specified in this license. ---- === Version Information ---- <<version info>>= Micca version: 1.1.7 ---- === Edit Warning ---- <<edit warning>>= # DO NOT EDIT THIS FILE! ................................................................................ domain micca { <<micca configuration>> } } rosea generate micca namespace eval ::micca { variable version 1.1.7 <<logger setup>> <<tclral imports>> namespace import ::ral::relvar <<micca constraints>> |
Changes to micca/src/example.txt.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
with those considerations here to focus on how the model is
translated into the implementation code using `micca`.
=== Translation Overview
To translate an XUML model using `micca`,
the model is encoded in a domain specific language.
You may draw the model in your favorite tool.
This example was done using http://www.umlet.com[UMLet]
as a drawing tool.
For this translation, we choose to keep the domain description
in one file and an initial instance population in another file.
This is a common way to be able to provide several different populations
to the same domain,
an important consideration for testing and deployment.
In the file for the domain,
we use the `domain` command to specify the details of the model.
[source,tcl]
----
<<wmctrl.micca>>=
|
| | |
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
with those considerations here to focus on how the model is translated into the implementation code using `micca`. === Translation Overview To translate an XUML model using `micca`, the model is encoded in a domain specific language. You may draw the model with your favorite UML drawing tool. This example was done using http://www.umlet.com[UMLet] as a drawing tool. For this translation, we choose to keep the domain description in one file and an initial instance population in another file. This is a common way to be able to provide several different populations to the same domain, an important consideration for keeping testing and deployment separate. In the file for the domain, we use the `domain` command to specify the details of the model. [source,tcl] ---- <<wmctrl.micca>>= |
Changes to micca/src/generate.txt.
6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 .... 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 .... 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 .... 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 .... 9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 .... 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 |
The counter is reset back to zero after each activity's code is generated in order to have consistent symbol names in the generated code. [source,tcl] ---- <<generation support data>>= variable symcounter 0 ---- Looking up a symbol returns a dictionary of the symbol attributes. [source,tcl] ---- <<generation support commands>>= ................................................................................ } proc CreateTempSymbol {args} { set name [CreateTempSymbolName] InsertSymbol Name $name {*}$args return $name } ---- Again, we specialize the creation procedure for the variable types commonly used in code generation. [source,tcl] ---- ................................................................................ string map [list \" {}] ~ | join ~ }] ; # <1> return "#error \"$msg\"\n" ; <2> } finally { relvar set Symbol [relation emptyof [relvar set Symbol]] variable symcounter 0 } } ---- <1> Preparing a message suitable for `#error` from the error result. <2> We place a `#error` statement in the code to make sure it will not compile. ................................................................................ [source,tcl] ---- <<generation support commands>>= proc InstanceFindRelatedWhere {startref instref where args} { set startlevel [GetBlock] set where [string trim $where] set endref [CreateTempSymbolName] set chaincode [TraverseRelChain $startref $endref $args] set endsym [LookUpSymbol $endref] append chaincode [IndentToBlock [string cat\ "$instref = $endref ;\n"\ "if ($where) \{\n"\ ]] PushBlock append chaincode [IndentToBlock "break ;\n"] PopBlock append chaincode [IndentToBlock "\} else \{\n"] PushBlock append chaincode [IndentToBlock "$instref = NULL ;\n"] set depth [expr {[GetBlock] - $startlevel}] for {set i 0} {$i < $depth} {incr i} { PopBlock append chaincode [IndentToBlock "\}\n"] } set result [IndentToBlock [string cat\ [linecomment "instance $startref findRelatedWhere\ $instref [list [string trim $where]] $args"]\ [CreateInstRefSymbol [dict get $endsym Class] $instref]\ "$instref = NULL ;\n"\ ]] return [append result $chaincode] } ---- ifdef::showtests[] [source,tcl] ---- <<generate command tests>>= test codegen-63.0 { Generated code file to select related instance ................................................................................ t__T2 = t__T2->next ; struct Z *t__T4 = t__T3->R2__BACK ; // ~R2 if (t__T4 != NULL) { struct Z *t__T1 ; t__T1 = t__T4 ; zref = t__T1 ; if (zref->pressure == 42) { break ; } else { zref = NULL ; } } } } } -result {1} ---- endif::showtests[] ==== Finding a Single Related Instance ................................................................................ mrt_InstSetInitialize(&zset, &codegen48__CLASSES[2]) ; for (MRT_LinkRef *t__T2 = mrtLinkRefBegin(&xref->R1__BACK) ; t__T2 != mrtLinkRefEnd(&xref->R1__BACK) ;) { struct Y *t__T3 = (struct Y *)((uintptr_t)t__T2 - offsetof(struct Y, R1__BLINKS)) ; t__T2 = t__T2->next ; struct Z *t__T4 = t__T3->R2__BACK ; // ~R2 if (t__T4 != NULL) { struct Z *t__T1 ; t__T1 = t__T4 ; mrt_InstSetAddInstance(&zset, t__T1) ; } } }]} } -result {1} ---- |
> > > > > > > > | > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 .... 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 .... 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 .... 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 9212 .... 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 9311 9312 9313 9314 9315 9316 9317 9318 9319 9320 9321 9322 9323 9324 9325 9326 9327 9328 9329 9330 9331 9332 9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 9380 9381 9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416 9417 9418 9419 9420 9421 9422 9423 9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 .... 9707 9708 9709 9710 9711 9712 9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752 9753 9754 9755 9756 9757 9758 9759 9760 9761 9762 9763 9764 9765 9766 9767 9768 9769 9770 9771 9772 9773 9774 9775 9776 9777 9778 9779 9780 9781 9782 9783 9784 9785 |
The counter is reset back to zero after each activity's code is generated in order to have consistent symbol names in the generated code. [source,tcl] ---- <<generation support data>>= variable symcounter 0 variable labelcounter 0 ---- Looking up a symbol returns a dictionary of the symbol attributes. [source,tcl] ---- <<generation support commands>>= ................................................................................ } proc CreateTempSymbol {args} { set name [CreateTempSymbolName] InsertSymbol Name $name {*}$args return $name } proc CreateLabelName {} { variable labelcounter return l__L[incr labelcounter] } ---- Again, we specialize the creation procedure for the variable types commonly used in code generation. [source,tcl] ---- ................................................................................ string map [list \" {}] ~ | join ~ }] ; # <1> return "#error \"$msg\"\n" ; <2> } finally { relvar set Symbol [relation emptyof [relvar set Symbol]] variable symcounter 0 variable labelcounter 0 } } ---- <1> Preparing a message suitable for `#error` from the error result. <2> We place a `#error` statement in the code to make sure it will not compile. ................................................................................ [source,tcl] ---- <<generation support commands>>= proc InstanceFindRelatedWhere {startref instref where args} { set startlevel [GetBlock] set where [string trim $where] set endref [CreateTempSymbolName] set endlabel [CreateLabelName] set chaincode [TraverseRelChain $startref $endref $args] set endsym [LookUpSymbol $endref] append chaincode [IndentToBlock [string cat\ "$instref = $endref ;\n"\ "if ($where) \{\n"\ ]] PushBlock append chaincode [IndentToBlock "goto $endlabel ;\n"] ; # <1> PopBlock append chaincode [IndentToBlock "\} else \{\n"] PushBlock append chaincode [IndentToBlock "$instref = NULL ;\n"] set depth [expr {[GetBlock] - $startlevel}] for {set i 0} {$i < $depth} {incr i} { PopBlock append chaincode [IndentToBlock "\}\n"] } append chaincode [IndentToBlock "${endlabel}: ;\n"] ; # <2> set result [IndentToBlock [string cat\ [linecomment "instance $startref findRelatedWhere\ $instref [list [string trim $where]] $args"]\ [CreateInstRefSymbol [dict get $endsym Class] $instref]\ "$instref = NULL ;\n"\ ]] return [append result $chaincode] } ---- <1> We use a naked `goto` here because we may be many levels deep in a loop to accomplish the relationships chain traversal. Alternatively, we might be traversing a singular relationships. The `goto` works for all the cases. <2> The semi-colon is necessary because a `goto` must label a statement. ifdef::showtests[] [source,tcl] ---- <<generate command tests>>= test codegen-63.0 { Generated code file to select related instance ................................................................................ t__T2 = t__T2->next ; struct Z *t__T4 = t__T3->R2__BACK ; // ~R2 if (t__T4 != NULL) { struct Z *t__T1 ; t__T1 = t__T4 ; zref = t__T1 ; if (zref->pressure == 42) { goto l__L1 ; } else { zref = NULL ; } } } l__L1: ; } } -result {1} ---- endif::showtests[] ifdef::showtests[] [source,tcl] ---- <<generate command tests>>= test codegen-71.0 { find related where for a super to sub class traversal } -setup { validateutils genMiccaFile codegen71 { domain codegen71 { class S { attribute size int -default 10 } class A { attribute height int -default 5 } class B { attribute width int -default 5 } generalization R42 -union S A B domainop void findBs {} { <% S findByName s1 sref %> <% instance sref findRelatedWhere bref {bref->width == 5}\ {~R42 B} %> } } population codegen71 { class S { instance s1 } class B { instance b1 R42 s1 } } } } -cleanup { micca clear validateutils forgetFiles } -body { validateutils compileFiles codegen71.c validateutils matchLines codegen71.c { struct B *bref ; bref = NULL ; struct B *t__T2 = &sref->R42.B ; // ~R42 B if (t__T2->base__INST.classDesc == &codegen71__CLASSES[2]) { struct B *t__T1 ; t__T1 = t__T2 ; bref = t__T1 ; if (bref->width == 5) { goto l__L1 ; } else { bref = NULL ; } } l__L1: ; } } -result {1} ---- endif::showtests[] ifdef::showtests[] [source,tcl] ---- <<generate command tests>>= test codegen-72.0 { find related where for simple singular association } -setup { validateutils genMiccaFile codegen72 { domain codegen72 { class A { attribute height int -default 5 } class B { attribute width int -default 5 } association R12 A 1--1 B domainop void findBs {} { <% A findByName a1 aref %> <% instance aref findRelatedWhere bref {bref->width == 5} R12 %> } } population codegen72 { class A { instance a1 R12 b1 } class B { instance b1 } } } } -cleanup { micca clear validateutils forgetFiles } -body { validateutils compileFiles codegen72.c validateutils matchLines codegen72.c { struct B *bref ; bref = NULL ; struct B *t__T2 = aref->R12 ; // R12 struct B *t__T1 ; t__T1 = t__T2 ; bref = t__T1 ; if (bref->width == 5) { goto l__L1 ; } else { bref = NULL ; } l__L1: ; } } -result {1} ---- endif::showtests[] ifdef::showtests[] [source,tcl] ---- <<generate command tests>>= test codegen-73.0 { find related where for multiple and singular chain } -setup { validateutils genMiccaFile codegen73 { domain codegen73 { class A { attribute height int -default 5 } class B { attribute width int -default 7 } class C { attribute area int -default 10 } association R12 A 1..*--1 B association R13 B 1..*--1 C domainop void findBs {} { <% C findByName c1 cref %> <% instance cref findRelatedWhere aref {aref->height == 5} ~R13 ~R12 %> } } population codegen73 { class A { instance a1 R12 b1 } class B { instance b1 R13 c1 } class C { instance c1 } } } } -cleanup { micca clear validateutils forgetFiles } -body { validateutils compileFiles codegen73.c validateutils matchLines codegen73.c { struct A *aref ; aref = NULL ; for (MRT_LinkRef *t__T2 = mrtLinkRefBegin(&cref->R13__BACK) ; t__T2 != mrtLinkRefEnd(&cref->R13__BACK) ;) { struct B *t__T3 = (struct B *)((uintptr_t)t__T2 - offsetof(struct B, R13__BLINKS)) ; t__T2 = t__T2->next ; for (MRT_LinkRef *t__T4 = mrtLinkRefBegin(&t__T3->R12__BACK) ; t__T4 != mrtLinkRefEnd(&t__T3->R12__BACK) ;) { struct A *t__T5 = (struct A *)((uintptr_t)t__T4 - offsetof(struct A, R12__BLINKS)) ; t__T4 = t__T4->next ; struct A *t__T1 ; t__T1 = t__T5 ; aref = t__T1 ; if (aref->height == 5) { goto l__L1 ; } else { aref = NULL ; } } } l__L1: ; } } -result {1} ---- endif::showtests[] ==== Finding a Single Related Instance ................................................................................ mrt_InstSetInitialize(&zset, &codegen48__CLASSES[2]) ; for (MRT_LinkRef *t__T2 = mrtLinkRefBegin(&xref->R1__BACK) ; t__T2 != mrtLinkRefEnd(&xref->R1__BACK) ;) { struct Y *t__T3 = (struct Y *)((uintptr_t)t__T2 - offsetof(struct Y, R1__BLINKS)) ; t__T2 = t__T2->next ; struct Z *t__T4 = t__T3->R2__BACK ; // ~R2 if (t__T4 != NULL) { struct Z *t__T1 ; t__T1 = t__T4 ; mrt_InstSetAddInstance(&zset, t__T1) ; } } }]} } -result {1} ---- endif::showtests[] ifdef::showtests[] [source,tcl] ---- <<generate command tests>>= test codegen-74.0 { Generated code file to select related instances } -setup { validateutils genMiccaFile codegen74 { domain codegen74 { class S { attribute color int -default 20 } class A { attribute temp int -default 30 } class B { } generalization R1 -union S A B class Z { attribute pressure int -default 40 } association R2 Z 1..*--1 B domainop void find {} { <%S findByName s1 sref%> <%instance sref selectRelated zset {~R1 B} ~R2%> } } population codegen74 { class S { instance s1 } class B { instance b1 R1 s1 } class Z { instance z1 R2 b1 pressure 41 instance z2 R2 b1 pressure 42 instance z3 R2 b1 pressure 43 } } } } -cleanup { micca clear validateutils forgetFiles } -body { validateutils compileFiles codegen74.c testConditions\ {[validateutils matchLines codegen74.c { MRT_InstSet zset ; mrt_InstSetInitialize(&zset, &codegen74__CLASSES[3]) ; struct B *t__T2 = &sref->R1.B ; // ~R1 B if (t__T2->base__INST.classDesc == &codegen74__CLASSES[2]) { for (MRT_LinkRef *t__T3 = mrtLinkRefBegin(&t__T2->R2__BACK) ; t__T3 != mrtLinkRefEnd(&t__T2->R2__BACK) ;) { struct Z *t__T4 = (struct Z *)((uintptr_t)t__T3 - offsetof(struct Z, R2__BLINKS)) ; t__T3 = t__T3->next ; struct Z *t__T1 ; t__T1 = t__T4 ; mrt_InstSetAddInstance(&zset, t__T1) ; } } }]} } -result {1} ---- |
Changes to micca/src/micca-docinfo.xml.
171 172 173 174 175 176 177 178 |
<authorinitials>GAM</authorinitials> <revremark> Corrected a problem with the declaration of the storage pool for multiple assigners. Minor improvements in man page documents. </revremark> </revision> </revhistory> |
> > > > > > > > > > > > |
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
<authorinitials>GAM</authorinitials> <revremark> Corrected a problem with the declaration of the storage pool for multiple assigners. Minor improvements in man page documents. </revremark> </revision> <revision> <revnumber>1.1.7</revnumber> <date>December 5, 2019</date> <authorinitials>GAM</authorinitials> <revremark> Corrected an error in the generated code for conditional relationship traversal. The code assumed a loop control structure was generated and used a break statement. This was not the case for singular relationships. </revremark> </revision> </revhistory> |
Changes to micca/src/platform.txt.
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 .... 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 .... 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 .... 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 |
Below is the UML class diagram for the domain subsystem of the platform model. image::platform-classes.pdf[title="Classes Subsystem Class Diagram"] A *Class* is composed of *ClassComponent* (*R20*). There are two types of *ClassComponent* (*R25*). *PopulatedComponent* are fundamental components whose values can be determine by population. *GeneratedComponent* are those that arise because of the design of how reference information is held. There are two types of *PopulatedComponent* (*R21). An *Attribute* is a named, descriptive value of the *Class*. Attributes come in two types (*R29*). The value of an *IndependentAttribute* does not depend upon any other aspect of the domain and may have a *DefaultValue* (*R22*). A *DependentAttribute* depends upon other aspects of the domain and its value can be computed by a formula. Consequently, you cannot update the value of a *DependentAttribute*. Dependent attributes are, strictly speaking, redundant, but are used by models to provide summary information in a more conveniently accessible form. A *Reference* is used to specify class relationships. There are three types of *Reference* (*R23*). An *AssociationReference* is a reference a class makes to realize a relationship. ................................................................................ references is realized by a *ComplementaryReference*. A *ComplementaryReference* may also be one of three different types (*R26*). The types of references fulfill different roles and types of relationships. A *SingularReference* is used to store a pointer to a single class instance. An *ArrayReference* holds the references for static associations of multiplicity greater than one and a *LinkReference* serves the same role for dynamic associations. A *LinkReference uses a *LinkContainer* to store pointers for chaining instances together (*R27*). A *ComplementaryReference* may also be used in one of two ways (*R28*). A *ForwardReference* is that reference set originated in a class based association when traversing the forward direction. A *BackwardReference* is that reference used when navigating any association in the reverse direction. ................................................................................ place a pointer variable in the ``C'' structure of the class on the *many* side and have the value of the pointer match that of a class instance on the *one* side. Now lets look at the computation required to navigate this relationship, first from the many side to the one side and then from the one side to the many side. For this discussion we will assume the relationship is unconditional on both sides. From the many side, given a pointer to an *A* instance we can navigate to the related *B* instance by simply accessing the structure member that points to the related *B* instance. When navigating from the one side to the many side, we will, in general, obtain more than one instance as a result of the ................................................................................ address of the one-side class instance. Having to perform a search for the one-side to many-side navigation is somewhat troubling. If the number of instances of the many-side class is small, then there is little concern. If it is larger, then we might explore ways to avoid costs associated with a straight linear search of the many-side instances. The search code is also rather inconvenient since we target a statically typed language. The function to iterate across the many-side instances looking for the one-side pointer value has to be specific to that particular relationship if we are to be strictly type safe and don't want to resort to extremes of type casting and pointer arithmetic. |
| | | | | | | |
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 .... 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 .... 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 .... 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 |
Below is the UML class diagram for the domain subsystem of the platform model. image::platform-classes.pdf[title="Classes Subsystem Class Diagram"] A *Class* is composed of *ClassComponent* (*R20*). There are two types of *ClassComponent* (*R25*). *PopulatedComponent* are fundamental components whose values can be determined by population. *GeneratedComponent* are those that arise because of the design of how reference information is held. There are two types of *PopulatedComponent* (*R21*). An *Attribute* is a named, descriptive value of the *Class*. Attributes come in two types (*R29*). The value of an *IndependentAttribute* does not depend upon any other aspect of the domain and may have a *DefaultValue* (*R22*). A *DependentAttribute* depends upon other aspects of the domain and its value is computed by a formula. Consequently, you cannot update the value of a *DependentAttribute*. Dependent attributes are, strictly speaking, redundant, but are used by models to provide summary information in a more conveniently accessible form. A *Reference* is used to specify class relationships. There are three types of *Reference* (*R23*). An *AssociationReference* is a reference a class makes to realize a relationship. ................................................................................ references is realized by a *ComplementaryReference*. A *ComplementaryReference* may also be one of three different types (*R26*). The types of references fulfill different roles and types of relationships. A *SingularReference* is used to store a pointer to a single class instance. An *ArrayReference* holds the references for static associations of multiplicity greater than one and a *LinkReference* serves the same role for dynamic associations. A *LinkReference* uses a *LinkContainer* to store pointers for chaining instances together (*R27*). A *ComplementaryReference* may also be used in one of two ways (*R28*). A *ForwardReference* is that reference set originated in a class based association when traversing the forward direction. A *BackwardReference* is that reference used when navigating any association in the reverse direction. ................................................................................ place a pointer variable in the ``C'' structure of the class on the *many* side and have the value of the pointer match that of a class instance on the *one* side. Now lets look at the computation required to navigate this relationship, first from the many side to the one side and then from the one side to the many side. For this discussion, we will assume the relationship is unconditional on both sides. From the many side, given a pointer to an *A* instance we can navigate to the related *B* instance by simply accessing the structure member that points to the related *B* instance. When navigating from the one side to the many side, we will, in general, obtain more than one instance as a result of the ................................................................................ address of the one-side class instance. Having to perform a search for the one-side to many-side navigation is somewhat troubling. If the number of instances of the many-side class is small, then there is little concern. If it is larger, then we might explore ways to avoid costs associated with a straight sequential` search of the many-side instances. The search code is also rather inconvenient since we target a statically typed language. The function to iterate across the many-side instances looking for the one-side pointer value has to be specific to that particular relationship if we are to be strictly type safe and don't want to resort to extremes of type casting and pointer arithmetic. |
Changes to micca/src/preface.txt.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
Part V on the run-time code has some interesting aspects as to how referential integrity is enforced. For those more interested in how platform model data may be queried and used to generate ``C'' code, Part VI gives the details of how the embedded macro commands for domain actions are translated into code. This book is also a literate program. See <<literal-programming>> for a description of the literate programming syntax. The syntax is not complicated, but you will need to know it to make much sense of any code sequences in the book. Being a literate program document means that all the source code for `micca` is included here. The `micca` program (and many other components) is built by extracting the source from the document source. Including the source code and all the design discussion makes the text rather long and skipping around when reading is encouraged. The next part of the book presents a simple example. This will give you a general sense of how model translation with `micca` works. After the example, we consider the four major components of `micca`: . The platform model. This is a complete model of the platform |
| | |
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
Part V on the run-time code has some interesting aspects as to
how referential integrity is enforced.
For those more interested in how platform model data may be queried and
used to generate ``C'' code,
Part VI gives the details of how the embedded macro commands for
domain actions are translated into code.
This book is a literate program.
See <<literal-programming>> for a description of the literate programming
syntax.
The syntax is not complicated, but you will need to know it
to make much sense of any code sequences in the book.
Being a literate program document means that all the source code for
`micca` is included here.
The `micca` program (and many other components) is built by extracting
the source from the document source.
Including the source code and all the design discussion makes the
text rather long
and skipping around when reading is encouraged.
Part II of the book presents a simple example.
This will give you a general sense of how model translation with
`micca` works.
After the example,
we consider the four major components of `micca`:
. The platform model. This is a complete model of the platform
|
Changes to micca/src/runtime.txt.
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 .... 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 .... 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 |
`mrtFindInstSlot` searchs for unused instance memory in the memory pool described by `iab`. It returns a pointer to the allocated memory if successful and `NULL` if no memory is available in the class pool. ***** The allocation algorithm is a simple linear search starting at the last location that was allocated. (((micca,Run Time Function,mrtFindInstSlot))) [source,c] ---- <<mrt static functions>>= static MRT_Instance * ................................................................................ the "source" instance reference must be one of the subclasses that participates in the relationship. The primary reference in a generalization is from subclass instance to superclass instance. <2> The "target" instance reference must then be to the superclass of the generalization. Finding the participating subclass of the generalization is a linear search of the subclass roles in the relationship description. (((micca,Run Time Function,mrtFindRefGenSubclassCode))) [source,c] ---- <<mrt static functions>>= static int ................................................................................ === Reclassifying Subclasses Generalization relationships represent a disjoint union of the subclasses. Because of this property, we know that there is an unconditional relationship between a subclass instance and a superclass instance and an unconditional relationship between a superclass instance and a subclass instance from among all the subclasses of the generalization. This situation leads to the concept of a reclassify operation to allow a related subclass instance to migrate from one subclass to another. It is a powerful concept to model modal operations in a domain. The run-time provides a function to accomplish the details. ***** |
| | | |
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 .... 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 .... 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 |
`mrtFindInstSlot` searchs for unused instance memory in the memory pool described by `iab`. It returns a pointer to the allocated memory if successful and `NULL` if no memory is available in the class pool. ***** The allocation algorithm is a simple sequential search starting at the last location that was allocated. (((micca,Run Time Function,mrtFindInstSlot))) [source,c] ---- <<mrt static functions>>= static MRT_Instance * ................................................................................ the "source" instance reference must be one of the subclasses that participates in the relationship. The primary reference in a generalization is from subclass instance to superclass instance. <2> The "target" instance reference must then be to the superclass of the generalization. Finding the participating subclass of the generalization is a sequential search of the subclass roles in the relationship description. (((micca,Run Time Function,mrtFindRefGenSubclassCode))) [source,c] ---- <<mrt static functions>>= static int ................................................................................ === Reclassifying Subclasses Generalization relationships represent a disjoint union of the subclasses. Because of this property, we know that there is an unconditional relationship between a subclass instance and a superclass instance and an unconditional relationship between a superclass instance and exactly one subclass instance from among all the subclasses of the generalization. This situation leads to the concept of a reclassify operation to allow a related subclass instance to migrate from one subclass to another. It is a powerful concept to model modal operations in a domain. The run-time provides a function to accomplish the details. ***** |