Check-in [07d00e9b7c]
Not logged in

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: 07d00e9b7cf6218f842c0ee3d648641fcd67f033
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.

*****