File: mlds.m

package info (click to toggle)
mercury 0.9-1
  • links: PTS
  • area: main
  • in suites: potato
  • size: 18,488 kB
  • ctags: 9,800
  • sloc: objc: 146,680; ansic: 51,418; sh: 6,436; lisp: 1,567; cpp: 1,040; perl: 854; makefile: 450; asm: 232; awk: 203; exp: 32; fortran: 3; csh: 1
file content (1380 lines) | stat: -rw-r--r-- 46,112 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
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
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
%-----------------------------------------------------------------------------%
% Copyright (C) 1999 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%

% MLDS - The Medium-Level Data Structure.
% Main author: fjh.

% This module defines the MLDS data structure itself.
% The MLDS is an intermediate data structure used in compilation;
% we compile Mercury source -> parse tree -> HLDS -> MLDS -> target (e.g. C).
% See notes/compiler_design.html for more information about the MLDS & LLDS.
%
% The MLDS is intended to be suitable for generating target code in
% languages such as Java, Java bytecode, high-level C, C++, or C--, etc.
% This is as opposed to the LLDS, which is better suited for generating
% assembler or the very low-level C or GNU C (lower level than C--) that
% the original Mercury compiler backend generates.  In the LLDS, we are
% doing all our own register allocation and stack manipulation, but with
% MLDS, those tasks are the responsibility of the target.
% The one really important simplification that we do make relative to the
% HLDS is that MLDS does not have any support for non-determinism, so the
% HLDS->MLDS compiler must compile non-deterministic code into code that
% uses continuation passing.

% The MLDS data structure is quite full-featured, including for example
% support for arbitrary nesting, multiple return values, and tagged pointers.
% However, many
% of the intended target languages don't support all of those features. 
% Therefore the HLDS->MLDS compiler must ensure that the final MLDS code that
% it eventually generates does not use features which the target does not
% support.  This will (presumably) be accomplished by having handle_options.m
% set various flags according to the selected target, and having the
% HLDS->MLDS compiler take account of those flags and either generate simpler
% MLDS code in the first place or run some extra simplification passes over
% the MLDS code before invoking the MLDS->target compiler.
% 

%-----------------------------------------------------------------------------%
%
% Mapping Mercury names to MLDS names
%

% 1. Modules
%
% Mercury module names map directly to MLDS package names, except that
% modules in the Mercury standard library map get a `mercury' prefix,
% e.g. `mercury.builtin', `mercury.io', `mercury.std_util', etc.

% 2. Procedures names
%
% HLDS procedure names map directly to MLDS function names.
% MLDS function names are structured terms that include sufficient
% information (arity, pred_or_func indicator, mode number, etc.)
% to avoid any ambiguities.
%
% [Rationale: the reason for keeping structured names rather than flattened
% names at the MLDS level is that we don't want to do name mangling at
% the HLDS -> MLDS stage, since we don't know what restrictions the target
% language will impose.  For example, some target languages (e.g. C++, Java)
% will support overloading, while others (e.g. C) will not.]

% 3. Procedures signatures
%
% MLDS function signatures are determined by the HLDS procedure's
% argument types, modes, and determinism.
% Procedures arguments with type `io__state' or `store(_)' are not passed.
% Procedures arguments with top_in modes are passed as input.
% Procedures arguments with top_out modes may be returned by value
% or alternatively may be passed by reference.
% Procedure arguments with top_unused modes should not be passed
% (except possibly in the case where they are polymorphically typed,
% and even then, depending on how polymorphism is handled).]
% Procedures with determinism model_det need no special handling.
% Procedures with determinism model_semi must return a boolean.
% Procedures with determinism model_non get passed a continuation;
% if the procedure succeeds, it must call the continuation, and if
% it fails, it must return.

% 4. Variables
%
% MLDS variable names are determined by the HLDS variable name and
% (to avoid ambiguity) variable number.
% All references to MLDS variables must however be fully qualified
% with the name of the enclosing entity that defines them.

% 5. Global data
%
% Is there any use in hanging on to the structure of the names for
% compiler-generated global data?  Currently we do.  I'm not sure
% if it would be better to flatten it (using mangled names) at this point.

% 6. Types
%
% If there is an MLDS type corresponding to a Mercury type, then
% the Mercury type name maps directly to the MLDS type name,
% suitable module-qualified of course. 
% The MLDS type name includes the type arity (arity overloading is allowed).
% However, if a low-level data representation scheme is used,
% then some Mercury types may not have corresponding MLDS type names
% (that is, the corresponding MLDS type may be just `Word' or its equivalent).

% 7.  Data constructors.
%
% [XXX Not yet documented or implemented]
% [XXX Also need to think about equivalence types and no_tag types]

% 8.  Insts and modes
%
% Inst and mode definitions do not get translated into MLDS.
%
% [Inst and mode definitions do however affect the signatures of the
% MLDS functions used to implement each procedure.]

% 9. Type classes.
% 
% Currently type classes are handled early and at a fairly low level.
% It's not yet clear how easy it will be to convert this to MLDS.
% It may depend to some degree on the target language.
% But if it is possible, then when it is done the target language
% generator will be able to ignore the issue of type classes.
%
% For language interoperability, however, it might be nice if the
% translation were done at higher level.
%
% Mercury type classes should map directly to MLDS interfaces.
%
% Mercury instance definitions should map to classes which implement the
% corresponding interface.  Note that if there is an instance declaration
% `:- instance foo(bar)', then the MLDS type for `bar' will *not* implement 
% the MLDS interface for `foo' -- instead, there will be a new MLDS type
% for `instance foo(bar)' which implements that interface.

%-----------------------------------------------------------------------------%
%
% Mapping MLDS names to the target language
%

% Ultimately the exact choice of how MLDS names are mapped to
% the target language is up to the target language generator.
% So the remarks here are just guidelines, not strict rules.

% 1.  Names.
%
% If the target language has standard conventions about certain categories
% of names beginning with uppercase or lowercase letters, then the target
% language generator should generate names that respect those conventions.
%
% An MLDS name may contain arbitrary characters.
% If the target language has restrictions on what names can be used
% in identifiers, then it is the responsibility of the target language
% generator to mangle MLDS names accordingly to ensure that they abide
% by those restrictions.

% 2. Packages.
%
% MLDS packages should be mapped directly to target packages, if possible.
% If the target doesn't have a notion of packages, then they should be
% mapped to names of the form "foo.bar.baz" or if dots are not allowed
% then to "foo__bar__baz".

% 3. Overloading
%
% If the target does not support overloading, then any Mercury names which
% are overloaded within a single Mercury module must be qualified to avoid
% ambiguity.  However, Mercury names which are not overloaded should not
% be qualified.  If a name is overloaded but occurs only once in the module's
% interface then the version in the interface should not be qualified.
% The arity-zero version of type should not be arity-qualified
% unless this would cause ambiguity with an unqualified name generated by
% the previous rule.  Likewise, the arity-zero version of function
% (i.e. a constant) should not be function-qualified or arity-qualified
% unless this would cause ambiguity with an unqualified name generated
% the aforementioned rule.
% The first mode of a predicate should not be mode-qualified.
%
% [Rationale: name mangling should be avoided where possible, because
% this makes it easier for the user to interoperate with other languages
% and to use tools which do not properly demangle Mercury names.]

% 4. Procedures.
%
% If a procedure name needs to be qualified, the qualification should be
% done by appending "_f" for functions or "_p" for predicates,
% optionally followed by the arity,
% optionally followed by an underscore and then the mode number,
% optionally followed by "_i" and then the MLDS function sequence number
% (for internal MLDS functions, used e.g. to implement backtracking).
%
% [Rationale: any qualifiers should go at the end of a name, so that
% command-line completion works even for mangled names (and hopefully
% even shows all the possible alternatives...).]
%
% To avoid ambiguity as to whether a name is qualified or not,,
% any procedures whose unqualified name matches the pattern for qualified
% names, i.e. the regular expression `.*_[fp][0-9]*(_[0-9]+)?(_i[0-9]+)?',
% should always be qualified (even if not overloaded).

% 5. Types.
%
% If a type name needs to be qualified, the qualification should be
% done by appending an underscore followed by the arity.
%
% To avoid ambiguity as to whether a name is qualified or not,
% any types whose unqualified name matches the pattern for qualified
% names, i.e. the regular expression `.*_[0-9]+',
% should always be qualified (even if not overloaded).

%-----------------------------------------------------------------------------%
%
% Notes on garbage collection and liveness.
% 

% "Liveness-accurate GC" is GC in which the collector does not trace local
% variables which are definitely not live according to a straight-forward
% static analysis of definite-deadness/possible-liveness.  Liveness-accurate
% GC is desirable, in general, since tracing through variables which are
% no longer live may lead to excessive memory retention for some programs.
% However these programs are relatively rare, so liveness-accurate GC
% is not always worth the extra complication.
%
% The MLDS is therefore designed to optionally support liveness-accurate
% GC, if the target language supports it.  If liveness-accurate GC is
% supported and enabled, then it is the responsibility of the target
% language implementation to do whatever is needed to avoid having the GC
% trace variables which have gone out of scope.
%
% That means that to support liveness-accurate the HLDS->MLDS code
% generator just needs to cover the cases where a straight-forward liveness
% calculation on the generated MLDS does not match up with the desired
% result of a straight-forward liveness calculation on the HLDS.  That is,
% the HLDS->MLDS code generator must generate code to clobber variables
% which are no longer live according to a straight-forward liveness
% calculation on the HLDS but which have not gone out of scope in
% the generated MLDS.  For example, with our current HLDS->MLDS code
% generation scheme, this is the case for variables in the `else' of a
% nondet if-then-else once the `then' has been entered.
% (XXX Currently ml_code_gen.m does _not_ clobber those variables, though.)

% The rationale for leaving most of the responsibility for liveness-accurate
% GC up to the MLDS back-end is as follows: at very least we need the
% target language implementation's _cooperation_, since if the MLDS code
% generator inserts statements to clobber variables that are no longer live,
% then an uncooperative target language implementation could just optimize
% them away, since they are assignments to dead variables.  Given this need
% for the MLDS target back-end's cooperation, it makes sense to assign as
% much of the responsibily for this task as is possible to the MLDS target
% back-end, to keep the front-end simple and to keep the responsibility
% for this task in one place.
%
% But in the cases such as nondet if-then-else, where HLDS-liveness does not
% match MLDS-liveness, we can't just leave it to the MLDS target back-end,
% because that would require assuming an unreasonably smart liveness
% calculation in the MLDS target back-end, so in such cases we do need
% to handle it in the HLDS->MLDS code generator.

%-----------------------------------------------------------------------------%

:- module mlds.

:- interface.

:- import_module hlds_pred, hlds_data, prog_data, builtin_ops.

% To avoid duplication, we use a few things from the LLDS.
% It would be nice to avoid this dependency...
:- import_module llds.

:- import_module bool, list, assoc_list, std_util.

%-----------------------------------------------------------------------------%

:- type mercury_module_name == prog_data__module_name.

%
% The type `mlds' is the actual MLDS.
% XXX we ought to make this type abstract
%
:- type mlds
	---> mlds(
		mercury_module_name,	% The Mercury module name

		mlds__foreign_code,	% Code defined in some other language,
					% e.g. for `pragma c_header_code', etc.

		% The MLDS code itself
		mlds__imports,		% Packages/classes to import
		mlds__defns		% Definitions of code and data
	).

:- func mlds__get_module_name(mlds) = mercury_module_name.

:- type mlds__imports == list(mlds__import).

% Currently an import just gives the name of the package to be imported.
% This might perhaps need to be expanded to cater to different kinds of
% imports, e.g. imports with wild-cards ("import java.lang.*").
:- type mlds__import == mlds_module_name.
					% Specifies the name of a package or
					% class to import.

% An mlds_module_name specifies the name of an mlds package or class.
:- type mlds_module_name.

% An mlds__package_name specifies the name of an mlds package.
:- type mlds__package_name == mlds_module_name.

% Given the name of a Mercury module, return the name of the corresponding
% MLDS package.
:- func mercury_module_name_to_mlds(mercury_module_name) = mlds__package_name.

% Given the name of a Mercury module, return the name of the corresponding
% MLDS package.
:- func mlds_module_name_to_sym_name(mlds__package_name) = sym_name.


:- type mlds__defns == list(mlds__defn).
:- type mlds__defn
	---> mlds__defn(
		mlds__entity_name,	% the name of the entity being declared
		mlds__context,		% the source location
		mlds__decl_flags,	% these contain the following:
			% mlds__access,		% public/private/protected
			% mlds__member_type,	% static/per_instance
			% mlds__virtuality,	% virtual/non_virtual
			% mlds__finality,	% final/overridable (funcs only)
			% mlds__constness,	% const/modifiable  (data only)
			% mlds__is_abstract,	% abstract/concrete
			% etc.
		mlds__entity_defn	% the definition of the entity
	).

% An mlds name may contain arbitrary characters.
% If the target language has restrictions on what names can be used
% in identifiers, then it is the responsibility of the target language
% generator to mangle these names accordingly.
:- type mlds__fully_qualified_name(T)
	---> 	qual(mlds_module_name, T).
:- type mlds__qualified_entity_name
	==	mlds__fully_qualified_name(mlds__entity_name).

:- type mlds__entity_name
	--->	type(mlds__class_name, arity)	% Name, arity.
	;	data(mlds__data_name)
	;	function(
			mlds__pred_label,	% Identifies the source code
						% predicate or function.

			proc_id,		% Mode number.

				% A sequence number used to distinguish 
				% different MLDS functions when compiling a
				% single HLDS predicate into multiple MLDS
				% functions (e.g. to handle backtracking).
			maybe(mlds__func_sequence_num),

				% This should generally not be needed much,
				% since all the necessary information should
				% be in the mlds__pred_label and/or in the
				% mlds__entity_defn.  However, the target
				% generator may want to refer to the HLDS
				% for additional information.
			pred_id			% Specifies the HLDS pred_id.
		)
	.

:- type mlds__func_sequence_num == int.

	% This specifies information about some entity being defined
	% The entity may be any of the following:
	%	constant or variable
	%	function
	%	class, including
	%		package (class with only static members)
	%		interface (abstract class, no data members)
	%		struct (value class)
	%		enum
:- type mlds__entity_defn
		% constants or variables
	--->	mlds__data(
			mlds__type,
			maybe(mlds__initializer)
		)
		% functions
	;	mlds__function(
			maybe(pred_proc_id),	% identifies the original
						% Mercury procedure, if any
			mlds__func_params,	% the arguments & return types
			maybe(mlds__statement)	% the function body, or `no'
						% if the function is abstract
		)
		% packages, classes, interfaces, structs, enums
	;	mlds__class(
			mlds__class_defn
		).

:- type mlds__initializer == list(mlds__rval).

:- type mlds__func_params
	---> mlds__func_params(
		mlds__arguments,	% names and types of arguments (inputs)
		list(mlds__type)	% types of return values (outputs)
	).

:- type mlds__arguments == assoc_list(mlds__entity_name, mlds__type).

	% An mlds__func_signature is like an mlds__func_params
	% except that it only includes the function's type, not
	% the parameter names.
:- type mlds__func_signature
	---> mlds__func_signature(
		list(mlds__type),	% argument types
		list(mlds__type)	% return types
	).

:- func mlds__get_func_signature(mlds__func_params) = mlds__func_signature.

:- type mlds__class_kind
	--->	mlds__class		% A generic class:
					% can inherit other classes and
					% interfaces
					% (but most targets will only support
					% single inheritence, so usually there
					% will be at most one class).
	;	mlds__package		% A class with only static members
					% (can only inherit other packages).
					% Unlike other kinds of classes,
					% packages should not be used as types.
	;	mlds__interface		% A class with no variable data members
					% (can only inherit other interfaces)
	;	mlds__struct		% A value class
					% (can only inherit other structs).
	;	mlds__enum		% A class with one integer member and
					% a bunch of static consts
					% (cannot inherit anything).
	.


:- type mlds__class_name == string.
:- type mlds__class == mlds__fully_qualified_name(mlds__class_name).

:- type mlds__class_defn
	---> mlds__class_defn(
		mlds__class_kind,
		mlds__imports,			% imports these classes (or
						% modules, packages, ...)
		list(mlds__class_id),		% inherits these base classes
		list(mlds__interface_id),	% implements these interfaces
		mlds__defns			% contains these members
	).

	% Note: the definition of the `mlds__type' type is subject to change.
	% In particular, we might add new alternatives here, so try to avoid
	% switching on this type.
:- type mlds__type
	--->	% Mercury data types
		mercury_type(prog_data__type)

		% The type for the continuation functions used
		% to handle nondeterminism
	;	mlds__cont_type

		% The type used for storing information about a commit.
		% This may be `jmp_buf' or `__label__'.
	;	mlds__commit_type

		% MLDS native builtin types.
		% These are the builtin types of the MLDS target language,
		% whatever that may be.
		% Currently we don't actually use many of these.
	;	mlds__bool_type
	;	mlds__int_type
	;	mlds__float_type
	;	mlds__char_type

		% MLDS types defined using mlds__class_defn
	;	mlds__class_type(mlds__class, arity)	% name, arity

		% Pointer types.
		% Currently these are used for handling output arguments.
	;	mlds__ptr_type(mlds__type)

		% Function types.
	;	mlds__func_type(mlds__func_params)

		% A generic type (e.g. `Word') that can hold any Mercury value.
		% This is used for implementing polymorphism.
	;	mlds__generic_type

		% A generic pointer type (e.g. `void *' in C)
		% that can be used to point to the environment
		% (set of local variables) of the containing function.
		% This is used for handling nondeterminism,
		% if the target language doesn't supported
		% nested functions, and also for handling
		% closures for higher-order code.
	;	mlds__generic_env_ptr_type

	;	mlds__base_type_info_type.

:- type mercury_type == prog_data__type.

:- func mercury_type_to_mlds_type(mercury_type) = mlds__type.

% Hmm... this is tentative.
:- type mlds__class_id == mlds__type.
:- type mlds__interface_id == mlds__type.

%-----------------------------------------------------------------------------%

:- type mlds__decl_flags.

:- type access
	--->	public
	;	protected
	;	private
	;	default.	% Java "default" access: accessible to anything
				% defined in the same package.

:- type per_instance
	--->	one_copy	% i.e. "static" storage duration
				% (but not necessarily static linkage)
				% or static member function
	;	per_instance.	% i.e. "auto" local variable in function,
				% or non-static member of class.

:- type virtuality
	--->	non_virtual
	;	virtual.

:- type finality
	--->	overridable
	;	final.

:- type constness
	--->	modifiable
	;	const.

:- type abstractness
	--->	concrete
	;	abstract.

:- func access(mlds__decl_flags) = access.
:- func per_instance(mlds__decl_flags) = per_instance.
:- func virtuality(mlds__decl_flags) = virtuality.
:- func finality(mlds__decl_flags) = finality.
:- func constness(mlds__decl_flags) = constness.
:- func abstractness(mlds__decl_flags) = abstractness.

:- func set_access(mlds__decl_flags, access) = mlds__decl_flags.
:- func set_per_instance(mlds__decl_flags, per_instance) = mlds__decl_flags.
:- func set_virtuality(mlds__decl_flags, virtuality) = mlds__decl_flags.
:- func set_finality(mlds__decl_flags, finality) = mlds__decl_flags.
:- func set_constness(mlds__decl_flags, constness) = mlds__decl_flags.
:- func set_abstractness(mlds__decl_flags, abstractness) = mlds__decl_flags.

:- func init_decl_flags(access, per_instance, virtuality, finality,
		constness, abstractness) = mlds__decl_flags.

%-----------------------------------------------------------------------------%

	%
	% C code required for the C interface.
	% When compiling to a language other than C,
	% this part still needs to be generated as C code
	% and compiled with a C compiler.
	%
:- type mlds__foreign_code
	---> mlds__foreign_code(
		c_header_info,
		list(user_c_code),
		list(c_export)		% XXX we will need to modify
					% export.m to handle different
					% target languages
	).

%-----------------------------------------------------------------------------%

	% mlds__context is probably == prog_context,
	% but might also contain goal_path or other information.
:- type mlds__context.

:- func mlds__make_context(prog_context) = mlds__context.

:- func mlds__get_prog_context(mlds__context) = prog_context.

%-----------------------------------------------------------------------------%

:- type mlds__statements == list(mlds__statement).

:- type mlds__statement
	--->	mlds__statement(
			mlds__stmt,
			mlds__context
		).

:- type mlds__stmt
	--->

	%
	% sequence
	%
		block(mlds__defns, list(mlds__statement))

	%
	% iteration
	%
	;	while(mlds__rval, mlds__statement, bool)
			% the `bool' is true iff the loop is guaranteed
			% to iterate at least once -- in that case,
			% the compiler can generate a `do...while' loop
			% rather than a `while...' loop.

	%
	% selection (see also computed_goto)
	%
	;	if_then_else(mlds__rval, mlds__statement,
			maybe(mlds__statement))

/******
	% Is it worth including this?  We already have `computed_goto'...
	;	switch(
			mlds__rval,

			% other representations might be better...
			assoc_list(mlds__rval, mlds__statement),
			mlds__statement		% the default case
		)
******/

	%
	% transfer of control
	%

	;	label(mlds__label)
			% Defines a label that can be used as the
			% target of calls, gotos, etc.

	;	goto(mlds__label)
			% goto(Target)
			% Branch to the specified address.

	;	computed_goto(mlds__rval, list(mlds__label))
			% Evaluate rval, which should be an integer,
			% and jump to the (rval+1)th label in the list.
			% e.g. computed_goto(2, [A, B, C, D])
			% will branch to label C.


	%
	% function call/return
	%

	;	call(
			mlds__func_signature,	% signature of the func
			mlds__rval,		% the function to call
			maybe(mlds__rval),	% for method calls, this field
						% specifies the `this' object
			list(mlds__rval),	% ordinary function arguments
			list(mlds__lval),	% places to store the
						% function return value(s)
			is_tail_call		% indicates whether this
						% call is a tail call
		)

	;	return(list(mlds__rval))	% Some targets will not support
						% returning more than one value
						
	%
	% commits (a specialized form of exception handling)
	%

		% try_commit(Ref, GoalToTry, CommitHandlerGoal):
		%	Execute GoalToTry.  If GoalToTry exits via a
		%	`commit(Ref)' instruction, then execute
		%	CommitHandlerGoal.
		%
		% do_commit(Ref):
		%	Unwind the stack to the corresponding `try_commit'
		%	statement for Ref, and branch to the CommitHandlerGoal
		%	that was specified in that try_commit instruction.
		%
		% For both try_commit and commit instructions,
		% Ref should be the name of a local variable of type
		% mlds__commit_type.  There should be exactly
		% one try_commit instruction for each Ref.
		% do_commit(Ref) instructions should only be used
		% in goals called from the GoalToTry goal in the
		% try_commit instruction with the same Ref.
		%	
	;	try_commit(mlds__lval, mlds__statement, mlds__statement)
	;	do_commit(mlds__rval)

	%
	% exception handling
	%
/*********
XXX Full exception handling support is not yet implemented.

	% We use C++-style exceptions.
	% For C, the back-end can simulate them using setjmp/longjmp.
	%
	% XXX This is tentative -- the current definition may be
	% a bit too specific to C++-style exceptions.
	% It might not be a good choice for different target languages.

		% throw the specified exception
	;	throw(mlds__type, mlds__rval)

		% rethrow the current exception
		% (only valid inside an exception handler)
	;	rethrow

		% Execute the specified statement, and if it throws an exception,
		% and the exception matches any of the exception handlers,
		% then execute the first matching exception handler.
	;	try_catch(
			mlds__statement,
			list(mlds__exception_handler)
		)
**********/

	%
	% atomic statements
	%

	;	atomic(mlds__atomic_statement)
	
	.


:- type mlds__label == string.

:- type is_tail_call
	--->	tail_call	% a tail call
	;	call		% just an ordinary call
	.


	% XXX This is tentative -- the current definition may be
	% a bit too specific to C++-style exceptions.
	% It might not be a good choice for different target languages.
:- type mlds__exception_handler
	--->	handler(
			maybe(mlds__type),
				% if `yes(T)', specifies the type of exceptions to catch
				% if `no', it means catch all exceptions

			maybe(string)
				% if `yes(Name)', gives the variable name to use for
				%	the exception value
				% if `no', then exception value will not be used
		).


	%
	% atomic statements
	%
:- type mlds__atomic_statement

	--->	comment(string)
			% Insert a comment into the output code.

	;	assign(mlds__lval, mlds__rval)
			% assign(Location, Value):
			% Assign the value specified by rval to the location
			% specified by lval.

	%
	% heap management
	%

		% XXX the following is still quite tentative
			% new_object(Target, Tag, Type,
			%	Size, CtorName, Args, ArgTypes):
			% Allocate a memory block of the given size,
			% initialize it with a new object of the given
			% type by calling the constructor with the specified
			% arguments, and put its address in the given lval,
			% possibly after tagging the address with a given tag.
			% (Some targets might not support tags.)
	;	new_object(
			mlds__lval,	% The target to assign the new object's
					% address to.
			maybe(mlds__tag),
					% A tag to tag the address with
					% before assigning the result to the
					% target.
			mlds__type,	% The type of the object being
					% allocated.
			maybe(mlds__rval),
					% The amount of memory that needs to
					% be allocated for the new object,
					% measured in bytes.
					% (XXX would it be better to measure
					% this in bits or words rather than
					% bytes?)
			maybe(ctor_name),
					% The name of the constructor to
					% invoke.
			list(mlds__rval),
					% The arguments to the constructor.
			list(mlds__type)
					% The types of the arguments to the
					% constructor.
		)

	;	mark_hp(mlds__lval)
			% Tell the heap sub-system to store a marker
			% (for later use in restore_hp/1 instructions)
			% in the specified lval
			%
			% It's OK for the target to treat this as a no-op,
			% and probably that is what most targets will do.

	;	restore_hp(mlds__rval)
			% The rval must be a marker as returned by mark_hp/1.
			% The effect is to deallocate all the memory which
			% was allocated since that call to mark_hp.
			%
			% It's OK for the target to treat this as a no-op,
			% and probably that is what most targets will do.

	%
	% trail management
	%

	;	trail_op(trail_op)

	%
	% foreign language interfacing
	%

	;	target_code(target_lang, string)
			% Do whatever is specified by the string,
			% which can be any piece of code in the specified
			% target language (C, assembler, or whatever)
			% that does not have any non-local flow of control.

	.


	%
	% This is just a random selection of possible languages
	% that we might want to target...
	%
:- type target_lang
	--->	lang_C
	;	lang_GNU_C
	;	lang_C_minus_minus
	;	lang_asm
	;	lang_java_asm
	;	lang_java_bytecode
	.

	% XXX I'm not sure what representation we should use here
:- type ctor_name == string.

	%
	% trail management
	%
:- type trail_op

	--->	store_ticket(mlds__lval)
			% Allocate a new "ticket" and store it in the lval.

	;	reset_ticket(mlds__rval, mlds__reset_trail_reason)
			% The rval must specify a ticket allocated with
			% `store_ticket' and not yet invalidated or
			% deallocated.
			% If undo_reason is `undo' or `exception', restore
			% any mutable global state to the state it was in when
			% the ticket was obtained with store_ticket();
			% invalidates any tickets allocated after this one.
			% If undo_reason is `commit' or `solve', leave the state
			% unchanged, just check that it is safe to commit
			% to this solution (i.e. that there are no outstanding
			% delayed goals -- this is the "floundering" check).
			% Note that we do not discard trail entries after
			% commits, because that would in general be unsafe.
			%
			% Any invalidated ticket is useless and should
			% be deallocated with either `discard_ticket'
			% or `discard_tickets_to'.

	;	discard_ticket
			% Deallocates the most-recently allocated ticket.

	;	mark_ticket_stack(mlds__lval)
			% Tell the trail sub-system to store a ticket counter
			% (for later use in discard_tickets_upto)
			% in the specified lval.

	;	discard_tickets_to(mlds__rval)
			% The rval must be a ticket counter obtained via
			% `mark_ticket_stack' and not yet invalidated.
			% Deallocates any trail tickets allocated after
			% the corresponding call to mark_ticket_stack.
			% Invalidates any later ticket counters.
	.

%-----------------------------------------------------------------------------%

	%
	% A field_id represents some data within an object
	%

:- type field_id 
	--->		% offset(N) represents the field
			% at offset N Words.
	 	offset(mlds__rval)
	;		% named_field(Name) represents the field
			% with the specified name.
		named_field(mlds__fully_qualified_name(field_name))
	.

:- type field_name == string.

	%
	% An mlds__var represents a variable or constant.
	%
:- type mlds__var == mlds__fully_qualified_name(mlds__var_name).
:- type mlds__var_name == string.

	%
	% An lval represents a data location or variable that can be used
	% as the target of an assignment.
	%
:- type mlds__lval 

	%
	% values on the heap
	% or fields of a structure
	%
	--->	field(maybe(mlds__tag), mlds__rval, field_id)
				% field(Tag, Address, FieldName)
				% selects a field of a compound term.
				% Address is a tagged pointer to a cell
				% on the heap; the offset into the cell
				% is FieldNum words. If Tag is yes, the
				% arg gives the value of the tag; if it is
				% no, the tag bits will have to be masked off.
				% The value of the tag should be given if
				% it is known, since this will lead to
				% faster code.

	%
	% values somewhere in memory
	% this is the deference operator (e.g. unary `*' in C)
	%
	;	mem_ref(mlds__rval)	% The rval should have
				% originally come from a mem_addr rval.

	%
	% variables
	% these may be local or they may come from some enclosing scope
	% the variable name should be fully qualified
	%
	;	var(mlds__var)
	
	.

%-----------------------------------------------------------------------------%

	% XXX this probably needs work

	% An rval is an expression that represents a value.
:- type mlds__rval	
	--->	lval(mlds__lval)
		% The value of an `lval' rval is just the value stored in
		% the specified lval.

	;	mkword(mlds__tag, mlds__rval)
		% Given a pointer and a tag, mkword returns a tagged pointer.
		%
		% (XXX It might be more consistent to make this a binary_op,
		% with the tag argument just being an rval, rather than
		% having `mkword' be a separate kind of rval.)

	;	const(mlds__rval_const)

	;	unop(mlds__unary_op, mlds__rval)

	;	binop(binary_op, mlds__rval, mlds__rval)

	;	mem_addr(mlds__lval).
		% The address of a variable, etc.

:- type mlds__unary_op
	--->	box(mlds__type)
	;	unbox(mlds__type)
	;	std_unop(builtin_ops__unary_op).

:- type mlds__rval_const
	--->	true
	;	false
	;	int_const(int)
	;	float_const(float)
	;	string_const(string)
			% A multi_string_const is a string containing
			% embedded NULs, whose real length is given
			% by the integer, and not the location of the
			% first null character.
	;	multi_string_const(int, string)
	;	code_addr_const(mlds__code_addr)
	;	data_addr_const(mlds__data_addr).

:- type mlds__code_addr
	--->	proc(mlds__qualified_proc_label)
	;	internal(mlds__qualified_proc_label, mlds__func_sequence_num).

:- type mlds__data_addr
	--->	data_addr(mlds_module_name, mlds__data_name).
			% module name; which var

:- type mlds__data_name
	--->	var(mlds__var_name)
			% ordinary variables
	;	common(int)
			% Compiler-introduced constants representing
			% global constants.  These are called "common"
			% because they may be common sub-expressions.
	%
	% Stuff for handling polymorphism and type classes
	%
	;	type_ctor(mlds__base_data, string, arity)
			% base_data, type name, type arity
	;	base_typeclass_info(hlds_data__class_id, string)
			% class name & class arity, names and arities of the
			% types
	%
	% Stuff for handling debugging and accurate garbage collection.
	% (Those features are not yet implemented for the MLDS back-end,
	% so these data_names are not yet used.)
	%
	;	module_layout
			% Layout information for the current module.
	;	proc_layout(mlds__proc_label)
			% Layout structure for the given procedure.
	;	internal_layout(mlds__proc_label, mlds__func_sequence_num)
			% Layout structure for the given internal MLDS func.
	%
	% Stuff for tabling
	%
	;	tabling_pointer(mlds__proc_label).
			% A variable that contains a pointer that points to
			% the table used to implement memoization, loopcheck
			% or minimal model semantics for the given procedure.

%-----------------------------------------------------------------------------%

%
% Note: the types `tag', `base_data', and `reset_trail_reason' here are all
% defined exactly the same as the ones in llds.m.  The definitions are
% duplicated here because we don't want mlds.m to depend on llds.m.
% (Alternatively, we could move all these definitions into a new module
% imported by both mlds.m and llds.m, but these definitions are small enough
% and simple enough that I don't think it is worth creating a new module
% just for them.)
%

	% A tag should be a small non-negative integer.
:- type tag == int.

	% See the definition in llds.m for comments about the meaning
	% of the `base_data' type.
	% For some targets, the target language and runtime system might
	% provide all the necessary information about type layouts,
	% in which case we won't need to define the type_functors and
	% type_layout stuff, and we may also be able to use the language's
	% RTTI rather than defining the type_infos ourselves.
:- type base_data
	--->	info
	;	functors
	;	layout.

	% see runtime/mercury_trail.h
:- type reset_trail_reason
	--->	undo
	;	commit
	;	solve
	;	exception
	;	gc
	.

%-----------------------------------------------------------------------------%

:- type mlds__qualified_proc_label
	==	mlds__fully_qualified_name(mlds__proc_label).
:- type mlds__proc_label
	==	pair(mlds__pred_label, proc_id).

:- type mlds__qualified_pred_label
	==	mlds__fully_qualified_name(mlds__pred_label).

	% An mlds__pred_label is a structure containing information that
	% uniquely identifies a HLDS predicate within a given module.
	%
	% Note that a predicate can have both a declaring and a defining module.
	% The defining module is the module that provides the code for the
	% predicate, the declaring module contains the `:- pred' declaration.
	% When these are different, as for specialised versions of predicates
	% from `.opt' files, the defining module's name is added as a
	% qualifier to the pred name.
:- type mlds__pred_label
	--->	pred(
			pred_or_func,		% predicate/function
				% The declaring module,
				% if different to the defining module
			maybe(mercury_module_name),
			string,			% name
			arity			% arity
		)
			
	;	special_pred(
			string,			% pred name
			maybe(mercury_module_name),
				% The module declaring the type,
				% if this is different to module defining
				% the special_pred.
			string,			% the type name
			arity			% the type arity
		).

%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%

:- implementation.
:- import_module int, term, require.

%-----------------------------------------------------------------------------%

mlds__get_module_name(mlds(ModuleName, _, _, _)) = ModuleName.

%-----------------------------------------------------------------------------%

% Currently mlds__contexts just contain a prog_context.

:- type mlds__context ---> mlds__context(prog_context).

mlds__make_context(Context) = mlds__context(Context).

mlds__get_prog_context(mlds__context(Context)) = Context.

%-----------------------------------------------------------------------------%

% Currently mlds__types are just the same as Mercury types.
% XXX something more complicated may be needed here...

mercury_type_to_mlds_type(Type) = mercury_type(Type).

%-----------------------------------------------------------------------------%

mlds__get_func_signature(func_params(Parameters, RetTypes)) =
		func_signature(ParamTypes, RetTypes) :-
	assoc_list__values(Parameters, ParamTypes).

%-----------------------------------------------------------------------------%

% Mercury module names are the same as MLDS package names, except that
% modules in the Mercury standard library map get a `mercury' prefix
% e.g. `mercury.builtin', `mercury.io', `mercury.std_util', etc.,
% when mapped to MLDS package names.

:- type mlds_module_name == prog_data__module_name.

mercury_module_name_to_mlds(MercuryModule) = MLDS_Package :-
	(
		MercuryModule = unqualified(ModuleName),
		mercury_std_library_module(ModuleName)
	->
		MLDS_Package = qualified(unqualified("mercury"), ModuleName)
	;
		MLDS_Package = MercuryModule
	).

:- pred mercury_std_library_module(string::in) is semidet.
mercury_std_library_module("array").
mercury_std_library_module("assoc_list").
mercury_std_library_module("bag").
mercury_std_library_module("benchmarking").
mercury_std_library_module("bimap").
mercury_std_library_module("bintree").
mercury_std_library_module("bintree_set").
mercury_std_library_module("bool").
mercury_std_library_module("bt_array").
mercury_std_library_module("builtin").
mercury_std_library_module("char").
mercury_std_library_module("dir").
mercury_std_library_module("eqvclass").
mercury_std_library_module("exception").
mercury_std_library_module("float").
mercury_std_library_module("gc").
mercury_std_library_module("getopt").
mercury_std_library_module("graph").
mercury_std_library_module("group").
mercury_std_library_module("int").
mercury_std_library_module("integer").
mercury_std_library_module("io").
mercury_std_library_module("lexer").
mercury_std_library_module("library").
mercury_std_library_module("list").
mercury_std_library_module("map").
mercury_std_library_module("math").
mercury_std_library_module("mercury_builtin").
mercury_std_library_module("multi_map").
mercury_std_library_module("ops").
mercury_std_library_module("parser").
mercury_std_library_module("pqueue").
mercury_std_library_module("private_builtin").
mercury_std_library_module("prolog").
mercury_std_library_module("queue").
mercury_std_library_module("random").
mercury_std_library_module("rational").
mercury_std_library_module("rbtree").
mercury_std_library_module("relation").
mercury_std_library_module("require").
mercury_std_library_module("set").
mercury_std_library_module("set_bbbtree").
mercury_std_library_module("set_ordlist").
mercury_std_library_module("set_unordlist").
mercury_std_library_module("stack").
mercury_std_library_module("std_util").
mercury_std_library_module("store").
mercury_std_library_module("string").
mercury_std_library_module("term").
mercury_std_library_module("term_io").
mercury_std_library_module("time").
mercury_std_library_module("tree234").
mercury_std_library_module("varset").

mlds_module_name_to_sym_name(MLDS_Package) = MLDS_Package.

%-----------------------------------------------------------------------------%

%
% We represent the set of declaration flags as a bunch of bit-fields packed
% into a single int.
%
:- type mlds__decl_flags == int.

%
% Here we define which bits are used to store each bitfield.
%
% It would be nicer to use a language builtin, e.g. index/2, for these.
% But currently builtin__index/2 does not work in the reverse mode,
% and you can't use std_util__construct/4 since that numbers the
% alternatives in a different order than builtin__index/2.
%
% It would also be nice to use a typeclass:
%	:- typeclass bitfield(T) where [
%		func bits(T) = int,
%		func mask(T::unused) = (int::out) is det
%	].
% But currently that is too cumbersome, since you can't define class
% methods inline.
%
% On the other hand, doing it manually may be more efficient than either
% of those two approaches.
%

:- func access_bits(access) = int.
:- mode access_bits(in) = out is det.
:- mode access_bits(out) = in is semidet.
access_bits(public)  	= 0x00.
access_bits(private) 	= 0x01.
access_bits(protected)	= 0x02.
access_bits(default)	= 0x03.
% 0x4 - 0x7 reserved

:- func access_mask = int.
access_mask = 0x07.

:- func per_instance_bits(per_instance) = int.
:- mode per_instance_bits(in) = out is det.
:- mode per_instance_bits(out) = in is semidet.
per_instance_bits(one_copy) 	= 0x00.
per_instance_bits(per_instance)	= 0x08.

:- func per_instance_mask = int.
per_instance_mask = per_instance_bits(per_instance).

:- func virtuality_bits(virtuality) = int.
:- mode virtuality_bits(in) = out is det.
:- mode virtuality_bits(out) = in is semidet.
virtuality_bits(non_virtual) 	= 0x00.
virtuality_bits(virtual)	= 0x10.

:- func virtuality_mask = int.
virtuality_mask = virtuality_bits(virtual).

:- func finality_bits(finality) = int.
:- mode finality_bits(in) = out is det.
:- mode finality_bits(out) = in is semidet.
finality_bits(overridable) 	= 0x00.
finality_bits(final)		= 0x20.

:- func finality_mask = int.
finality_mask = finality_bits(final).

:- func constness_bits(constness) = int.
:- mode constness_bits(in) = out is det.
:- mode constness_bits(out) = in is semidet.
constness_bits(modifiable) 	= 0x00.
constness_bits(const)		= 0x40.

:- func constness_mask = int.
constness_mask = constness_bits(const).

:- func abstractness_bits(abstractness) = int.
:- mode abstractness_bits(in) = out is det.
:- mode abstractness_bits(out) = in is semidet.
abstractness_bits(abstract) 	= 0x00.
abstractness_bits(concrete)	= 0x80.

:- func abstractness_mask = int.
abstractness_mask = abstractness_bits(concrete).

%
% Here we define the functions to lookup a member of the set.
%

access(Flags) = promise_det(pred(Access::out) is semidet :-
	Flags /\ access_mask = access_bits(Access)).

per_instance(Flags) = promise_det(pred(PerInstance::out) is semidet :-
	Flags /\ per_instance_mask = per_instance_bits(PerInstance)).

virtuality(Flags) = promise_det(pred(Virtuality::out) is semidet :-
	Flags /\ virtuality_mask = virtuality_bits(Virtuality)).

finality(Flags) = promise_det(pred(Finality::out) is semidet :-
	Flags /\ finality_mask = finality_bits(Finality)).

constness(Flags) = promise_det(pred(Constness::out) is semidet :-
	Flags /\ constness_mask = constness_bits(Constness)).

abstractness(Flags) = promise_det(pred(Abstractness::out) is semidet :-
	Flags /\ abstractness_mask = abstractness_bits(Abstractness)).

:- func promise_det(pred(T)) = T.
:- mode promise_det(pred(out) is semidet) = out is det.

promise_det(Pred) = X :-
	(if Pred(X0) then X = X0 else error("promise_det failed")).


%
% Here we define the functions to set a member of the set.
%

set_access(Flags, Access) =
	Flags /\ \access_mask \/ access_bits(Access).

set_per_instance(Flags, PerInstance) =
	Flags /\ \per_instance_mask \/ per_instance_bits(PerInstance).

set_virtuality(Flags, Virtuality) =
	Flags /\ \virtuality_mask \/ virtuality_bits(Virtuality).

set_finality(Flags, Finality) =
	Flags /\ \finality_mask \/ finality_bits(Finality).

set_constness(Flags, Constness) =
	Flags /\ \constness_mask \/ constness_bits(Constness).

set_abstractness(Flags, Abstractness) =
	Flags /\ \abstractness_mask \/ abstractness_bits(Abstractness).

init_decl_flags(Access, PerInstance, Virtuality, Finality, Constness,
		Abstractness) =
	access_bits(Access) \/
	per_instance_bits(PerInstance) \/
	virtuality_bits(Virtuality) \/
	finality_bits(Finality) \/
	constness_bits(Constness) \/
	abstractness_bits(Abstractness).

%-----------------------------------------------------------------------------%