1 (* decl.mod declaration nodes used to create the AST.
3 Copyright (C) 2015-2024 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius@glam.ac.uk>.
6 This file is part of GNU Modula-2.
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Modula-2; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. *)
22 IMPLEMENTATION MODULE decl
; (*!m2pim*)
24 FROM ASCII
IMPORT lf
, tab
;
25 FROM symbolKey
IMPORT NulKey
, symbolTree
, initTree
, getSymKey
, putSymKey
, foreachNodeDo
;
26 FROM mcDebug
IMPORT assert
;
27 FROM Storage
IMPORT ALLOCATE
, DEALLOCATE
;
28 FROM nameKey
IMPORT NulName
, makeKey
, lengthKey
, makekey
, keyToCharStar
;
29 FROM SFIO
IMPORT OpenToWrite
, WriteS
;
30 FROM FIO
IMPORT File
, Close
, FlushBuffer
, StdOut
, WriteLine
, WriteChar
;
31 FROM DynamicStrings
IMPORT String
, InitString
, EqualArray
, InitStringCharStar
, KillString
, ConCat
, Mark
, RemoveWhitePostfix
, RemoveWhitePrefix
;
32 FROM StringConvert
IMPORT CardinalToString
, ostoc
;
34 FROM mcOptions
IMPORT getOutputFile
, getDebugTopological
, getHPrefix
, getIgnoreFQ
,
35 getExtendedOpaque
, writeGPLheader
, getGccConfigSystem
,
36 getScaffoldDynamic
, getScaffoldMain
, getSuppressNoReturn
,
37 useBool
, getCRealType
, getCShortRealType
,
40 FROM FormatStrings
IMPORT Sprintf0
, Sprintf1
, Sprintf2
, Sprintf3
;
41 FROM libc
IMPORT printf
, memset
;
42 FROM mcMetaError
IMPORT metaError1
, metaError2
, metaError3
, metaErrors1
, metaErrors2
;
43 FROM mcError
IMPORT errorAbort0
, flushErrors
;
45 FROM mcLexBuf
IMPORT findFileNameFromToken
, tokenToLineNo
, tokenToColumnNo
,
46 getProcedureComment
, getBodyComment
, getAfterComment
,
49 FROM mcComment
IMPORT commentDesc
, isProcedureComment
, isAfterComment
, isBodyComment
, getContent
, initComment
, addText
;
51 FROM StrLib
IMPORT StrEqual
, StrLen
;
53 FROM mcPretty
IMPORT pretty
, initPretty
, dupPretty
, killPretty
, print
, prints
, raw
,
54 setNeedSpace
, noSpace
, setindent
, getindent
, getcurpos
,
55 getseekpos
, getcurline
,
56 pushPretty
, popPretty
;
58 FROM Indexing
IMPORT Index
, InitIndex
, ForeachIndiceInIndexDo
,
59 IncludeIndiceIntoIndex
, IsIndiceInIndex
,
60 HighIndice
, LowIndice
, GetIndice
, RemoveIndiceFromIndex
,
63 IMPORT DynamicStrings
;
64 IMPORT alists
, wlists
;
68 FROM alists
IMPORT alist
;
69 FROM wlists
IMPORT wlist
;
77 caseException
= TRUE ;
78 returnException
= TRUE ;
79 (* this is a work around to avoid ever having to handle dangling else. *)
80 forceCompoundStatement
= TRUE ; (* TRUE will avoid dangling else, by always using {}. *)
81 enableDefForCStrings
= FALSE ; (* currently disabled. *)
82 enableMemsetOnAllocation
= TRUE ; (* Should we memset (..., 0, ...) the allocated mem? *)
83 forceQualified
= TRUE ;
87 language
= (ansiC
, ansiCP
, pim4
) ;
89 nodeT
= (explist
, funccall
,
90 exit
, return
, stmtseq
, comment
, halt
,
91 new
, dispose
, inc
, dec
, incl
, excl
,
96 address
, loc
, byte
, word
,
100 cardinal
, longcard
, shortcard
,
101 integer
, longint
, shortint
,
102 real
, longreal
, shortreal
,
103 bitset
, boolean
, proc
,
105 complex
, longcomplex
, shortcomplex
,
106 (* language features and compound type attributes. *)
107 type
, record
, varient
, var
, enumeration
,
108 subrange
, array
, subscript
,
109 string
, const
, literal
, varparam
, param
, varargs
, optarg
,
110 pointer
, recordfield
, varientfield
, enumerationfield
,
113 procedure
, def
, imp
, module
,
115 loop
, while
, for
, repeat
,
116 case
, caselabellist
, caselist
, range
,
123 plus
, sub
, div
, mod
, mult
, divide
, in
,
124 adr
, size
, tsize
, ord
, float
, trunc
, chr
, abs
, cap
,
125 high
, throw
, unreachable
,
128 componentref
, pointerref
, arrayref
, deref
,
129 equal
, notequal
, less
, greater
, greequal
, lessequal
,
130 lsl
, lsr
, lor
, land
, lnot
, lxor
,
131 and
, or
, not
, identlist
, vardecl
, setvalue
, opaquecast
) ;
133 node
= POINTER TO nodeRec
;
146 halt
: intrinsicF
: intrinsicT |
147 explist
: explistF
: explistT |
148 exit
: exitF
: exitT |
149 return
: returnF
: returnT |
150 stmtseq
: stmtF
: stmtT |
151 comment
: commentF
: commentT |
152 (* base constants. *)
182 (* language features and compound type attributes. *)
183 type
: typeF
: typeT |
184 record
: recordF
: recordT |
185 varient
: varientF
: varientT |
187 enumeration
: enumerationF
: enumerationT |
188 subrange
: subrangeF
: subrangeT |
189 subscript
: subscriptF
: subscriptT |
190 array
: arrayF
: arrayT |
191 string
: stringF
: stringT |
192 const
: constF
: constT |
193 literal
: literalF
: literalT |
194 varparam
: varparamF
: varparamT |
195 param
: paramF
: paramT |
196 varargs
: varargsF
: varargsT |
197 optarg
: optargF
: optargT |
198 pointer
: pointerF
: pointerT |
199 recordfield
: recordfieldF
: recordfieldT |
200 varientfield
: varientfieldF
: varientfieldT |
201 enumerationfield
: enumerationfieldF
: enumerationfieldT |
203 proctype
: proctypeF
: proctypeT |
205 procedure
: procedureF
: procedureT |
208 module
: moduleF
: moduleT |
210 loop
: loopF
: loopT |
211 while
: whileF
: whileT |
213 repeat
: repeatF
: repeatT |
214 case
: caseF
: caseT |
215 caselabellist
: caselabellistF
: caselabellistT |
216 caselist
: caselistF
: caselistT |
217 range
: rangeF
: rangeT |
219 elsif
: elsifF
: elsifT |
220 assignment
: assignmentF
: assignmentT |
222 arrayref
: arrayrefF
: arrayrefT |
223 pointerref
: pointerrefF
: pointerrefT |
224 componentref
: componentrefF
: componentrefT |
242 in
: binaryF
: binaryT |
260 max
: unaryF
: unaryT |
261 identlist
: identlistF
: identlistT |
262 vardecl
: vardeclF
: vardeclT |
263 funccall
: funccallF
: funccallT |
264 setvalue
: setvalueF
: setvalueT |
265 opaquecast
: opaquecastF
: opaquecastT
271 opaqueCastState
= RECORD
277 (* Describes the cast of the opaque. *)
279 opaqueState
: opaqueCastState
;
286 intrinsicComment
: commentPair
;
287 postUnreachable
: BOOLEAN ;
313 funccallComment
: commentPair
;
314 opaqueState
: opaqueCastState
;
318 content
: commentDesc
;
328 returnComment
: commentPair
;
347 isInternal
: BOOLEAN ;
351 localSymbols
: symbolTree
;
373 opaqueState
: opaqueCastState
;
376 enumerationT
= RECORD
377 noOfElements
: CARDINAL ;
378 localSymbols
: symbolTree
;
400 isUnbounded
: BOOLEAN ;
401 opaqueState
: opaqueCastState
;
407 isCharCompatible
: BOOLEAN ;
429 isUnbounded
: BOOLEAN ;
432 opaqueState
: opaqueCastState
;
439 isUnbounded
: BOOLEAN ;
442 opaqueState
: opaqueCastState
;
459 opaqueState
: opaqueCastState
;
462 recordfieldT
= RECORD
470 opaqueState
: opaqueCastState
;
473 varientfieldT
= RECORD
482 enumerationfieldT
= RECORD
495 componentrefT
= RECORD
499 opaqueState
: opaqueCastState
;
506 opaqueState
: opaqueCastState
;
513 opaqueState
: opaqueCastState
;
524 assignComment
: commentPair
;
529 elsif
, (* either else or elsif must be NIL. *)
533 elseComment
, (* used for else or elsif *)
534 endComment
: commentPair
;
539 elsif
, (* either else or elsif must be NIL. *)
542 elseComment
: commentPair
; (* used for else or elsif *)
547 labelno
: CARDINAL ; (* 0 means no label. *)
554 endComment
: commentPair
;
561 untilComment
: commentPair
;
566 caseLabelList
: Index
;
570 caselabellistT
= RECORD
597 symbols
: symbolTree
;
616 paramcount
: CARDINAL ;
619 beginStatements
: node
;
622 modComment
: commentDesc
;
623 opaqueState
: opaqueCastState
;
633 opaqueState
: opaqueCastState
;
650 importedModules
: Index
;
652 enumFixup
: fixupInfo
;
655 finallyStatements
: node
;
669 importedModules
: Index
;
671 enumFixup
: fixupInfo
;
682 importedModules
: Index
;
684 enumFixup
: fixupInfo
;
686 finallyStatements
: node
;
687 definitionModule
: node
;
698 firstUsed
: CARDINAL ;
701 outputStates
= (text
, punct
, space
) ;
703 nodeProcedure
= PROCEDURE (node
) ;
705 dependentState
= (completed
, blocked
, partial
, recursive
) ;
712 group
= POINTER TO RECORD
722 globalGroup
: group
; (* The global group of all alists. *)
791 modUniverseI
: Index
;
793 defUniverse
: symbolTree
;
794 baseSymbols
: symbolTree
;
795 outputState
: outputStates
;
798 simplified
: BOOLEAN ;
799 tempCount
: CARDINAL ;
803 newNode - create and return a new node of kind k.
806 PROCEDURE newNode (k
: nodeT
) : node
;
811 IF enableMemsetOnAllocation
813 d
:= memset (d
, 0, SIZE (d^
))
820 d^.at.defDeclared
:= 0 ;
821 d^.at.modDeclared
:= 0 ;
822 d^.at.firstUsed
:= 0 ;
829 disposeNode - dispose node, n.
832 PROCEDURE disposeNode (VAR n
: node
) ;
843 PROCEDURE newGroup (VAR g
: group
) ;
850 freeGroup
:= freeGroup^.next
856 initGroup - returns a group which with all lists initialized.
859 PROCEDURE initGroup () : group
;
865 todoQ
:= alists.
initList () ;
866 partialQ
:= alists.
initList () ;
867 doneQ
:= alists.
initList () ;
875 killGroup - deallocate the group and place the group record into the freeGroup list.
878 PROCEDURE killGroup (VAR g
: group
) ;
880 alists.
killList (g^.todoQ
) ;
881 alists.
killList (g^.partialQ
) ;
882 alists.
killList (g^.doneQ
) ;
883 g^.next
:= freeGroup
;
889 dupGroup - If g is not NIL then destroy g.
890 Return a duplicate of GlobalGroup (not g).
893 PROCEDURE dupGroup (g
: group
) : group
;
897 (* Kill old group. *)
902 (* Copy all lists. *)
903 todoQ
:= alists.
duplicateList (globalGroup^.todoQ
) ;
904 partialQ
:= alists.
duplicateList (globalGroup^.partialQ
) ;
905 doneQ
:= alists.
duplicateList (globalGroup^.doneQ
) ;
913 equalGroup - return TRUE if group left = right.
916 PROCEDURE equalGroup (left
, right
: group
) : BOOLEAN ;
918 RETURN ((left
= right
) OR
919 (alists.
equalList (left^.todoQ
, right^.todoQ
) AND
920 alists.
equalList (left^.partialQ
, right^.partialQ
) AND
921 alists.
equalList (left^.doneQ
, right^.doneQ
)))
926 getDeclaredDef - returns the token number associated with the nodes declaration
927 in the definition module.
930 PROCEDURE getDeclaredDef (n
: node
) : CARDINAL ;
932 RETURN n^.at.defDeclared
937 getDeclaredMod - returns the token number associated with the nodes declaration
938 in the implementation or program module.
941 PROCEDURE getDeclaredMod (n
: node
) : CARDINAL ;
943 RETURN n^.at.modDeclared
948 getFirstUsed - returns the token number associated with the first use of
952 PROCEDURE getFirstUsed (n
: node
) : CARDINAL ;
954 RETURN n^.at.firstUsed
959 setVisited - set the visited flag on a def/imp/module node.
962 PROCEDURE setVisited (n
: node
) ;
966 def
: n^.defF.visited
:= TRUE |
967 imp
: n^.impF.visited
:= TRUE |
968 module
: n^.moduleF.visited
:= TRUE
975 unsetVisited - unset the visited flag on a def/imp/module node.
978 PROCEDURE unsetVisited (n
: node
) ;
982 def
: n^.defF.visited
:= FALSE |
983 imp
: n^.impF.visited
:= FALSE |
984 module
: n^.moduleF.visited
:= FALSE
991 isVisited - returns TRUE if the node was visited.
994 PROCEDURE isVisited (n
: node
) : BOOLEAN ;
998 def
: RETURN n^.defF.visited |
999 imp
: RETURN n^.impF.visited |
1000 module
: RETURN n^.moduleF.visited
1007 isDef - return TRUE if node, n, is a definition module.
1010 PROCEDURE isDef (n
: node
) : BOOLEAN ;
1013 RETURN n^.kind
= def
1018 isImp - return TRUE if node, n, is an implementation module.
1021 PROCEDURE isImp (n
: node
) : BOOLEAN ;
1024 RETURN n^.kind
= imp
1029 isModule - return TRUE if node, n, is a program module.
1032 PROCEDURE isModule (n
: node
) : BOOLEAN ;
1035 RETURN n^.kind
= module
1040 isImpOrModule - returns TRUE if, n, is a program module or implementation module.
1043 PROCEDURE isImpOrModule (n
: node
) : BOOLEAN ;
1045 RETURN isImp (n
) OR isModule (n
)
1050 isProcedure - returns TRUE if node, n, is a procedure.
1053 PROCEDURE isProcedure (n
: node
) : BOOLEAN ;
1056 RETURN n^.kind
= procedure
1061 isConst - returns TRUE if node, n, is a const.
1064 PROCEDURE isConst (n
: node
) : BOOLEAN ;
1067 RETURN n^.kind
= const
1072 isType - returns TRUE if node, n, is a type.
1075 PROCEDURE isType (n
: node
) : BOOLEAN ;
1078 RETURN n^.kind
= type
1083 isVar - returns TRUE if node, n, is a type.
1086 PROCEDURE isVar (n
: node
) : BOOLEAN ;
1089 RETURN n^.kind
= var
1094 isTemporary - returns TRUE if node, n, is a variable and temporary.
1097 PROCEDURE isTemporary (n
: node
) : BOOLEAN ;
1104 isExported - returns TRUE if symbol, n, is exported from
1105 the definition module.
1108 PROCEDURE isExported (n
: node
) : BOOLEAN ;
1117 def
: RETURN IsIndiceInIndex (s^.defF.exported
, n
)
1128 isLocal - returns TRUE if symbol, n, is locally declared in a procedure.
1131 PROCEDURE isLocal (n
: node
) : BOOLEAN ;
1138 RETURN isProcedure (s
)
1145 lookupExported - attempts to lookup a node named, i, from definition
1146 module, n. The node is returned if found.
1147 NIL is returned if not found.
1150 PROCEDURE lookupExported (n
: node
; i
: Name
) : node
;
1154 assert (isDef (n
)) ;
1155 r
:= getSymKey (n^.defF.decls.symbols
, i
) ;
1156 IF (r#
NIL) AND isExported (r
)
1161 END lookupExported
;
1165 importEnumFields - if, n, is an enumeration type import the all fields into module, m.
1168 PROCEDURE importEnumFields (m
, n
: node
) ;
1173 assert (isDef (m
) OR isModule (m
) OR isImp (m
)) ;
1175 IF (n#
NIL) AND isEnumeration (n
)
1177 i
:= LowIndice (n^.enumerationF.listOfSons
) ;
1178 h
:= HighIndice (n^.enumerationF.listOfSons
) ;
1180 e
:= GetIndice (n^.enumerationF.listOfSons
, i
) ;
1181 r
:= import (m
, e
) ;
1184 metaError2 ('enumeration field {%1ad} cannot be imported implicitly into {%2d} due to a name clash',
1190 END importEnumFields
;
1194 checkGccType - check to see if node n is gcc tree or location_t
1195 and record its use in keyc.
1198 PROCEDURE checkGccType (n
: node
) ;
1200 IF getGccConfigSystem () AND (getScope (n
) #
NIL) AND
1201 (getSymName (getScope (n
)) = makeKey ('gcctypes'))
1203 IF getSymName (n
) = makeKey ('location_t')
1206 ELSIF getSymName (n
) = makeKey ('tree')
1215 checkCDataTypes - check to see if node n is CharStar or ConstCharStar
1216 and if necessary assign n to the global variable.
1219 PROCEDURE checkCDataTypes (n
: node
) ;
1221 IF (getScope (n
) #
NIL) AND (getSymName (getScope (n
)) = makeKey ('CDataTypes'))
1223 IF getSymName (n
) = makeKey ('CharStar')
1226 ELSIF getSymName (n
) = makeKey ('ConstCharStar')
1231 END checkCDataTypes
;
1235 import - attempts to add node, n, into the scope of module, m.
1236 It might fail due to a name clash in which case the
1237 previous named symbol is returned. On success, n,
1241 PROCEDURE import (m
, n
: node
) : node
;
1246 assert (isDef (m
) OR isModule (m
) OR isImp (m
)) ;
1247 name
:= getSymName (n
) ;
1249 checkCDataTypes (n
) ;
1250 r
:= lookupInScope (m
, name
) ;
1255 def
: putSymKey (m^.defF.decls.symbols
, name
, n
) |
1256 imp
: putSymKey (m^.impF.decls.symbols
, name
, n
) |
1257 module
: putSymKey (m^.moduleF.decls.symbols
, name
, n
)
1260 importEnumFields (m
, n
) ;
1268 isZtype - returns TRUE if, n, is the Z type.
1271 PROCEDURE isZtype (n
: node
) : BOOLEAN ;
1278 isRtype - returns TRUE if, n, is the R type.
1281 PROCEDURE isRtype (n
: node
) : BOOLEAN ;
1288 isComplex - returns TRUE if, n, is the complex type.
1291 PROCEDURE isComplex (n
: node
) : BOOLEAN ;
1298 isLongComplex - returns TRUE if, n, is the longcomplex type.
1301 PROCEDURE isLongComplex (n
: node
) : BOOLEAN ;
1303 RETURN n
= longcomplexN
1308 isShortComplex - returns TRUE if, n, is the shortcomplex type.
1311 PROCEDURE isShortComplex (n
: node
) : BOOLEAN ;
1313 RETURN n
= shortcomplexN
1314 END isShortComplex
;
1318 isLiteral - returns TRUE if, n, is a literal.
1321 PROCEDURE isLiteral (n
: node
) : BOOLEAN ;
1324 RETURN n^.kind
= literal
1329 isConstSet - returns TRUE if, n, is a constant set.
1332 PROCEDURE isConstSet (n
: node
) : BOOLEAN ;
1335 IF isLiteral (n
) OR isConst (n
)
1337 RETURN isSet (skipType (getType (n
)))
1344 isEnumerationField - returns TRUE if, n, is an enumeration field.
1347 PROCEDURE isEnumerationField (n
: node
) : BOOLEAN ;
1350 RETURN n^.kind
= enumerationfield
1351 END isEnumerationField
;
1355 isUnbounded - returns TRUE if, n, is an unbounded array.
1358 PROCEDURE isUnbounded (n
: node
) : BOOLEAN ;
1361 RETURN (n^.kind
= array
) AND (n^.arrayF.isUnbounded
)
1366 isParameter - returns TRUE if, n, is a parameter.
1369 PROCEDURE isParameter (n
: node
) : BOOLEAN ;
1372 RETURN (n^.kind
= param
) OR (n^.kind
= varparam
)
1377 isVarParam - returns TRUE if, n, is a var parameter.
1380 PROCEDURE isVarParam (n
: node
) : BOOLEAN ;
1383 RETURN n^.kind
= varparam
1388 isParam - returns TRUE if, n, is a non var parameter.
1391 PROCEDURE isParam (n
: node
) : BOOLEAN ;
1394 RETURN n^.kind
= param
1399 isNonVarParam - is an alias to isParam.
1402 PROCEDURE isNonVarParam (n
: node
) : BOOLEAN ;
1409 isRecord - returns TRUE if, n, is a record.
1412 PROCEDURE isRecord (n
: node
) : BOOLEAN ;
1415 RETURN n^.kind
= record
1420 isRecordField - returns TRUE if, n, is a record field.
1423 PROCEDURE isRecordField (n
: node
) : BOOLEAN ;
1426 RETURN n^.kind
= recordfield
1431 isArray - returns TRUE if, n, is an array.
1434 PROCEDURE isArray (n
: node
) : BOOLEAN ;
1437 RETURN n^.kind
= array
1442 isProcType - returns TRUE if, n, is a procedure type.
1445 PROCEDURE isProcType (n
: node
) : BOOLEAN ;
1448 RETURN n^.kind
= proctype
1453 isAProcType - returns TRUE if, n, is a proctype or proc node.
1456 PROCEDURE isAProcType (n
: node
) : BOOLEAN ;
1459 RETURN isProcType (n
) OR (n
= procN
)
1464 isProcedure - returns TRUE if, n, is a procedure.
1467 PROCEDURE isProcedure (n
: node
) : BOOLEAN ;
1470 RETURN n^.kind
= procedure
1475 isPointer - returns TRUE if, n, is a pointer.
1478 PROCEDURE isPointer (n
: node
) : BOOLEAN ;
1481 RETURN n^.kind
= pointer
1486 isVarient - returns TRUE if, n, is a varient record.
1489 PROCEDURE isVarient (n
: node
) : BOOLEAN ;
1492 RETURN n^.kind
= varient
1497 isVarientField - returns TRUE if, n, is a varient field.
1500 PROCEDURE isVarientField (n
: node
) : BOOLEAN ;
1503 RETURN n^.kind
= varientfield
1504 END isVarientField
;
1508 isSet - returns TRUE if, n, is a set type.
1511 PROCEDURE isSet (n
: node
) : BOOLEAN ;
1514 RETURN n^.kind
= set
1519 isSubrange - returns TRUE if, n, is a subrange type.
1522 PROCEDURE isSubrange (n
: node
) : BOOLEAN ;
1525 RETURN n^.kind
= subrange
1530 isMainModule - return TRUE if node, n, is the main module specified
1531 by the source file. This might be a definition,
1532 implementation or program module.
1535 PROCEDURE isMainModule (n
: node
) : BOOLEAN ;
1538 RETURN n
= mainModule
1543 setMainModule - sets node, n, as the main module to be compiled.
1546 PROCEDURE setMainModule (n
: node
) ;
1554 getMainModule - returns the main module node.
1557 PROCEDURE getMainModule () : node
;
1564 setCurrentModule - sets node, n, as the current module being compiled.
1567 PROCEDURE setCurrentModule (n
: node
) ;
1571 END setCurrentModule
;
1575 getCurrentModule - returns the current module being compiled.
1578 PROCEDURE getCurrentModule () : node
;
1580 RETURN currentModule
1581 END getCurrentModule
;
1585 initFixupInfo - initialize the fixupInfo record.
1588 PROCEDURE initFixupInfo () : fixupInfo
;
1593 f.info
:= InitIndex (1) ;
1599 makeDef - returns a definition module node named, n.
1602 PROCEDURE makeDef (n
: Name
) : node
;
1606 d
:= newNode (def
) ;
1609 defF.source
:= NulName
;
1610 defF.hasHidden
:= FALSE ;
1611 defF.forC
:= FALSE ;
1612 defF.unqualified
:= FALSE ;
1613 defF.exported
:= InitIndex (1) ;
1614 defF.importedModules
:= InitIndex (1) ;
1615 defF.constFixup
:= initFixupInfo () ;
1616 defF.enumFixup
:= initFixupInfo () ;
1617 initDecls (defF.decls
) ;
1618 defF.enumsComplete
:= FALSE ;
1619 defF.constsComplete
:= FALSE ;
1620 defF.visited
:= FALSE ;
1628 makeImp - returns an implementation module node named, n.
1631 PROCEDURE makeImp (n
: Name
) : node
;
1635 d
:= newNode (imp
) ;
1638 impF.source
:= NulName
;
1639 impF.importedModules
:= InitIndex (1) ;
1640 impF.constFixup
:= initFixupInfo () ;
1641 impF.enumFixup
:= initFixupInfo () ;
1642 initDecls (impF.decls
) ;
1643 impF.beginStatements
:= NIL ;
1644 impF.finallyStatements
:= NIL ;
1645 impF.definitionModule
:= NIL ;
1646 impF.enumsComplete
:= FALSE ;
1647 impF.constsComplete
:= FALSE ;
1648 impF.visited
:= FALSE ;
1656 makeModule - returns a module node named, n.
1659 PROCEDURE makeModule (n
: Name
) : node
;
1663 d
:= newNode (module
) ;
1666 moduleF.source
:= NulName
;
1667 moduleF.importedModules
:= InitIndex (1) ;
1668 moduleF.constFixup
:= initFixupInfo () ;
1669 moduleF.enumFixup
:= initFixupInfo () ;
1670 initDecls (moduleF.decls
) ;
1671 moduleF.beginStatements
:= NIL ;
1672 moduleF.finallyStatements
:= NIL ;
1673 moduleF.enumsComplete
:= FALSE ;
1674 moduleF.constsComplete
:= FALSE ;
1675 moduleF.visited
:= FALSE ;
1676 initPair (moduleF.com
)
1683 putDefForC - the definition module was defined FOR "C".
1686 PROCEDURE putDefForC (n
: node
) ;
1688 assert (isDef (n
)) ;
1689 n^.defF.forC
:= TRUE
1694 isDefForC - returns TRUE if the definition module was defined FOR "C".
1697 PROCEDURE isDefForC (n
: node
) : BOOLEAN ;
1699 RETURN isDef (n
) AND n^.defF.forC
1704 putDefUnqualified - the definition module uses unqualified.
1707 PROCEDURE putDefUnqualified (n
: node
) ;
1709 assert (isDef (n
)) ;
1710 (* Currently (and this is a temporary development restriction to
1711 reduce any search space for bugs) the only module which can be
1712 export unqualified is gcctypes. *)
1713 IF n^.defF.name
= makeKey ('gcctypes')
1715 n^.defF.unqualified
:= TRUE
1717 END putDefUnqualified
;
1721 isDefUnqualified - returns TRUE if the definition module uses unqualified.
1724 PROCEDURE isDefUnqualified (n
: node
) : BOOLEAN ;
1726 RETURN isDef (n
) AND n^.defF.unqualified
1727 END isDefUnqualified
;
1731 lookupDef - returns a definition module node named, n.
1734 PROCEDURE lookupDef (n
: Name
) : node
;
1738 d
:= getSymKey (defUniverse
, n
) ;
1742 putSymKey (defUniverse
, n
, d
) ;
1743 IncludeIndiceIntoIndex (defUniverseI
, d
)
1750 lookupImp - returns an implementation module node named, n.
1753 PROCEDURE lookupImp (n
: Name
) : node
;
1757 m
:= getSymKey (modUniverse
, n
) ;
1761 putSymKey (modUniverse
, n
, m
) ;
1762 IncludeIndiceIntoIndex (modUniverseI
, m
)
1764 assert (NOT isModule (m
)) ;
1770 lookupModule - returns a module node named, n.
1773 PROCEDURE lookupModule (n
: Name
) : node
;
1777 m
:= getSymKey (modUniverse
, n
) ;
1780 m
:= makeModule (n
) ;
1781 putSymKey (modUniverse
, n
, m
) ;
1782 IncludeIndiceIntoIndex (modUniverseI
, m
)
1784 assert (NOT isImp (m
)) ;
1790 setSource - sets the source filename for module, n, to s.
1793 PROCEDURE setSource (n
: node
; s
: Name
) ;
1798 def
: defF.source
:= s |
1799 module
: moduleF.source
:= s |
1800 imp
: impF.source
:= s
1808 getSource - returns the source filename for module, n.
1811 PROCEDURE getSource (n
: node
) : Name
;
1816 def
: RETURN defF.source |
1817 module
: RETURN moduleF.source |
1818 imp
: RETURN impF.source
1826 initDecls - initialize the decls, scopeT.
1829 PROCEDURE initDecls (VAR decls
: scopeT
) ;
1831 decls.symbols
:= initTree () ;
1832 decls.constants
:= InitIndex (1) ;
1833 decls.types
:= InitIndex (1) ;
1834 decls.procedures
:= InitIndex (1) ;
1835 decls.variables
:= InitIndex (1)
1840 enterScope - pushes symbol, n, to the scope stack.
1843 PROCEDURE enterScope (n
: node
) ;
1845 IF IsIndiceInIndex (scopeStack
, n
)
1849 IncludeIndiceIntoIndex (scopeStack
, n
)
1853 printf ("enter scope\n") ;
1860 leaveScope - removes the top level scope.
1863 PROCEDURE leaveScope
;
1868 i
:= HighIndice (scopeStack
) ;
1869 n
:= GetIndice (scopeStack
, i
) ;
1870 RemoveIndiceFromIndex (scopeStack
, n
) ;
1873 printf ("leave scope\n") ;
1880 getDeclScope - returns the node representing the
1881 current declaration scope.
1884 PROCEDURE getDeclScope () : node
;
1888 i
:= HighIndice (scopeStack
) ;
1889 RETURN GetIndice (scopeStack
, i
)
1894 addTo - adds node, d, to scope decls and returns, d.
1895 It stores, d, in the symbols tree associated with decls.
1898 PROCEDURE addTo (VAR decls
: scopeT
; d
: node
) : node
;
1902 n
:= getSymName (d
) ;
1905 IF getSymKey (decls.symbols
, n
)=NIL
1907 putSymKey (decls.symbols
, n
, d
)
1909 metaError1 ('{%1DMad} was declared', d
) ;
1910 metaError1 ('{%1k} and is being declared again', n
)
1915 IncludeIndiceIntoIndex (decls.constants
, d
)
1918 IncludeIndiceIntoIndex (decls.variables
, d
)
1921 IncludeIndiceIntoIndex (decls.types
, d
)
1922 ELSIF isProcedure (d
)
1924 IncludeIndiceIntoIndex (decls.procedures
, d
) ;
1927 printf ("%d procedures on the dynamic array\n",
1928 HighIndice (decls.procedures
))
1936 export - export node, n, from definition module, d.
1939 PROCEDURE export (d
, n
: node
) ;
1941 assert (isDef (d
)) ;
1942 IncludeIndiceIntoIndex (d^.defF.exported
, n
)
1947 addToScope - adds node, n, to the current scope and returns, n.
1950 PROCEDURE addToScope (n
: node
) : node
;
1955 i
:= HighIndice (scopeStack
) ;
1956 s
:= GetIndice (scopeStack
, i
) ;
1961 outText (doP
, "adding ") ;
1963 outText (doP
, " to procedure\n")
1965 RETURN addTo (s^.procedureF.decls
, n
)
1970 outText (doP
, "adding ") ;
1972 outText (doP
, " to module\n")
1974 RETURN addTo (s^.moduleF.decls
, n
)
1979 outText (doP
, "adding ") ;
1981 outText (doP
, " to definition module\n")
1984 RETURN addTo (s^.defF.decls
, n
)
1989 outText (doP
, "adding ") ;
1991 outText (doP
, " to implementation module\n")
1993 RETURN addTo (s^.impF.decls
, n
)
2000 addModuleToScope - adds module, i, to module, m, scope.
2003 PROCEDURE addModuleToScope (m
, i
: node
) ;
2005 assert (getDeclScope () = m
) ;
2006 IF lookupSym (getSymName (i
))=NIL
2010 END addModuleToScope
;
2014 addImportedModule - add module, i, to be imported by, m.
2015 If scoped then module, i, is added to the
2019 PROCEDURE addImportedModule (m
, i
: node
; scoped
: BOOLEAN) ;
2021 assert (isDef (i
) OR isModule (i
)) ;
2024 IncludeIndiceIntoIndex (m^.defF.importedModules
, i
)
2027 IncludeIndiceIntoIndex (m^.impF.importedModules
, i
)
2030 IncludeIndiceIntoIndex (m^.moduleF.importedModules
, i
)
2036 addModuleToScope (m
, i
)
2038 END addImportedModule
;
2042 completedEnum - assign boolean enumsComplete to TRUE if a definition,
2043 implementation or module symbol.
2046 PROCEDURE completedEnum (n
: node
) ;
2048 assert (isDef (n
) OR isImp (n
) OR isModule (n
)) ;
2051 n^.defF.enumsComplete
:= TRUE
2054 n^.impF.enumsComplete
:= TRUE
2057 n^.moduleF.enumsComplete
:= TRUE
2063 setUnary - sets a unary node to contain, arg, a, and type, t.
2066 PROCEDURE setUnary (u
: node
; k
: nodeT
; a
, t
: node
) ;
2088 max
: u^.kind
:= k
;
2089 u^.unaryF.arg
:= a
;
2090 u^.unaryF.resultType
:= t
2097 makeConst - create, initialise and return a const node.
2100 PROCEDURE makeConst (n
: Name
) : node
;
2104 d
:= newNode (const
) ;
2107 constF.type
:= NIL ;
2108 constF.scope
:= getDeclScope () ;
2111 RETURN addToScope (d
)
2116 makeType - create, initialise and return a type node.
2119 PROCEDURE makeType (n
: Name
) : node
;
2123 d
:= newNode (type
) ;
2127 typeF.scope
:= getDeclScope () ;
2128 typeF.isOpaque
:= FALSE ;
2129 typeF.isHidden
:= FALSE ;
2130 typeF.isInternal
:= FALSE
2132 RETURN addToScope (d
)
2137 makeTypeImp - lookup a type in the definition module
2138 and return it. Otherwise create a new type.
2141 PROCEDURE makeTypeImp (n
: Name
) : node
;
2145 d
:= lookupSym (n
) ;
2148 d^.typeF.isHidden
:= FALSE ;
2149 RETURN addToScope (d
)
2151 d
:= newNode (type
) ;
2155 typeF.scope
:= getDeclScope () ;
2156 typeF.isOpaque
:= FALSE ;
2157 typeF.isHidden
:= FALSE
2159 RETURN addToScope (d
)
2165 makeVar - create, initialise and return a var node.
2168 PROCEDURE makeVar (n
: Name
) : node
;
2172 d
:= newNode (var
) ;
2177 varF.scope
:= getDeclScope () ;
2178 varF.isInitialised
:= FALSE ;
2179 varF.isParameter
:= FALSE ;
2180 varF.isVarParameter
:= FALSE ;
2181 initCname (varF.cname
)
2183 RETURN addToScope (d
)
2188 putVar - places, type, as the type for var.
2191 PROCEDURE putVar (var
, type
, decl
: node
) ;
2194 assert (isVar (var
)) ;
2195 var^.varF.type
:= type
;
2196 var^.varF.decl
:= decl
;
2197 initNodeOpaqueState (var
) ;
2202 putVarBool - assigns the four booleans associated with a variable.
2205 PROCEDURE putVarBool (v
: node
; init
, param
, isvar
, isused
: BOOLEAN) ;
2207 assert (isVar (v
)) ;
2208 v^.varF.isInitialised
:= init
;
2209 v^.varF.isParameter
:= param
;
2210 v^.varF.isVarParameter
:= isvar
;
2211 v^.varF.isUsed
:= isused
2216 checkPtr - in C++ we need to create a typedef for a pointer
2217 in case we need to use reinterpret_cast.
2220 PROCEDURE checkPtr (n
: node
) : node
;
2230 p
:= makeType (makekey (DynamicStrings.
string (s
))) ;
2232 s
:= KillString (s
) ;
2241 makeVarDecl - create a vardecl node and create a shadow variable in the
2245 PROCEDURE makeVarDecl (i
: node
; type
: node
) : node
;
2250 type
:= checkPtr (type
) ;
2251 d
:= newNode (vardecl
) ;
2253 vardeclF.names
:= i^.identlistF.names
;
2254 vardeclF.type
:= type
;
2255 vardeclF.scope
:= getDeclScope ()
2257 n
:= wlists.
noOfItemsInList (d^.vardeclF.names
) ;
2260 v
:= lookupSym (wlists.
getItemFromList (d^.vardeclF.names
, j
)) ;
2261 assert (isVar (v
)) ;
2262 putVar (v
, type
, d
) ;
2270 isVarDecl - returns TRUE if, n, is a vardecl node.
2273 PROCEDURE isVarDecl (n
: node
) : BOOLEAN ;
2275 RETURN n^.kind
= vardecl
2280 makeVariablesFromParameters - creates variables which are really parameters.
2283 PROCEDURE makeVariablesFromParameters (proc
, id
, type
: node
; isvar
, isused
: BOOLEAN) ;
2290 assert (isProcedure (proc
)) ;
2291 assert (isIdentList (id
)) ;
2293 n
:= wlists.
noOfItemsInList (id^.identlistF.names
) ;
2295 m
:= wlists.
getItemFromList (id^.identlistF.names
, i
) ;
2297 putVar (v
, type
, NIL) ;
2298 putVarBool (v
, TRUE, TRUE, isvar
, isused
) ;
2301 printf ("adding parameter variable into top scope\n") ;
2303 printf (" variable name is: ") ;
2304 s
:= InitStringCharStar (keyToCharStar (m
)) ;
2305 IF KillString (WriteS (StdOut
, s
))=NIL
2312 END makeVariablesFromParameters
;
2316 addProcedureToScope - add a procedure name n and node d to the
2320 PROCEDURE addProcedureToScope (d
: node
; n
: Name
) : node
;
2325 i
:= HighIndice (scopeStack
) ;
2326 m
:= GetIndice (scopeStack
, i
) ;
2328 (getSymName (m
) = makeKey ('M2RTS')) AND
2329 (getSymName (d
) = makeKey ('HALT'))
2332 putSymKey (baseSymbols
, n
, haltN
)
2334 RETURN addToScope (d
)
2335 END addProcedureToScope
;
2339 makeProcedure - create, initialise and return a procedure node.
2342 PROCEDURE makeProcedure (n
: Name
) : node
;
2346 d
:= lookupSym (n
) ;
2349 d
:= newNode (procedure
) ;
2351 procedureF.name
:= n
;
2352 initDecls (procedureF.decls
) ;
2353 procedureF.scope
:= getDeclScope () ;
2354 procedureF.parameters
:= InitIndex (1) ;
2355 procedureF.isForC
:= isDefForCNode (getDeclScope ()) ;
2356 procedureF.built
:= FALSE ;
2357 procedureF.returnopt
:= FALSE ;
2358 procedureF.optarg
:= NIL ;
2359 procedureF.noreturnused
:= FALSE ;
2360 procedureF.noreturn
:= FALSE ;
2361 procedureF.vararg
:= FALSE ;
2362 procedureF.checking
:= FALSE ;
2363 procedureF.paramcount
:= 0 ;
2364 procedureF.returnType
:= NIL ;
2365 procedureF.beginStatements
:= NIL ;
2366 initCname (procedureF.cname
) ;
2367 procedureF.defComment
:= NIL ;
2368 procedureF.modComment
:= NIL ;
2371 RETURN addProcedureToScope (d
, n
)
2376 putCommentDefProcedure - remembers the procedure comment (if it exists) as a
2377 definition module procedure heading. NIL is placed
2378 if there is no procedure comment available.
2381 PROCEDURE putCommentDefProcedure (n
: node
) ;
2383 assert (isProcedure (n
)) ;
2384 IF isProcedureComment (lastcomment
)
2386 n^.procedureF.defComment
:= lastcomment
2388 END putCommentDefProcedure
;
2392 putCommentModProcedure - remembers the procedure comment (if it exists) as an
2393 implementation/program module procedure heading. NIL is placed
2394 if there is no procedure comment available.
2397 PROCEDURE putCommentModProcedure (n
: node
) ;
2399 assert (isProcedure (n
)) ;
2400 IF isProcedureComment (lastcomment
)
2402 n^.procedureF.modComment
:= lastcomment
2404 END putCommentModProcedure
;
2408 paramEnter - reset the parameter count.
2411 PROCEDURE paramEnter (n
: node
) ;
2413 assert (isProcedure (n
)) ;
2414 n^.procedureF.paramcount
:= 0
2419 paramLeave - set paramater checking to TRUE from now onwards.
2422 PROCEDURE paramLeave (n
: node
) ;
2424 assert (isProcedure (n
)) ;
2425 n^.procedureF.checking
:= TRUE ;
2426 IF isImp (currentModule
) OR isModule (currentModule
)
2428 n^.procedureF.built
:= TRUE
2434 putReturnType - sets the return type of procedure or proctype proc to type.
2437 PROCEDURE putReturnType (proc
, type
: node
) ;
2439 assert (isProcedure (proc
) OR isProcType (proc
)) ;
2440 IF isProcedure (proc
)
2442 proc^.procedureF.returnType
:= type
2444 proc^.proctypeF.returnType
:= type
2446 initNodeOpaqueState (proc
)
2451 putOptReturn - sets, proctype or procedure, proc, to have an optional return type.
2454 PROCEDURE putOptReturn (proc
: node
) ;
2456 assert (isProcedure (proc
) OR isProcType (proc
)) ;
2457 IF isProcedure (proc
)
2459 proc^.procedureF.returnopt
:= TRUE
2461 proc^.proctypeF.returnopt
:= TRUE
2467 makeProcType - returns a proctype node.
2470 PROCEDURE makeProcType () : node
;
2474 d
:= newNode (proctype
) ;
2476 proctypeF.scope
:= getDeclScope () ;
2477 proctypeF.parameters
:= InitIndex (1) ;
2478 proctypeF.returnopt
:= FALSE ;
2479 proctypeF.optarg
:= NIL ;
2480 proctypeF.vararg
:= FALSE ;
2481 proctypeF.returnType
:= NIL ;
2483 initNodeOpaqueState (d
) ;
2489 putProcTypeReturn - sets the return type of, proc, to, type.
2492 PROCEDURE putProcTypeReturn (proc
, type
: node
) ;
2494 assert (isProcType (proc
)) ;
2495 proc^.proctypeF.returnType
:= type
;
2496 initNodeOpaqueState (proc
)
2497 END putProcTypeReturn
;
2501 putProcTypeOptReturn - sets, proc, to have an optional return type.
2504 PROCEDURE putProcTypeOptReturn (proc
: node
) ;
2506 assert (isProcType (proc
)) ;
2507 proc^.proctypeF.returnopt
:= TRUE
2508 END putProcTypeOptReturn
;
2512 makeNonVarParameter - returns a non var parameter node with, name: type.
2515 PROCEDURE makeNonVarParameter (l
: node
; type
, proc
: node
; isused
: BOOLEAN) : node
;
2519 assert ((l
=NIL) OR isIdentList (l
)) ;
2520 d
:= newNode (param
) ;
2521 d^.paramF.namelist
:= l
;
2522 d^.paramF.type
:= type
;
2523 d^.paramF.scope
:= proc
;
2524 d^.paramF.isUnbounded
:= FALSE ;
2525 d^.paramF.isForC
:= isDefForCNode (proc
) ;
2526 d^.paramF.isUsed
:= isused
;
2527 initNodeOpaqueState (d
) ;
2529 END makeNonVarParameter
;
2533 makeVarParameter - returns a var parameter node with, name: type.
2536 PROCEDURE makeVarParameter (l
: node
; type
, proc
: node
; isused
: BOOLEAN) : node
;
2540 assert ((l
=NIL) OR isIdentList (l
)) ;
2541 d
:= newNode (varparam
) ;
2542 d^.varparamF.namelist
:= l
;
2543 d^.varparamF.type
:= type
;
2544 d^.varparamF.scope
:= proc
;
2545 d^.varparamF.isUnbounded
:= FALSE ;
2546 d^.varparamF.isForC
:= isDefForCNode (proc
) ;
2547 d^.varparamF.isUsed
:= isused
;
2548 initNodeOpaqueState (d
) ;
2550 END makeVarParameter
;
2554 makeVarargs - returns a varargs node.
2557 PROCEDURE makeVarargs () : node
;
2561 d
:= newNode (varargs
) ;
2562 d^.varargsF.scope
:= NIL ;
2568 isVarargs - returns TRUE if, n, is a varargs node.
2571 PROCEDURE isVarargs (n
: node
) : BOOLEAN ;
2573 RETURN n^.kind
= varargs
2578 addParameter - adds a parameter, param, to procedure or proctype, proc.
2581 PROCEDURE addParameter (proc
, param
: node
) ;
2583 assert (isVarargs (param
) OR isParam (param
) OR isVarParam (param
) OR isOptarg (param
)) ;
2586 procedure
: IncludeIndiceIntoIndex (proc^.procedureF.parameters
, param
) ;
2587 IF isVarargs (param
)
2589 proc^.procedureF.vararg
:= TRUE
2593 proc^.procedureF.optarg
:= param
2595 proctype
: IncludeIndiceIntoIndex (proc^.proctypeF.parameters
, param
) ;
2596 IF isVarargs (param
)
2598 proc^.proctypeF.vararg
:= TRUE
2602 proc^.proctypeF.optarg
:= param
2610 isOptarg - returns TRUE if, n, is an optarg.
2613 PROCEDURE isOptarg (n
: node
) : BOOLEAN ;
2615 RETURN n^.kind
= optarg
2620 makeOptParameter - creates and returns an optarg.
2623 PROCEDURE makeOptParameter (l
, type
, init
: node
) : node
;
2627 n
:= newNode (optarg
) ;
2628 n^.optargF.namelist
:= l
;
2629 n^.optargF.type
:= type
;
2630 n^.optargF.init
:= init
;
2631 n^.optargF.scope
:= NIL ;
2633 END makeOptParameter
;
2637 addOptParameter - returns an optarg which has been created and added to
2638 procedure node, proc. It has a name, id, and, type,
2639 and an initial value, init.
2642 PROCEDURE addOptParameter (proc
: node
; id
: Name
; type
, init
: node
) : node
;
2646 assert (isProcedure (proc
)) ;
2647 l
:= makeIdentList () ;
2648 assert (putIdent (l
, id
)) ;
2649 checkMakeVariables (proc
, l
, type
, FALSE, TRUE) ;
2650 IF NOT proc^.procedureF.checking
2652 p
:= makeOptParameter (l
, type
, init
) ;
2653 addParameter (proc
, p
)
2656 END addOptParameter
;
2664 setwatch - assign the globalNode to n.
2667 PROCEDURE setwatch (n
: node
) : BOOLEAN ;
2675 runwatch - set the globalNode to an identlist.
2678 PROCEDURE runwatch () : BOOLEAN ;
2680 RETURN globalNode^.kind
= identlist
2685 makeIdentList - returns a node which will be used to maintain an ident list.
2688 PROCEDURE makeIdentList () : node
;
2692 n
:= newNode (identlist
) ;
2693 n^.identlistF.names
:= wlists.
initList () ;
2694 n^.identlistF.cnamed
:= FALSE ;
2700 isIdentList - returns TRUE if, n, is an identlist.
2703 PROCEDURE isIdentList (n
: node
) : BOOLEAN ;
2705 RETURN n^.kind
= identlist
2710 putIdent - places ident, i, into identlist, n. It returns TRUE if
2711 ident, i, is unique.
2714 PROCEDURE putIdent (n
: node
; i
: Name
) : BOOLEAN ;
2716 assert (isIdentList (n
)) ;
2717 IF wlists.
isItemInList (n^.identlistF.names
, i
)
2721 wlists.
putItemIntoList (n^.identlistF.names
, i
) ;
2728 identListLen - returns the length of identlist.
2731 PROCEDURE identListLen (n
: node
) : CARDINAL ;
2737 assert (isIdentList (n
)) ;
2738 RETURN wlists.
noOfItemsInList (n^.identlistF.names
)
2744 checkParameters - placeholder for future parameter checking.
2747 PROCEDURE checkParameters (p
: node
; i
: node
; type
: node
; isvar
, isused
: BOOLEAN) ;
2751 END checkParameters
;
2755 avoidCnames - checks each name in, n, against C reserved
2756 keywords and macros.
2759 PROCEDURE avoidCnames (n
: node
) ;
2763 assert (isIdentList (n
)) ;
2764 IF NOT n^.identlistF.cnamed
2766 n^.identlistF.cnamed
:= TRUE ;
2767 j
:= wlists.
noOfItemsInList (n^.identlistF.names
) ;
2770 wlists.
replaceItemInList (n^.identlistF.names
,
2772 keyc.
cnamen (wlists.
getItemFromList (n^.identlistF.names
, i
), FALSE)) ;
2781 checkMakeVariables - create shadow local variables for parameters providing that
2782 procedure n has not already been built and we are compiling
2783 a module or an implementation module.
2786 PROCEDURE checkMakeVariables (n
, i
, type
: node
; isvar
, isused
: BOOLEAN) ;
2788 IF (isImp (currentModule
) OR isModule (currentModule
)) AND
2789 (NOT n^.procedureF.built
)
2791 makeVariablesFromParameters (n
, i
, type
, isvar
, isused
)
2793 END checkMakeVariables
;
2797 addVarParameters - adds the identlist, i, of, type, to be VAR parameters
2801 PROCEDURE addVarParameters (n
: node
; i
: node
; type
: node
; isused
: BOOLEAN) ;
2805 assert (isIdentList (i
)) ;
2806 assert (isProcedure (n
)) ;
2807 checkMakeVariables (n
, i
, type
, TRUE, isused
) ;
2808 IF n^.procedureF.checking
2810 checkParameters (n
, i
, type
, TRUE, isused
) (* will destroy, i. *)
2812 p
:= makeVarParameter (i
, type
, n
, isused
) ;
2813 IncludeIndiceIntoIndex (n^.procedureF.parameters
, p
) ;
2815 END addVarParameters
;
2819 addNonVarParameters - adds the identlist, i, of, type, to be parameters
2823 PROCEDURE addNonVarParameters (n
: node
; i
: node
; type
: node
; isused
: BOOLEAN) ;
2827 assert (isIdentList (i
)) ;
2828 assert (isProcedure (n
)) ;
2829 checkMakeVariables (n
, i
, type
, FALSE, isused
) ;
2830 IF n^.procedureF.checking
2832 checkParameters (n
, i
, type
, FALSE, isused
) (* will destroy, i. *)
2834 p
:= makeNonVarParameter (i
, type
, n
, isused
) ;
2835 IncludeIndiceIntoIndex (n^.procedureF.parameters
, p
)
2837 END addNonVarParameters
;
2841 makeSubrange - returns a subrange node, built from range: low..high.
2844 PROCEDURE makeSubrange (low
, high
: node
) : node
;
2848 n
:= newNode (subrange
) ;
2849 n^.subrangeF.low
:= low
;
2850 n^.subrangeF.high
:= high
;
2851 n^.subrangeF.type
:= NIL ;
2852 n^.subrangeF.scope
:= getDeclScope () ;
2858 putSubrangeType - assigns, type, to the subrange type, sub.
2861 PROCEDURE putSubrangeType (sub
, type
: node
) ;
2863 assert (isSubrange (sub
)) ;
2864 sub^.subrangeF.type
:= type
2865 END putSubrangeType
;
2869 makeSet - returns a set of, type, node.
2872 PROCEDURE makeSet (type
: node
) : node
;
2876 n
:= newNode (set
) ;
2877 n^.setF.type
:= type
;
2878 n^.setF.scope
:= getDeclScope () ;
2884 makeSetValue - creates and returns a setvalue node.
2887 PROCEDURE makeSetValue () : node
;
2891 n
:= newNode (setvalue
) ;
2892 n^.setvalueF.type
:= bitsetN
;
2893 n^.setvalueF.values
:= InitIndex (1) ;
2899 isSetValue - returns TRUE if, n, is a setvalue node.
2902 PROCEDURE isSetValue (n
: node
) : BOOLEAN ;
2905 RETURN n^.kind
= setvalue
2910 putSetValue - assigns the type, t, to the set value, n. The
2911 node, n, is returned.
2914 PROCEDURE putSetValue (n
, t
: node
) : node
;
2916 assert (isSetValue (n
)) ;
2917 n^.setvalueF.type
:= t
;
2923 includeSetValue - includes the range l..h into the setvalue.
2924 h might be NIL indicating that a single element
2925 is to be included into the set.
2929 PROCEDURE includeSetValue (n
: node
; l
, h
: node
) : node
;
2931 assert (isSetValue (n
)) ;
2932 IncludeIndiceIntoIndex (n^.setvalueF.values
, l
) ;
2934 END includeSetValue
;
2938 makePointer - returns a pointer of, type, node.
2941 PROCEDURE makePointer (type
: node
) : node
;
2945 n
:= newNode (pointer
) ;
2946 n^.pointerF.type
:= type
;
2947 n^.pointerF.scope
:= getDeclScope () ;
2953 makeArray - returns a node representing ARRAY subr OF type.
2956 PROCEDURE makeArray (subr
, type
: node
) : node
;
2960 s
:= skipType (subr
) ;
2961 assert (isSubrange (s
) OR isOrdinal (s
) OR isEnumeration (s
)) ;
2962 n
:= newNode (array
) ;
2963 n^.arrayF.subr
:= subr
;
2964 n^.arrayF.type
:= type
;
2965 n^.arrayF.scope
:= getDeclScope () ;
2966 n^.arrayF.isUnbounded
:= FALSE ;
2972 makeRecord - creates and returns a record node.
2975 PROCEDURE makeRecord () : node
;
2979 n
:= newNode (record
) ;
2980 n^.recordF.localSymbols
:= initTree () ;
2981 n^.recordF.listOfSons
:= InitIndex (1) ;
2982 n^.recordF.scope
:= getDeclScope () ;
2988 addFieldsToRecord - adds fields, i, of type, t, into a record, r.
2992 PROCEDURE addFieldsToRecord (r
, v
, i
, t
: node
) : node
;
3003 p
:= getRecord (getParent (r
)) ;
3004 assert (isVarientField (r
)) ;
3005 assert (isVarient (v
)) ;
3006 putFieldVarient (r
, v
)
3008 n
:= wlists.
noOfItemsInList (i^.identlistF.names
) ;
3011 fn
:= wlists.
getItemFromList (i^.identlistF.names
, j
) ;
3012 fj
:= getSymKey (p^.recordF.localSymbols
, n
) ;
3015 fj
:= putFieldRecord (r
, fn
, t
, v
)
3017 metaErrors2 ('record field {%1ad} has already been declared inside a {%2Dd} {%2a}',
3018 'attempting to declare a duplicate record field', fj
, p
)
3023 END addFieldsToRecord
;
3027 makeVarient - creates a new symbol, a varient symbol for record or varient field
3031 PROCEDURE makeVarient (r
: node
) : node
;
3035 n
:= newNode (varient
) ;
3037 varientF.listOfSons
:= InitIndex (1) ;
3038 (* do we need to remember our parent (r) ? *)
3039 (* if so use this n^.varientF.parent := r *)
3042 varientF.varient
:= NIL
3044 varientF.varient
:= r
3046 varientF.tag
:= NIL ;
3047 varientF.scope
:= getDeclScope () ;
3049 (* now add, n, to the record/varient, r, field list *)
3053 record
: IncludeIndiceIntoIndex (recordF.listOfSons
, n
) |
3054 varientfield
: IncludeIndiceIntoIndex (varientfieldF.listOfSons
, n
)
3063 buildVarientFieldRecord - builds a varient field into a varient symbol, v.
3064 The varient field is returned.
3067 PROCEDURE buildVarientFieldRecord (v
: node
; p
: node
) : node
;
3071 assert (isVarient (v
)) ;
3072 f
:= makeVarientField (v
, p
) ;
3073 assert (isVarientField (f
)) ;
3074 putFieldVarient (f
, v
) ;
3076 END buildVarientFieldRecord
;
3080 makeVarientField - create a varient field within varient, v,
3081 The new varient field is returned.
3084 PROCEDURE makeVarientField (v
: node
; p
: node
) : node
;
3088 n
:= newNode (varientfield
) ;
3089 WITH n^.varientfieldF
DO
3094 listOfSons
:= InitIndex (1) ;
3095 scope
:= getDeclScope ()
3098 END makeVarientField
;
3102 putFieldVarient - places the field varient, f, as a brother to, the
3103 varient symbol, v, and also tells, f, that its varient
3107 PROCEDURE putFieldVarient (f
, v
: node
) ;
3109 assert (isVarient (v
)) ;
3110 assert (isVarientField (f
)) ;
3114 varient
: IncludeIndiceIntoIndex (varientF.listOfSons
, f
)
3121 varientfield
: varientfieldF.varient
:= v
3125 END putFieldVarient
;
3129 putFieldRecord - create a new recordfield and place it into record r.
3130 The new field has a tagname and type and can have a
3134 PROCEDURE putFieldRecord (r
: node
; tag
: Name
; type
, v
: node
) : node
;
3138 n
:= newNode (recordfield
) ;
3142 record
: IncludeIndiceIntoIndex (recordF.listOfSons
, n
) ;
3143 (* ensure that field, n, is in the parents Local Symbols. *)
3146 IF getSymKey (recordF.localSymbols
, tag
) = NulKey
3148 putSymKey (recordF.localSymbols
, tag
, n
)
3150 f
:= getSymKey (recordF.localSymbols
, tag
) ;
3151 metaErrors1 ('field record {%1Dad} has already been declared',
3152 'field record duplicate', f
)
3155 varientfield
: IncludeIndiceIntoIndex (varientfieldF.listOfSons
, n
) ;
3156 p
:= getParent (r
) ;
3157 assert (p^.kind
=record
) ;
3160 putSymKey (p^.recordF.localSymbols
, tag
, n
)
3166 n^.recordfieldF.type
:= type
;
3167 n^.recordfieldF.name
:= tag
;
3168 n^.recordfieldF.parent
:= r
;
3169 n^.recordfieldF.varient
:= v
;
3170 n^.recordfieldF.tag
:= FALSE ;
3171 n^.recordfieldF.scope
:= NIL ;
3172 initCname (n^.recordfieldF.cname
) ;
3180 END putFieldRecord
;
3184 buildVarientSelector - builds a field of name, tag, of, type onto:
3185 record or varient field, r.
3189 PROCEDURE buildVarientSelector (r
, v
: node
; tag
: Name
; type
: node
) ;
3193 assert (isRecord (r
) OR isVarientField (r
)) ;
3194 IF isRecord (r
) OR isVarientField (r
)
3196 IF (type
=NIL) AND (tag
=NulName
)
3198 metaError1 ('expecting a tag field in the declaration of a varient record {%1Ua}', r
)
3201 f
:= lookupSym (tag
) ;
3202 putVarientTag (v
, f
)
3204 f
:= putFieldRecord (r
, tag
, type
, v
) ;
3205 assert (isRecordField (f
)) ;
3206 f^.recordfieldF.tag
:= TRUE ;
3207 putVarientTag (v
, f
)
3210 END buildVarientSelector
;
3214 ensureOrder - ensures that, a, and, b, exist in, i, and also
3215 ensure that, a, is before, b.
3218 PROCEDURE ensureOrder (i
: Index
; a
, b
: node
) ;
3220 assert (IsIndiceInIndex (i
, a
)) ;
3221 assert (IsIndiceInIndex (i
, b
)) ;
3222 RemoveIndiceFromIndex (i
, a
) ;
3223 RemoveIndiceFromIndex (i
, b
) ;
3224 IncludeIndiceIntoIndex (i
, a
) ;
3225 IncludeIndiceIntoIndex (i
, b
) ;
3226 assert (IsIndiceInIndex (i
, a
)) ;
3227 assert (IsIndiceInIndex (i
, b
))
3232 putVarientTag - places tag into variant v.
3235 PROCEDURE putVarientTag (v
: node
; tag
: node
) ;
3239 assert (isVarient (v
)) ;
3242 varient
: v^.varientF.tag
:= tag
3249 getParent - returns the parent field of recordfield or varientfield symbol, n.
3252 PROCEDURE getParent (n
: node
) : node
;
3256 recordfield
: RETURN n^.recordfieldF.parent |
3257 varientfield
: RETURN n^.varientfieldF.parent
3264 getRecord - returns the record associated with node, n.
3268 PROCEDURE getRecord (n
: node
) : node
;
3270 assert (n^.kind # varient
) ; (* if this fails then we need to add parent field to varient. *)
3274 varientfield
: RETURN getRecord (getParent (n
))
3281 putUnbounded - sets array, n, as unbounded.
3284 PROCEDURE putUnbounded (n
: node
) ;
3286 assert (n^.kind
= array
) ;
3287 n^.arrayF.isUnbounded
:= TRUE
3292 isConstExp - return TRUE if the node kind is a constexp.
3295 PROCEDURE isConstExp (c
: node
) : BOOLEAN ;
3298 RETURN c^.kind
= constexp
3303 addEnumToModule - adds enumeration type, e, into the list of enums
3307 PROCEDURE addEnumToModule (m
, e
: node
) ;
3309 assert (isEnumeration (e
) OR isEnumerationField (e
)) ;
3310 assert (isModule (m
) OR isDef (m
) OR isImp (m
)) ;
3313 IncludeIndiceIntoIndex (m^.moduleF.enumFixup.info
, e
)
3316 IncludeIndiceIntoIndex (m^.defF.enumFixup.info
, e
)
3319 IncludeIndiceIntoIndex (m^.impF.enumFixup.info
, e
)
3321 END addEnumToModule
;
3325 getNextFixup - return the next fixup from from f.
3328 PROCEDURE getNextFixup (VAR f
: fixupInfo
) : node
;
3331 RETURN GetIndice (f.info
, f.count
)
3336 getNextEnum - returns the next enumeration node.
3339 PROCEDURE getNextEnum () : node
;
3344 assert (isDef (currentModule
) OR isImp (currentModule
) OR isModule (currentModule
)) ;
3345 WITH currentModule^
DO
3346 IF isDef (currentModule
)
3348 n
:= getNextFixup (defF.enumFixup
)
3349 ELSIF isImp (currentModule
)
3351 n
:= getNextFixup (impF.enumFixup
)
3352 ELSIF isModule (currentModule
)
3354 n
:= getNextFixup (moduleF.enumFixup
)
3358 assert (isEnumeration (n
) OR isEnumerationField (n
)) ;
3364 resetEnumPos - resets the index into the saved list of enums inside
3368 PROCEDURE resetEnumPos (n
: node
) ;
3370 assert (isDef (n
) OR isImp (n
) OR isModule (n
)) ;
3373 n^.defF.enumFixup.count
:= 0
3376 n^.impF.enumFixup.count
:= 0
3379 n^.moduleF.enumFixup.count
:= 0
3385 getEnumsComplete - gets the field from the def or imp or module, n.
3388 PROCEDURE getEnumsComplete (n
: node
) : BOOLEAN ;
3392 def
: RETURN n^.defF.enumsComplete |
3393 imp
: RETURN n^.impF.enumsComplete |
3394 module
: RETURN n^.moduleF.enumsComplete
3397 END getEnumsComplete
;
3401 setEnumsComplete - sets the field inside the def or imp or module, n.
3404 PROCEDURE setEnumsComplete (n
: node
) ;
3408 def
: n^.defF.enumsComplete
:= TRUE |
3409 imp
: n^.impF.enumsComplete
:= TRUE |
3410 module
: n^.moduleF.enumsComplete
:= TRUE
3413 END setEnumsComplete
;
3417 doMakeEnum - create an enumeration type and add it to the current module.
3420 PROCEDURE doMakeEnum () : node
;
3424 e
:= newNode (enumeration
) ;
3426 enumerationF.noOfElements
:= 0 ;
3427 enumerationF.localSymbols
:= initTree () ;
3428 enumerationF.scope
:= getDeclScope () ;
3429 enumerationF.listOfSons
:= InitIndex (1) ;
3430 enumerationF.low
:= NIL ;
3431 enumerationF.high
:= NIL ;
3433 addEnumToModule (currentModule
, e
) ;
3439 makeEnum - creates an enumerated type and returns the node.
3442 PROCEDURE makeEnum () : node
;
3444 IF (currentModule#
NIL) AND getEnumsComplete (currentModule
)
3446 RETURN getNextEnum ()
3448 RETURN doMakeEnum ()
3454 doMakeEnumField - create an enumeration field name and add it to enumeration e.
3455 Return the new field.
3458 PROCEDURE doMakeEnumField (e
: node
; n
: Name
) : node
;
3462 assert (isEnumeration (e
)) ;
3463 f
:= lookupSym (n
) ;
3466 f
:= newNode (enumerationfield
) ;
3467 putSymKey (e^.enumerationF.localSymbols
, n
, f
) ;
3468 IncludeIndiceIntoIndex (e^.enumerationF.listOfSons
, f
) ;
3470 enumerationfieldF.name
:= n
;
3471 enumerationfieldF.type
:= e
;
3472 enumerationfieldF.scope
:= getDeclScope () ;
3473 enumerationfieldF.value
:= e^.enumerationF.noOfElements
;
3474 initCname (enumerationfieldF.cname
)
3476 INC (e^.enumerationF.noOfElements
) ;
3477 assert (GetIndice (e^.enumerationF.listOfSons
, e^.enumerationF.noOfElements
) = f
) ;
3478 addEnumToModule (currentModule
, f
) ;
3479 IF e^.enumerationF.low
= NIL
3481 e^.enumerationF.low
:= f
3483 e^.enumerationF.high
:= f
;
3484 RETURN addToScope (f
)
3486 metaErrors2 ('cannot create enumeration field {%1k} as the name is already in use',
3487 '{%2DMad} was declared elsewhere', n
, f
)
3490 END doMakeEnumField
;
3494 makeEnumField - returns an enumeration field, named, n.
3497 PROCEDURE makeEnumField (e
: node
; n
: Name
) : node
;
3499 IF (currentModule#
NIL) AND getEnumsComplete (currentModule
)
3501 RETURN getNextEnum ()
3503 RETURN doMakeEnumField (e
, n
)
3509 isEnumeration - returns TRUE if node, n, is an enumeration type.
3512 PROCEDURE isEnumeration (n
: node
) : BOOLEAN ;
3515 RETURN n^.kind
= enumeration
3520 makeExpList - creates and returns an expList node.
3523 PROCEDURE makeExpList () : node
;
3527 n
:= newNode (explist
) ;
3528 n^.explistF.exp
:= InitIndex (1) ;
3534 isExpList - returns TRUE if, n, is an explist node.
3537 PROCEDURE isExpList (n
: node
) : BOOLEAN ;
3540 RETURN n^.kind
= explist
3545 putExpList - places, expression, e, within the explist, n.
3548 PROCEDURE putExpList (n
: node
; e
: node
) ;
3551 assert (isExpList (n
)) ;
3552 PutIndice (n^.explistF.exp
, HighIndice (n^.explistF.exp
) + 1, e
)
3557 getExpList - returns the, n, th argument in an explist.
3560 PROCEDURE getExpList (p
: node
; n
: CARDINAL) : node
;
3563 assert (isExpList (p
)) ;
3564 assert (n
<= HighIndice (p^.explistF.exp
)) ;
3565 RETURN GetIndice (p^.explistF.exp
, n
)
3570 expListLen - returns the length of explist, p.
3573 PROCEDURE expListLen (p
: node
) : CARDINAL ;
3579 assert (isExpList (p
)) ;
3580 RETURN HighIndice (p^.explistF.exp
)
3586 getConstExpComplete - gets the field from the def or imp or module, n.
3589 PROCEDURE getConstExpComplete (n
: node
) : BOOLEAN ;
3593 def
: RETURN n^.defF.constsComplete |
3594 imp
: RETURN n^.impF.constsComplete |
3595 module
: RETURN n^.moduleF.constsComplete
3598 END getConstExpComplete
;
3602 setConstExpComplete - sets the field inside the def or imp or module, n.
3605 PROCEDURE setConstExpComplete (n
: node
) ;
3609 def
: n^.defF.constsComplete
:= TRUE |
3610 imp
: n^.impF.constsComplete
:= TRUE |
3611 module
: n^.moduleF.constsComplete
:= TRUE
3614 END setConstExpComplete
;
3618 getNextConstExp - returns the next constexp node.
3621 PROCEDURE getNextConstExp () : node
;
3623 assert (isDef (currentModule
) OR isImp (currentModule
) OR isModule (currentModule
)) ;
3624 WITH currentModule^
DO
3625 IF isDef (currentModule
)
3627 RETURN getNextFixup (defF.constFixup
)
3628 ELSIF isImp (currentModule
)
3630 RETURN getNextFixup (impF.constFixup
)
3632 assert (isModule (currentModule
)) ;
3633 RETURN getNextFixup (moduleF.constFixup
)
3636 END getNextConstExp
;
3640 resetConstExpPos - resets the index into the saved list of constexps inside
3644 PROCEDURE resetConstExpPos (n
: node
) ;
3646 assert (isDef (n
) OR isImp (n
) OR isModule (n
)) ;
3649 n^.defF.constFixup.count
:= 0
3652 n^.impF.constFixup.count
:= 0
3655 n^.moduleF.constFixup.count
:= 0
3657 END resetConstExpPos
;
3661 addConstToModule - adds const exp, e, into the list of constant
3662 expressions in module, m.
3665 PROCEDURE addConstToModule (m
, e
: node
) ;
3667 assert (isModule (m
) OR isDef (m
) OR isImp (m
)) ;
3670 IncludeIndiceIntoIndex (m^.moduleF.constFixup.info
, e
)
3673 IncludeIndiceIntoIndex (m^.defF.constFixup.info
, e
)
3676 IncludeIndiceIntoIndex (m^.impF.constFixup.info
, e
)
3678 END addConstToModule
;
3682 doMakeConstExp - create a constexp node and add it to the current module.
3685 PROCEDURE doMakeConstExp () : node
;
3689 c
:= makeUnary (constexp
, NIL, NIL) ;
3690 addConstToModule (currentModule
, c
) ;
3692 END doMakeConstExp
;
3696 makeConstExp - returns a constexp node.
3699 PROCEDURE makeConstExp () : node
;
3701 IF (currentModule#
NIL) AND getConstExpComplete (currentModule
)
3703 RETURN getNextConstExp ()
3705 RETURN doMakeConstExp ()
3711 fixupConstExp - assign fixup expression, e, into the argument of, c.
3714 PROCEDURE fixupConstExp (c
, e
: node
) : node
;
3716 assert (isConstExp (c
)) ;
3717 c^.unaryF.arg
:= e
;
3723 isAnyType - return TRUE if node n is any type kind.
3726 PROCEDURE isAnyType (n
: node
) : BOOLEAN ;
3757 makeVal - creates a VAL (type, expression) node.
3760 PROCEDURE makeVal (params
: node
) : node
;
3762 assert (isExpList (params
)) ;
3763 IF expListLen (params
) = 2
3765 RETURN makeBinary (val
,
3766 getExpList (params
, 1),
3767 getExpList (params
, 2),
3768 getExpList (params
, 1))
3776 makeCast - creates a cast node TYPENAME (expr).
3779 PROCEDURE makeCast (c
, p
: node
) : node
;
3781 assert (isExpList (p
)) ;
3782 IF expListLen (p
) = 1
3784 RETURN makeBinary (cast
, c
, getExpList (p
, 1), c
)
3792 makeIntrisicProc - create an intrinsic node.
3795 PROCEDURE makeIntrinsicProc (k
: nodeT
; noArgs
: CARDINAL; p
: node
) : node
;
3800 f^.intrinsicF.args
:= p
;
3801 f^.intrinsicF.noArgs
:= noArgs
;
3802 f^.intrinsicF.type
:= NIL ;
3803 f^.intrinsicF.postUnreachable
:= (k
= halt
) ;
3804 initPair (f^.intrinsicF.intrinsicComment
) ;
3806 END makeIntrinsicProc
;
3810 makeIntrinsicUnaryType - create an intrisic unary type.
3813 PROCEDURE makeIntrinsicUnaryType (k
: nodeT
; paramList
: node
; returnType
: node
) : node
;
3815 RETURN makeUnary (k
, getExpList (paramList
, 1), returnType
)
3816 END makeIntrinsicUnaryType
;
3820 makeIntrinsicBinaryType - create an intrisic binary type.
3823 PROCEDURE makeIntrinsicBinaryType (k
: nodeT
; paramList
: node
; returnType
: node
) : node
;
3825 RETURN makeBinary (k
, getExpList (paramList
, 1), getExpList (paramList
, 2), returnType
)
3826 END makeIntrinsicBinaryType
;
3830 checkIntrinsic - checks to see if the function call to, c, with
3831 parameter list, n, is really an intrinic. If it
3832 is an intrinic then an intrinic node is created
3833 and returned. Otherwise NIL is returned.
3836 PROCEDURE checkIntrinsic (c
, n
: node
) : node
;
3840 RETURN makeCast (c
, n
)
3843 RETURN makeIntrinsicUnaryType (max
, n
, NIL)
3846 RETURN makeIntrinsicUnaryType (min
, n
, NIL)
3849 RETURN makeIntrinsicProc (halt
, expListLen (n
), n
)
3855 RETURN makeIntrinsicUnaryType (adr
, n
, addressN
)
3858 RETURN makeIntrinsicUnaryType (size
, n
, cardinalN
)
3861 RETURN makeIntrinsicUnaryType (tsize
, n
, cardinalN
)
3864 RETURN makeIntrinsicUnaryType (float
, n
, realN
)
3867 RETURN makeIntrinsicUnaryType (trunc
, n
, integerN
)
3870 RETURN makeIntrinsicUnaryType (ord
, n
, cardinalN
)
3873 RETURN makeIntrinsicUnaryType (chr
, n
, charN
)
3876 RETURN makeIntrinsicUnaryType (cap
, n
, charN
)
3879 RETURN makeIntrinsicUnaryType (abs
, n
, NIL)
3882 RETURN makeIntrinsicUnaryType (im
, n
, NIL)
3885 RETURN makeIntrinsicUnaryType (re
, n
, NIL)
3888 RETURN makeIntrinsicBinaryType (cmplx
, n
, NIL)
3891 RETURN makeIntrinsicUnaryType (high
, n
, cardinalN
)
3894 RETURN makeIntrinsicProc (inc
, expListLen (n
), n
)
3897 RETURN makeIntrinsicProc (dec
, expListLen (n
), n
)
3900 RETURN makeIntrinsicProc (incl
, expListLen (n
), n
)
3903 RETURN makeIntrinsicProc (excl
, expListLen (n
), n
)
3906 RETURN makeIntrinsicProc (new
, 1, n
)
3909 RETURN makeIntrinsicProc (dispose
, 1, n
)
3912 RETURN makeIntrinsicUnaryType (length
, n
, cardinalN
)
3916 RETURN makeIntrinsicProc (throw
, 1, n
)
3919 END checkIntrinsic
;
3923 checkCHeaders - check to see if the function is a C system function and
3924 requires a header file included.
3927 PROCEDURE checkCHeaders (c
: node
) ;
3935 IF getSymName (s
) = makeKey ('libc')
3937 name
:= getSymName (c
) ;
3938 IF (name
= makeKey ('read')) OR
3939 (name
= makeKey ('write')) OR
3940 (name
= makeKey ('open')) OR
3941 (name
= makeKey ('close'))
3951 makeFuncCall - builds a function call to c with param list, n.
3954 PROCEDURE makeFuncCall (c
, n
: node
) : node
;
3958 assert ((n
=NIL) OR isExpList (n
)) ;
3960 (getMainModule () #
lookupDef (makeKey ('M2RTS'))) AND
3961 (getMainModule () #
lookupImp (makeKey ('M2RTS')))
3963 addImportedModule (getMainModule (), lookupDef (makeKey ('M2RTS')), FALSE)
3965 f
:= checkIntrinsic (c
, n
) ;
3969 f
:= newNode (funccall
) ;
3970 f^.funccallF.function
:= c
;
3971 f^.funccallF.args
:= n
;
3972 f^.funccallF.type
:= getType (c
) ;
3973 initPair (f^.funccallF.funccallComment
) ;
3974 initNodeOpaqueState (f
)
3981 isFuncCall - returns TRUE if, n, is a function/procedure call.
3984 PROCEDURE isFuncCall (n
: node
) : BOOLEAN ;
3987 RETURN n^.kind
= funccall
3992 putType - places, exp, as the type alias to des.
3996 PROCEDURE putType (des
, exp
: node
) ;
3999 assert (isType (des
)) ;
4000 des^.typeF.type
:= exp
4005 putTypeHidden - marks type, des, as being a hidden type.
4009 PROCEDURE putTypeHidden (des
: node
) ;
4014 assert (isType (des
)) ;
4015 des^.typeF.isHidden
:= TRUE ;
4016 s
:= getScope (des
) ;
4017 assert (isDef (s
)) ;
4018 s^.defF.hasHidden
:= TRUE
4023 isTypeHidden - returns TRUE if type, n, is hidden.
4026 PROCEDURE isTypeHidden (n
: node
) : BOOLEAN ;
4029 assert (isType (n
)) ;
4030 RETURN n^.typeF.isHidden
4035 hasHidden - returns TRUE if module, n, has a hidden type.
4038 PROCEDURE hasHidden (n
: node
) : BOOLEAN ;
4040 assert (isDef (n
)) ;
4041 RETURN n^.defF.hasHidden
4046 putTypeOpaque - marks type, des, as being an opaque type.
4050 PROCEDURE putTypeOpaque (des
: node
) ;
4055 assert (isType (des
)) ;
4056 des^.typeF.isOpaque
:= TRUE
4061 isTypeOpaque - returns TRUE if type, n, is an opaque type.
4064 PROCEDURE isTypeOpaque (n
: node
) : BOOLEAN ;
4067 assert (isType (n
)) ;
4068 RETURN n^.typeF.isOpaque
4073 putTypeInternal - marks type, des, as being an internally generated type.
4076 PROCEDURE putTypeInternal (des
: node
) ;
4079 assert (isType (des
)) ;
4080 des^.typeF.isInternal
:= TRUE
4081 END putTypeInternal
;
4085 isTypeInternal - returns TRUE if type, n, is internal.
4088 PROCEDURE isTypeInternal (n
: node
) : BOOLEAN ;
4091 assert (isType (n
)) ;
4092 RETURN n^.typeF.isInternal
4093 END isTypeInternal
;
4097 putConst - places value, v, into node, n.
4100 PROCEDURE putConst (n
: node
; v
: node
) ;
4102 assert (isConst (n
)) ;
4103 n^.constF.value
:= v
4108 makeLiteralInt - creates and returns a literal node based on an integer type.
4111 PROCEDURE makeLiteralInt (n
: Name
) : node
;
4116 m
:= newNode (literal
) ;
4117 s
:= InitStringCharStar (keyToCharStar (n
)) ;
4119 literalF.name
:= n
;
4120 IF DynamicStrings.
char (s
, -1)='C'
4122 literalF.type
:= charN
4124 literalF.type
:= ztypeN
4127 s
:= KillString (s
) ;
4129 END makeLiteralInt
;
4133 makeLiteralReal - creates and returns a literal node based on a real type.
4136 PROCEDURE makeLiteralReal (n
: Name
) : node
;
4140 m
:= newNode (literal
) ;
4142 literalF.name
:= n
;
4143 literalF.type
:= rtypeN
4146 END makeLiteralReal
;
4150 makeString - creates and returns a node containing string, n.
4153 PROCEDURE makeString (n
: Name
) : node
;
4157 m
:= newNode (string
) ;
4160 stringF.length
:= lengthKey (n
) ;
4161 stringF.isCharCompatible
:= (stringF.length
<= 3) ;
4162 stringF.cstring
:= toCstring (n
) ;
4163 stringF.clength
:= lenCstring (stringF.cstring
) ;
4164 IF stringF.isCharCompatible
4166 stringF.cchar
:= toCchar (n
)
4168 stringF.cchar
:= NIL
4176 getBuiltinConst - creates and returns a builtin const if available.
4179 PROCEDURE getBuiltinConst (n
: Name
) : node
;
4181 IF n
=makeKey ('BITS_PER_UNIT')
4184 ELSIF n
=makeKey ('BITS_PER_WORD')
4187 ELSIF n
=makeKey ('BITS_PER_CHAR')
4190 ELSIF n
=makeKey ('UNITS_PER_WORD')
4192 RETURN unitsperwordN
4196 END getBuiltinConst
;
4200 lookupInScope - looks up a symbol named, n, from, scope.
4203 PROCEDURE lookupInScope (scope
: node
; n
: Name
) : node
;
4207 def
: RETURN getSymKey (scope^.defF.decls.symbols
, n
) |
4208 module
: RETURN getSymKey (scope^.moduleF.decls.symbols
, n
) |
4209 imp
: RETURN getSymKey (scope^.impF.decls.symbols
, n
) |
4210 procedure
: RETURN getSymKey (scope^.procedureF.decls.symbols
, n
) |
4211 record
: RETURN getSymKey (scope^.recordF.localSymbols
, n
)
4218 lookupBase - return node named n from the base symbol scope.
4221 PROCEDURE lookupBase (n
: Name
) : node
;
4225 m
:= getSymKey (baseSymbols
, n
) ;
4229 ELSIF (m
=complexN
) OR (m
=longcomplexN
) OR (m
=shortcomplexN
)
4238 dumpScopes - display the names of all the scopes stacked.
4241 PROCEDURE dumpScopes
;
4246 h
:= HighIndice (scopeStack
) ;
4247 printf ("total scopes stacked %d\n", h
);
4250 s
:= GetIndice (scopeStack
, h
) ;
4251 out2 (" scope [%d] is %s\n", h
, s
) ;
4258 out0 - write string a to StdOut.
4261 PROCEDURE out0 (a
: ARRAY OF CHAR) ;
4265 m
:= Sprintf0 (InitString (a
)) ;
4266 m
:= KillString (WriteS (StdOut
, m
))
4271 out1 - write string a to StdOut using format specifier a.
4274 PROCEDURE out1 (a
: ARRAY OF CHAR; s
: node
) ;
4279 m
:= getFQstring (s
) ;
4280 IF EqualArray (m
, '')
4282 d
:= VAL (CARDINAL, VAL (LONGCARD, s
)) ;
4283 m
:= KillString (m
) ;
4284 m
:= Sprintf1 (InitString ('[%d]'), d
)
4286 m
:= Sprintf1 (InitString (a
), m
) ;
4287 m
:= KillString (WriteS (StdOut
, m
))
4292 out2 - write string a to StdOut using format specifier a.
4295 PROCEDURE out2 (a
: ARRAY OF CHAR; c
: CARDINAL; s
: node
) ;
4299 m1
:= getString (s
) ;
4300 m
:= Sprintf2 (InitString (a
), c
, m1
) ;
4301 m
:= KillString (WriteS (StdOut
, m
)) ;
4302 m1
:= KillString (m1
)
4307 out3 - write string a to StdOut using format specifier a.
4310 PROCEDURE out3 (a
: ARRAY OF CHAR; l
: CARDINAL; n
: Name
; s
: node
) ;
4314 m1
:= InitStringCharStar (keyToCharStar (n
)) ;
4315 m2
:= getString (s
) ;
4316 m
:= Sprintf3 (InitString (a
), l
, m1
, m2
) ;
4317 m
:= KillString (WriteS (StdOut
, m
)) ;
4318 m1
:= KillString (m1
) ;
4319 m2
:= KillString (m2
)
4324 lookupSym - returns the symbol named, n, from the scope stack.
4327 PROCEDURE lookupSym (n
: Name
) : node
;
4332 l
:= LowIndice (scopeStack
) ;
4333 h
:= HighIndice (scopeStack
) ;
4336 s
:= GetIndice (scopeStack
, h
) ;
4337 m
:= lookupInScope (s
, n
) ;
4338 IF debugScopes
AND (m
=NIL)
4340 out3 (" [%d] search for symbol name %s in scope %s\n", h
, n
, s
)
4346 out3 (" [%d] search for symbol name %s in scope %s (found)\n", h
, n
, s
)
4352 RETURN lookupBase (n
)
4357 getSymName - returns the name of symbol, n.
4360 PROCEDURE getSymName (n
: node
) : Name
;
4365 new
: RETURN makeKey ('NEW') |
4366 dispose
: RETURN makeKey ('DISPOSE') |
4367 length
: RETURN makeKey ('LENGTH') |
4368 inc
: RETURN makeKey ('INC') |
4369 dec
: RETURN makeKey ('DEC') |
4370 incl
: RETURN makeKey ('INCL') |
4371 excl
: RETURN makeKey ('EXCL') |
4372 nil
: RETURN makeKey ('NIL') |
4373 true
: RETURN makeKey ('TRUE') |
4374 false
: RETURN makeKey ('FALSE') |
4375 address
: RETURN makeKey ('ADDRESS') |
4376 loc
: RETURN makeKey ('LOC') |
4377 byte
: RETURN makeKey ('BYTE') |
4378 word
: RETURN makeKey ('WORD') |
4379 csizet
: RETURN makeKey ('CSIZE_T') |
4380 cssizet
: RETURN makeKey ('CSSIZE_T') |
4382 boolean
: RETURN makeKey ('BOOLEAN') |
4383 proc
: RETURN makeKey ('PROC') |
4384 char
: RETURN makeKey ('CHAR') |
4385 cardinal
: RETURN makeKey ('CARDINAL') |
4386 longcard
: RETURN makeKey ('LONGCARD') |
4387 shortcard
: RETURN makeKey ('SHORTCARD') |
4388 integer
: RETURN makeKey ('INTEGER') |
4389 longint
: RETURN makeKey ('LONGINT') |
4390 shortint
: RETURN makeKey ('SHORTINT') |
4391 real
: RETURN makeKey ('REAL') |
4392 longreal
: RETURN makeKey ('LONGREAL') |
4393 shortreal
: RETURN makeKey ('SHORTREAL') |
4394 bitset
: RETURN makeKey ('BITSET') |
4395 ztype
: RETURN makeKey ('_ZTYPE') |
4396 rtype
: RETURN makeKey ('_RTYPE') |
4397 complex
: RETURN makeKey ('COMPLEX') |
4398 longcomplex
: RETURN makeKey ('LONGCOMPLEX') |
4399 shortcomplex
: RETURN makeKey ('SHORTCOMPLEX') |
4401 (* language features and compound type attributes. *)
4402 type
: RETURN typeF.name |
4403 record
: RETURN NulName |
4404 varient
: RETURN NulName |
4405 var
: RETURN varF.name |
4406 enumeration
: RETURN NulName |
4407 subrange
: RETURN NulName |
4408 pointer
: RETURN NulName |
4409 array
: RETURN NulName |
4410 string
: RETURN stringF.name |
4411 const
: RETURN constF.name |
4412 literal
: RETURN literalF.name |
4413 varparam
: RETURN NulName |
4414 param
: RETURN NulName |
4415 optarg
: RETURN NulName |
4416 recordfield
: RETURN recordfieldF.name |
4417 varientfield
: RETURN varientfieldF.name |
4418 enumerationfield
: RETURN enumerationfieldF.name |
4419 set
: RETURN NulName |
4420 proctype
: RETURN NulName |
4421 subscript
: RETURN NulName |
4423 procedure
: RETURN procedureF.name |
4424 def
: RETURN defF.name |
4425 imp
: RETURN impF.name |
4426 module
: RETURN moduleF.name |
4434 assignment
: RETURN NulName |
4455 lessequal
: RETURN NulName |
4456 adr
: RETURN makeKey ('ADR') |
4457 size
: RETURN makeKey ('SIZE') |
4458 tsize
: RETURN makeKey ('TSIZE') |
4459 chr
: RETURN makeKey ('CHR') |
4460 abs
: RETURN makeKey ('ABS') |
4461 ord
: RETURN makeKey ('ORD') |
4462 float
: RETURN makeKey ('FLOAT') |
4463 trunc
: RETURN makeKey ('TRUNC') |
4464 high
: RETURN makeKey ('HIGH') |
4465 throw
: RETURN makeKey ('THROW') |
4466 unreachable
: RETURN makeKey ('builtin_unreachable') |
4467 cmplx
: RETURN makeKey ('CMPLX') |
4468 re
: RETURN makeKey ('RE') |
4469 im
: RETURN makeKey ('IM') |
4470 max
: RETURN makeKey ('MAX') |
4471 min
: RETURN makeKey ('MIN') |
4472 pointerref
: RETURN NulName |
4473 funccall
: RETURN NulName |
4474 identlist
: RETURN NulName
4484 isUnary - returns TRUE if, n, is an unary node.
4487 PROCEDURE isUnary (n
: node
) : BOOLEAN ;
4519 isBinary - returns TRUE if, n, is an binary node.
4522 PROCEDURE isBinary (n
: node
) : BOOLEAN ;
4553 makeUnary - create a unary expression node with, e, as the argument
4554 and res as the return type.
4557 PROCEDURE makeUnary (k
: nodeT
; e
: node
; res
: node
) : node
;
4588 tsize
: WITH unaryF
DO
4601 isLeafString - returns TRUE if n is a leaf node which is a string constant.
4604 PROCEDURE isLeafString (n
: node
) : BOOLEAN ;
4606 RETURN isString (n
) OR
4607 (isLiteral (n
) AND (getType (n
) = charN
)) OR
4608 (isConst (n
) AND (getExprType (n
) = charN
))
4613 getLiteralStringContents - return the contents of a literal node as a string.
4616 PROCEDURE getLiteralStringContents (n
: node
) : String
;
4622 assert (n^.kind
= literal
) ;
4623 s
:= InitStringCharStar (keyToCharStar (n^.literalF.name
)) ;
4625 IF n^.literalF.type
= charN
4627 IF DynamicStrings.
char (s
, -1) = 'C'
4629 IF DynamicStrings.
Length (s
) > 1
4631 number
:= DynamicStrings.
Slice (s
, 0, -1) ;
4632 content
:= DynamicStrings.
InitStringChar (VAL (CHAR, ostoc (number
))) ;
4633 number
:= DynamicStrings.
KillString (number
)
4635 content
:= DynamicStrings.
InitStringChar ('C')
4638 content
:= DynamicStrings.
Dup (s
)
4641 metaError1 ('cannot obtain string contents from {%1k}', n^.literalF.name
)
4643 s
:= DynamicStrings.
KillString (s
) ;
4645 END getLiteralStringContents
;
4649 getStringContents - return the string contents of a constant, literal,
4650 string or a constexp node.
4653 PROCEDURE getStringContents (n
: node
) : String
;
4657 RETURN getStringContents (n^.constF.value
)
4660 RETURN getLiteralStringContents (n
)
4663 RETURN getString (n
)
4664 ELSIF isConstExp (n
)
4666 RETURN getStringContents (n^.unaryF.arg
)
4669 END getStringContents
;
4676 PROCEDURE addNames (a
, b
: node
) : Name
;
4681 sa
:= DynamicStrings.
InitStringCharStar (keyToCharStar (getSymName (a
))) ;
4682 sb
:= DynamicStrings.
InitStringCharStar (keyToCharStar (getSymName (b
))) ;
4683 sa
:= ConCat (sa
, sb
) ;
4684 n
:= makekey (DynamicStrings.
string (sa
)) ;
4685 sa
:= KillString (sa
) ;
4686 sb
:= KillString (sb
) ;
4695 PROCEDURE resolveString (n
: node
) : node
;
4697 WHILE isConst (n
) OR isConstExp (n
) DO
4700 n
:= n^.constF.value
4707 n
:= makeString (addNames (resolveString (n^.binaryF.left
),
4708 resolveString (n^.binaryF.right
)))
4718 PROCEDURE foldBinary (k
: nodeT
; l
, r
: node
; res
: node
) : node
;
4725 IF (k
= plus
) AND isLeafString (l
) AND isLeafString (r
)
4727 ls
:= getStringContents (l
) ;
4728 rs
:= getStringContents (r
) ;
4729 ls
:= DynamicStrings.
Add (ls
, rs
) ;
4730 n
:= makeString (makekey (DynamicStrings.
string (ls
))) ;
4731 ls
:= DynamicStrings.
KillString (ls
) ;
4732 rs
:= DynamicStrings.
KillString (rs
)
4739 makeBinary - create a binary node with left/right/result type: l, r and resultType.
4742 PROCEDURE makeBinary (k
: nodeT
; l
, r
: node
; resultType
: node
) : node
;
4746 n
:= foldBinary (k
, l
, r
, resultType
) ;
4749 n
:= doMakeBinary (k
, l
, r
, resultType
)
4756 doMakeBinary - returns a binary node containing left/right/result values
4757 l, r, res, with a node operator, k.
4760 PROCEDURE doMakeBinary (k
: nodeT
; l
, r
: node
; res
: node
) : node
;
4785 in
: WITH binaryF
DO
4798 doMakeComponentRef -
4801 PROCEDURE doMakeComponentRef (rec
, field
: node
) : node
;
4805 n
:= newNode (componentref
) ;
4806 n^.componentrefF.rec
:= rec
;
4807 n^.componentrefF.field
:= field
;
4808 n^.componentrefF.resultType
:= getType (field
) ;
4809 initNodeOpaqueState (n
) ;
4811 END doMakeComponentRef
;
4815 makeComponentRef - build a componentref node which accesses, field,
4816 within, record, rec.
4819 PROCEDURE makeComponentRef (rec
, field
: node
) : node
;
4824 n := getLastOp (rec) ;
4825 IF (n#NIL) AND (isDeref (n) OR isPointerRef (n)) AND
4826 (skipType (getType (rec)) = skipType (getType (n)))
4828 a := n^.unaryF.arg ;
4829 n^.kind := pointerref ;
4830 n^.pointerrefF.ptr := a ;
4831 n^.pointerrefF.field := field ;
4832 n^.pointerrefF.resultType := getType (field) ;
4835 RETURN doMakeComponentRef (rec, field)
4840 a
:= rec^.unaryF.arg
;
4841 rec^.kind
:= pointerref
;
4842 rec^.pointerrefF.ptr
:= a
;
4843 rec^.pointerrefF.field
:= field
;
4844 rec^.pointerrefF.resultType
:= getType (field
) ;
4845 initNodeOpaqueState (rec
) ;
4848 RETURN doMakeComponentRef (rec
, field
)
4850 END makeComponentRef
;
4857 PROCEDURE isComponentRef (n
: node
) : BOOLEAN ;
4860 RETURN n^.kind
= componentref
4861 END isComponentRef
;
4865 makePointerRef - build a pointerref node which accesses, field,
4866 within, pointer to record, ptr.
4869 PROCEDURE makePointerRef (ptr
, field
: node
) : node
;
4873 n
:= newNode (pointerref
) ;
4874 n^.pointerrefF.ptr
:= ptr
;
4875 n^.pointerrefF.field
:= field
;
4876 n^.pointerrefF.resultType
:= getType (field
) ;
4877 initNodeOpaqueState (n
) ;
4879 END makePointerRef
;
4883 isPointerRef - returns TRUE if, n, is a pointerref node.
4886 PROCEDURE isPointerRef (n
: node
) : BOOLEAN ;
4889 RETURN n^.kind
= pointerref
4894 makeArrayRef - build an arrayref node which access element,
4895 index, in, array. array is a variable/expression/constant
4896 which has a type array.
4899 PROCEDURE makeArrayRef (array
, index
: node
) : node
;
4904 n
:= newNode (arrayref
) ;
4905 n^.arrayrefF.array
:= array
;
4906 n^.arrayrefF.index
:= index
;
4908 j
:= expListLen (index
) ;
4910 t
:= skipType (getType (t
)) ;
4914 t
:= skipType (getType (t
))
4916 metaError2 ('cannot access {%1N} dimension of array {%2a}', i
, t
)
4920 n^.arrayrefF.resultType
:= t
;
4926 isArrayRef - returns TRUE if the node was an arrayref.
4929 PROCEDURE isArrayRef (n
: node
) : BOOLEAN ;
4932 RETURN n^.kind
= arrayref
4937 makeDeRef - dereferences the pointer defined by, n.
4940 PROCEDURE makeDeRef (n
: node
) : node
;
4944 t
:= skipType (getType (n
)) ;
4945 assert (isPointer (t
)) ;
4946 RETURN makeUnary (deref
, n
, getType (t
))
4951 isDeref - returns TRUE if, n, is a deref node.
4954 PROCEDURE isDeref (n
: node
) : BOOLEAN ;
4957 RETURN n^.kind
= deref
4962 makeBase - create a base type or constant.
4963 It only supports the base types and constants
4967 PROCEDURE makeBase (k
: nodeT
) : node
;
5025 max
: (* legal kind. *) |
5036 makeBinaryTok - creates and returns a boolean type node with,
5040 PROCEDURE makeBinaryTok (op
: toktype
; l
, r
: node
) : node
;
5044 RETURN makeBinary (equal
, l
, r
, booleanN
)
5045 ELSIF (op
=hashtok
) OR (op
=lessgreatertok
)
5047 RETURN makeBinary (notequal
, l
, r
, booleanN
)
5050 RETURN makeBinary (less
, l
, r
, booleanN
)
5053 RETURN makeBinary (greater
, l
, r
, booleanN
)
5054 ELSIF op
=greaterequaltok
5056 RETURN makeBinary (greequal
, l
, r
, booleanN
)
5057 ELSIF op
=lessequaltok
5059 RETURN makeBinary (lessequal
, l
, r
, booleanN
)
5062 RETURN makeBinary (and
, l
, r
, booleanN
)
5065 RETURN makeBinary (or
, l
, r
, booleanN
)
5068 RETURN makeBinary (plus
, l
, r
, NIL)
5071 RETURN makeBinary (sub
, l
, r
, NIL)
5074 RETURN makeBinary (div
, l
, r
, NIL)
5077 RETURN makeBinary (mult
, l
, r
, NIL)
5080 RETURN makeBinary (mod
, l
, r
, NIL)
5083 RETURN makeBinary (in
, l
, r
, NIL)
5086 RETURN makeBinary (divide
, l
, r
, NIL)
5088 HALT (* most likely op needs a clause as above. *)
5094 makeUnaryTok - creates and returns a boolean type node with,
5098 PROCEDURE makeUnaryTok (op
: toktype
; e
: node
) : node
;
5102 RETURN makeUnary (not
, e
, booleanN
)
5105 RETURN makeUnary (plus
, e
, NIL)
5108 RETURN makeUnary (neg
, e
, NIL)
5110 HALT (* most likely op needs a clause as above. *)
5116 isOrdinal - returns TRUE if, n, is an ordinal type.
5119 PROCEDURE isOrdinal (n
: node
) : BOOLEAN ;
5136 bitset
: RETURN TRUE
5145 getType - returns the type associated with node, n.
5148 PROCEDURE getType (n
: node
) : node
;
5154 dispose
: RETURN NIL |
5155 length
: RETURN cardinalN |
5160 nil
: RETURN addressN |
5162 false
: RETURN booleanN |
5163 address
: RETURN n |
5168 cssizet
: RETURN n |
5170 boolean
: RETURN n |
5173 cardinal
: RETURN n |
5174 longcard
: RETURN n |
5175 shortcard
: RETURN n |
5176 integer
: RETURN n |
5177 longint
: RETURN n |
5178 shortint
: RETURN n |
5180 longreal
: RETURN n |
5181 shortreal
: RETURN n |
5185 complex
: RETURN n |
5186 longcomplex
: RETURN n |
5187 shortcomplex
: RETURN n |
5189 (* language features and compound type attributes. *)
5190 type
: RETURN typeF.type |
5192 varient
: RETURN n |
5193 var
: RETURN varF.type |
5194 enumeration
: RETURN n |
5195 subrange
: RETURN subrangeF.type |
5196 array
: RETURN arrayF.type |
5197 string
: RETURN charN |
5198 const
: RETURN constF.type |
5199 literal
: RETURN literalF.type |
5200 varparam
: RETURN varparamF.type |
5201 param
: RETURN paramF.type |
5202 optarg
: RETURN optargF.type |
5203 pointer
: RETURN pointerF.type |
5204 recordfield
: RETURN recordfieldF.type |
5205 varientfield
: RETURN n |
5206 enumerationfield
: RETURN enumerationfieldF.type |
5207 set
: RETURN setF.type |
5208 proctype
: RETURN proctypeF.returnType |
5209 subscript
: RETURN subscriptF.type |
5211 procedure
: RETURN procedureF.returnType |
5212 throw
: RETURN NIL |
5213 unreachable
: RETURN NIL |
5234 divide
: RETURN binaryF.resultType |
5235 in
: RETURN booleanN |
5246 tsize
: RETURN unaryF.resultType |
5255 lessequal
: RETURN booleanN |
5256 trunc
: RETURN integerN |
5257 float
: RETURN realN |
5258 high
: RETURN cardinalN |
5259 ord
: RETURN cardinalN |
5260 chr
: RETURN charN |
5261 cap
: RETURN charN |
5262 arrayref
: RETURN arrayrefF.resultType |
5263 componentref
: RETURN componentrefF.resultType |
5264 pointerref
: RETURN pointerrefF.resultType |
5265 funccall
: RETURN funccallF.type |
5266 setvalue
: RETURN setvalueF.type
5278 PROCEDURE mixTypes (a
, b
: node
) : node
;
5280 IF (a
= addressN
) OR (b
= addressN
)
5292 PROCEDURE doSetExprType (VAR t
: node
; n
: node
) : node
;
5306 PROCEDURE getMaxMinType (n
: node
) : node
;
5308 IF isVar (n
) OR isConst (n
)
5311 ELSIF isConstExp (n
)
5313 n
:= getExprType (n^.unaryF.arg
) ;
5330 PROCEDURE doGetFuncType (n
: node
) : node
;
5334 assert (isFuncCall (n
)) ;
5335 result
:= doSetExprType (n^.funccallF.type
, getType (n^.funccallF.function
)) ;
5336 initNodeOpaqueState (n
) ; (* Update now that the return type is known. *)
5342 doGetExprType - works out the type which is associated with node, n.
5345 PROCEDURE doGetExprType (n
: node
) : node
;
5351 min
: RETURN getMaxMinType (n^.unaryF.arg
) |
5353 val
: RETURN doSetExprType (n^.binaryF.resultType
, n^.binaryF.left
) |
5356 dispose
: RETURN NIL |
5361 nil
: RETURN addressN |
5363 false
: RETURN booleanN |
5364 address
: RETURN n |
5369 cssizet
: RETURN n |
5371 boolean
: RETURN n |
5374 cardinal
: RETURN n |
5375 longcard
: RETURN n |
5376 shortcard
: RETURN n |
5377 integer
: RETURN n |
5378 longint
: RETURN n |
5379 shortint
: RETURN n |
5381 longreal
: RETURN n |
5382 shortreal
: RETURN n |
5386 complex
: RETURN n |
5387 longcomplex
: RETURN n |
5388 shortcomplex
: RETURN n |
5390 (* language features and compound type attributes. *)
5391 type
: RETURN typeF.type |
5393 varient
: RETURN n |
5394 var
: RETURN varF.type |
5395 enumeration
: RETURN n |
5396 subrange
: RETURN subrangeF.type |
5397 array
: RETURN arrayF.type |
5398 string
: RETURN charN |
5399 const
: RETURN doSetExprType (constF.type
, getExprType (constF.value
)) |
5400 literal
: RETURN literalF.type |
5401 varparam
: RETURN varparamF.type |
5402 param
: RETURN paramF.type |
5403 optarg
: RETURN optargF.type |
5404 pointer
: RETURN pointerF.type |
5405 recordfield
: RETURN recordfieldF.type |
5406 varientfield
: RETURN n |
5407 enumerationfield
: RETURN enumerationfieldF.type |
5408 set
: RETURN setF.type |
5409 proctype
: RETURN proctypeF.returnType |
5410 subscript
: RETURN subscriptF.type |
5412 procedure
: RETURN procedureF.returnType |
5413 throw
: RETURN NIL |
5414 unreachable
: RETURN NIL |
5432 divide
: RETURN doSetExprType (binaryF.resultType
, mixTypes (getExprType (binaryF.left
), getExprType (binaryF.right
))) |
5441 lessequal
: RETURN doSetExprType (binaryF.resultType
, booleanN
) |
5442 cmplx
: RETURN doSetExprType (binaryF.resultType
, complexN
) |
5446 neg
: RETURN doSetExprType (unaryF.resultType
, getExprType (unaryF.arg
)) |
5447 adr
: RETURN doSetExprType (unaryF.resultType
, addressN
) |
5449 tsize
: RETURN doSetExprType (unaryF.resultType
, cardinalN
) |
5451 ord
: RETURN doSetExprType (unaryF.resultType
, cardinalN
) |
5452 float
: RETURN doSetExprType (unaryF.resultType
, realN
) |
5453 trunc
: RETURN doSetExprType (unaryF.resultType
, integerN
) |
5454 chr
: RETURN doSetExprType (unaryF.resultType
, charN
) |
5455 cap
: RETURN doSetExprType (unaryF.resultType
, charN
) |
5456 not
: RETURN doSetExprType (unaryF.resultType
, booleanN
) |
5457 re
: RETURN doSetExprType (unaryF.resultType
, realN
) |
5458 im
: RETURN doSetExprType (unaryF.resultType
, realN
) |
5459 arrayref
: RETURN arrayrefF.resultType |
5460 componentref
: RETURN componentrefF.resultType |
5461 pointerref
: RETURN pointerrefF.resultType |
5462 funccall
: RETURN doSetExprType (funccallF.type
, doGetFuncType (n
)) |
5463 setvalue
: RETURN setvalueF.type
5472 getExprType - return the expression type.
5475 PROCEDURE getExprType (n
: node
) : node
;
5479 IF isFuncCall (n
) AND (getType (n
) #
NIL) AND isProcType (skipType (getType (n
)))
5481 RETURN getType (skipType (getType (n
)))
5486 t
:= doGetExprType (n
)
5493 skipType - skips over type aliases.
5496 PROCEDURE skipType (n
: node
) : node
;
5498 WHILE (n#
NIL) AND isType (n
) AND (NOT isCDataType (n
)) DO
5499 IF getType (n
) = NIL
5501 (* this will occur if, n, is an opaque type. *)
5511 getScope - returns the scope associated with node, n.
5514 PROCEDURE getScope (n
: node
) : node
;
5535 false
: RETURN NIL |
5541 cssizet
: RETURN systemN |
5560 shortcomplex
: RETURN NIL |
5561 (* language features and compound type attributes. *)
5562 type
: RETURN typeF.scope |
5563 record
: RETURN recordF.scope |
5564 varient
: RETURN varientF.scope |
5565 var
: RETURN varF.scope |
5566 enumeration
: RETURN enumerationF.scope |
5567 subrange
: RETURN subrangeF.scope |
5568 array
: RETURN arrayF.scope |
5569 string
: RETURN NIL |
5570 const
: RETURN constF.scope |
5571 literal
: RETURN NIL |
5572 varparam
: RETURN varparamF.scope |
5573 param
: RETURN paramF.scope |
5574 optarg
: RETURN optargF.scope |
5575 pointer
: RETURN pointerF.scope |
5576 recordfield
: RETURN recordfieldF.scope |
5577 varientfield
: RETURN varientfieldF.scope |
5578 enumerationfield
: RETURN enumerationfieldF.scope |
5579 set
: RETURN setF.scope |
5580 proctype
: RETURN proctypeF.scope |
5581 subscript
: RETURN NIL |
5583 procedure
: RETURN procedureF.scope |
5595 assignment
: RETURN NIL |
5632 lessequal
: RETURN NIL |
5636 throw
: RETURN systemN |
5641 vardecl
: RETURN vardeclF.scope |
5642 funccall
: RETURN NIL |
5643 explist
: RETURN NIL |
5644 caselabellist
: RETURN NIL |
5645 caselist
: RETURN NIL |
5646 range
: RETURN NIL |
5647 varargs
: RETURN varargsF.scope
5655 foreachDefModuleDo - foreach definition node, n, in the module universe,
5659 PROCEDURE foreachDefModuleDo (p
: performOperation
) ;
5661 ForeachIndiceInIndexDo (defUniverseI
, p
)
5662 END foreachDefModuleDo
;
5666 foreachModModuleDo - foreach implementation or module node, n, in the module universe,
5670 PROCEDURE foreachModModuleDo (p
: performOperation
) ;
5672 ForeachIndiceInIndexDo (modUniverseI
, p
)
5673 END foreachModModuleDo
;
5680 PROCEDURE openOutput
;
5684 s
:= getOutputFile () ;
5685 IF EqualArray (s
, '-')
5687 outputFile
:= StdOut
5689 outputFile
:= OpenToWrite (s
)
5691 mcStream.
setDest (outputFile
)
5699 PROCEDURE closeOutput
;
5703 s
:= getOutputFile () ;
5704 outputFile
:= mcStream.
combine () ;
5705 IF NOT EqualArray (s
, '-')
5713 write - outputs a single char, ch.
5716 PROCEDURE write (ch
: CHAR) ;
5718 WriteChar (outputFile
, ch
) ;
5719 FlushBuffer (outputFile
)
5729 WriteLine (outputFile
) ;
5730 FlushBuffer (outputFile
)
5735 doIncludeC - include header file for definition module, n.
5738 PROCEDURE doIncludeC (n
: node
) ;
5742 s
:= InitStringCharStar (keyToCharStar (getSymName (n
))) ;
5743 IF getExtendedOpaque ()
5745 (* no include in this case. *)
5748 print (doP
, '# include "') ;
5749 prints (doP
, getHPrefix ()) ;
5751 print (doP
, '.h"\n') ;
5752 foreachNodeDo (n^.defF.decls.symbols
, addDoneDef
)
5759 getSymScope - returns the scope where node, n, was declared.
5762 PROCEDURE getSymScope (n
: node
) : node
;
5767 const
: RETURN constF.scope |
5768 type
: RETURN typeF.scope |
5769 var
: RETURN varF.scope |
5770 procedure
: RETURN procedureF.scope
5779 isQualifiedForced - should the node be written with a module prefix?
5782 PROCEDURE isQualifiedForced (n
: node
) : BOOLEAN ;
5784 RETURN (forceQualified
AND
5785 (isType (n
) OR isRecord (n
) OR isArray (n
) OR isEnumeration (n
) OR isEnumerationField (n
)))
5786 END isQualifiedForced
;
5793 PROCEDURE getFQstring (n
: node
) : String
;
5797 IF (getScope (n
) = NIL) OR (isDefUnqualified (getScope (n
)))
5799 RETURN InitStringCharStar (keyToCharStar (getSymName (n
)))
5800 ELSIF isQualifiedForced (n
)
5802 i
:= InitStringCharStar (keyToCharStar (getSymName (n
))) ;
5803 s
:= InitStringCharStar (keyToCharStar (getSymName (getScope (n
)))) ;
5804 RETURN Sprintf2 (InitString ("%s_%s"), s
, i
)
5805 ELSIF (NOT isExported (n
)) OR getIgnoreFQ () OR (isDefUnqualified (getScope (n
)))
5807 RETURN InitStringCharStar (keyToCharStar (getSymName (n
)))
5809 i
:= InitStringCharStar (keyToCharStar (getSymName (n
))) ;
5810 s
:= InitStringCharStar (keyToCharStar (getSymName (getScope (n
)))) ;
5811 RETURN Sprintf2 (InitString ("%s_%s"), s
, i
)
5820 PROCEDURE getFQDstring (n
: node
; scopes
: BOOLEAN) : String
;
5824 IF (getScope (n
) = NIL) OR (isDefUnqualified (getScope (n
)))
5826 RETURN InitStringCharStar (keyToCharStar (getDName (n
, scopes
)))
5827 ELSIF isQualifiedForced (n
)
5829 (* we assume a qualified name will never conflict. *)
5830 i
:= InitStringCharStar (keyToCharStar (getSymName (n
))) ;
5831 s
:= InitStringCharStar (keyToCharStar (getSymName (getScope (n
)))) ;
5832 RETURN Sprintf2 (InitString ("%s_%s"), s
, i
)
5833 ELSIF (NOT isExported (n
)) OR getIgnoreFQ () OR (isDefUnqualified (getScope (n
)))
5835 RETURN InitStringCharStar (keyToCharStar (getDName (n
, scopes
)))
5837 (* we assume a qualified name will never conflict. *)
5838 i
:= InitStringCharStar (keyToCharStar (getSymName (n
))) ;
5839 s
:= InitStringCharStar (keyToCharStar (getSymName (getScope (n
)))) ;
5840 RETURN Sprintf2 (InitString ("%s_%s"), s
, i
)
5846 getString - returns the name as a string.
5849 PROCEDURE getString (n
: node
) : String
;
5851 IF getSymName (n
) = NulName
5853 RETURN InitString ('')
5855 RETURN InitStringCharStar (keyToCharStar (getSymName (n
)))
5861 getCardinal - returns the cardinal type node.
5864 PROCEDURE getCardinal () : node
;
5874 PROCEDURE doNone (n
: node
) ;
5881 doNothing - does nothing!
5884 PROCEDURE doNothing (n
: node
) ;
5893 PROCEDURE doConstC (n
: node
) ;
5895 IF NOT alists.
isItemInList (globalGroup^.doneQ
, n
)
5897 print (doP
, "# define ") ;
5898 doFQNameC (doP
, n
) ;
5899 setNeedSpace (doP
) ;
5900 doExprC (doP
, n^.constF.value
) ;
5902 alists.
includeItemIntoList (globalGroup^.doneQ
, n
)
5908 needsParen - returns TRUE if expression, n, needs to be enclosed in ().
5911 PROCEDURE needsParen (n
: node
) : BOOLEAN ;
5919 false
: RETURN FALSE |
5920 constexp
: RETURN needsParen (unaryF.arg
) |
5921 neg
: RETURN needsParen (unaryF.arg
) |
5922 not
: RETURN needsParen (unaryF.arg
) |
5931 high
: RETURN FALSE |
5932 deref
: RETURN FALSE |
5938 lessequal
: RETURN TRUE |
5939 componentref
: RETURN FALSE |
5940 pointerref
: RETURN FALSE |
5941 cast
: RETURN TRUE |
5943 abs
: RETURN FALSE |
5954 string
: RETURN FALSE |
5957 var
: RETURN FALSE |
5958 arrayref
: RETURN FALSE |
5961 funccall
: RETURN TRUE |
5962 recordfield
: RETURN FALSE |
5982 proc
: RETURN FALSE |
5983 setvalue
: RETURN FALSE |
5984 address
: RETURN TRUE |
5985 procedure
: RETURN FALSE |
5987 cmplx
, re
, im
: RETURN TRUE
5999 PROCEDURE doUnary (p
: pretty
; op
: ARRAY OF CHAR; expr
, type
: node
; l
, r
: BOOLEAN) ;
6010 IF needsParen (expr
)
6022 doSetSub - perform l & (~ r)
6025 PROCEDURE doSetSub (p
: pretty
; left
, right
: node
) ;
6027 IF needsParen (left
)
6038 IF needsParen (right
)
6040 outText (p
, '(~(') ;
6041 doExprC (p
, right
) ;
6045 doExprC (p
, right
) ;
6055 PROCEDURE doPolyBinary (p
: pretty
; op
: nodeT
; left
, right
: node
; l
, r
: BOOLEAN) ;
6059 lt
:= skipType (getExprType (left
)) ;
6060 rt
:= skipType (getExprType (right
)) ;
6061 IF ((lt #
NIL) AND (isSet (lt
) OR isBitset (lt
))) OR
6062 ((rt #
NIL) AND (isSet (rt
) OR isBitset (rt
)))
6066 plus
: doBinary (p
, '|', left
, right
, l
, r
, FALSE) |
6067 sub
: doSetSub (p
, left
, right
) |
6068 mult
: doBinary (p
, '&', left
, right
, l
, r
, FALSE) |
6069 divide
: doBinary (p
, '^', left
, right
, l
, r
, FALSE)
6075 plus
: doBinary (p
, '+', left
, right
, l
, r
, FALSE) |
6076 sub
: doBinary (p
, '-', left
, right
, l
, r
, FALSE) |
6077 mult
: doBinary (p
, '*', left
, right
, l
, r
, FALSE) |
6078 divide
: doBinary (p
, '/', left
, right
, l
, r
, FALSE)
6089 PROCEDURE doBinary (p
: pretty
; op
: ARRAY OF CHAR; left
, right
: node
; l
, r
, unpackProc
: BOOLEAN) ;
6091 IF needsParen (left
)
6094 left
:= doExprCup (p
, left
, unpackProc
, FALSE) ;
6097 left
:= doExprCup (p
, left
, unpackProc
, FALSE)
6108 IF needsParen (right
)
6111 right
:= doExprCup (p
, right
, unpackProc
, FALSE) ;
6114 right
:= doExprCup (p
, right
, unpackProc
, FALSE)
6123 PROCEDURE doPostUnary (p
: pretty
; op
: ARRAY OF CHAR; expr
: node
) ;
6134 PROCEDURE doDeRefC (p
: pretty
; expr
: node
) : node
;
6137 expr
:= castOpaque (p
, expr
, FALSE) ;
6144 doGetLastOp - returns, a, if b is a terminal otherwise walk right.
6147 PROCEDURE doGetLastOp (a
, b
: node
) : node
;
6155 constexp
: RETURN doGetLastOp (b
, unaryF.arg
) |
6156 neg
: RETURN doGetLastOp (b
, unaryF.arg
) |
6157 not
: RETURN doGetLastOp (b
, unaryF.arg
) |
6158 adr
: RETURN doGetLastOp (b
, unaryF.arg
) |
6159 size
: RETURN doGetLastOp (b
, unaryF.arg
) |
6160 tsize
: RETURN doGetLastOp (b
, unaryF.arg
) |
6161 ord
: RETURN doGetLastOp (b
, unaryF.arg
) |
6163 trunc
: RETURN doGetLastOp (b
, unaryF.arg
) |
6164 chr
: RETURN doGetLastOp (b
, unaryF.arg
) |
6165 cap
: RETURN doGetLastOp (b
, unaryF.arg
) |
6166 high
: RETURN doGetLastOp (b
, unaryF.arg
) |
6167 deref
: RETURN doGetLastOp (b
, unaryF.arg
) |
6169 im
: RETURN doGetLastOp (b
, unaryF.arg
) |
6170 equal
: RETURN doGetLastOp (b
, binaryF.right
) |
6171 notequal
: RETURN doGetLastOp (b
, binaryF.right
) |
6172 less
: RETURN doGetLastOp (b
, binaryF.right
) |
6173 greater
: RETURN doGetLastOp (b
, binaryF.right
) |
6174 greequal
: RETURN doGetLastOp (b
, binaryF.right
) |
6175 lessequal
: RETURN doGetLastOp (b
, binaryF.right
) |
6176 componentref
: RETURN doGetLastOp (b
, componentrefF.field
) |
6177 pointerref
: RETURN doGetLastOp (b
, pointerrefF.field
) |
6178 cast
: RETURN doGetLastOp (b
, binaryF.right
) |
6179 val
: RETURN doGetLastOp (b
, binaryF.right
) |
6180 plus
: RETURN doGetLastOp (b
, binaryF.right
) |
6181 sub
: RETURN doGetLastOp (b
, binaryF.right
) |
6182 div
: RETURN doGetLastOp (b
, binaryF.right
) |
6183 mod
: RETURN doGetLastOp (b
, binaryF.right
) |
6184 mult
: RETURN doGetLastOp (b
, binaryF.right
) |
6185 divide
: RETURN doGetLastOp (b
, binaryF.right
) |
6186 in
: RETURN doGetLastOp (b
, binaryF.right
) |
6187 and
: RETURN doGetLastOp (b
, binaryF.right
) |
6188 or
: RETURN doGetLastOp (b
, binaryF.right
) |
6189 cmplx
: RETURN doGetLastOp (b
, binaryF.right
) |
6190 literal
: RETURN a |
6192 enumerationfield
: RETURN a |
6194 max
: RETURN doGetLastOp (b
, unaryF.arg
) |
6195 min
: RETURN doGetLastOp (b
, unaryF.arg
) |
6197 arrayref
: RETURN a |
6198 funccall
: RETURN a |
6199 procedure
: RETURN a |
6200 recordfield
: RETURN a
6208 getLastOp - return the right most non leaf node.
6211 PROCEDURE getLastOp (n
: node
) : node
;
6213 RETURN doGetLastOp (n
, n
)
6221 PROCEDURE doComponentRefC (p
: pretty
; l
, r
: node
) ;
6223 flushOpaque (p
, l
, FALSE) ;
6226 END doComponentRefC
;
6233 PROCEDURE doPointerRefC (p
: pretty
; l
, r
: node
) ;
6235 flushOpaque (p
, l
, FALSE) ;
6245 PROCEDURE doPreBinary (p
: pretty
; op
: ARRAY OF CHAR; left
, right
: node
; l
, r
: BOOLEAN) ;
6260 doExprC (p
, right
) ;
6269 PROCEDURE doConstExpr (p
: pretty
; n
: node
) ;
6276 doEnumerationField -
6279 PROCEDURE doEnumerationField (p
: pretty
; n
: node
) ;
6281 doFQDNameC (p
, n
, FALSE)
6282 END doEnumerationField
;
6286 isZero - returns TRUE if node, n, is zero.
6289 PROCEDURE isZero (n
: node
) : BOOLEAN ;
6293 RETURN isZero (n^.unaryF.arg
)
6295 RETURN getSymName (n
)=makeKey ('0')
6300 doArrayRef - perform an array reference. If constCast
6301 then an unbounded array access will be const_cast
6302 (the constCast should be TRUE if an assignment to
6303 the array is required).
6306 PROCEDURE doArrayRef (p
: pretty
; n
: node
; constCast
: BOOLEAN) ;
6313 assert (isArrayRef (n
)) ;
6314 type
:= skipType (getType (n^.arrayrefF.array
)) ;
6315 IF isUnbounded (type
)
6317 v
:= n^.arrayrefF.array
;
6318 IF constCast
AND isVar (n^.arrayrefF.array
) AND
6319 (v^.varF.isParameter
OR v^.varF.isVarParameter
)
6321 outText (p
, "const_cast<") ;
6322 doTypeNameC (p
, getType (v
)) ;
6324 outTextN (p
, getSymName (n^.arrayrefF.array
)) ;
6327 outTextN (p
, getSymName (n^.arrayrefF.array
))
6330 doExprC (p
, n^.arrayrefF.array
) ;
6331 assert (isArray (type
)) ;
6332 outText (p
, '.array')
6336 c
:= expListLen (n^.arrayrefF.index
) ;
6338 doExprC (p
, getExpList (n^.arrayrefF.index
, i
)) ;
6339 IF isUnbounded (type
)
6343 doSubtractC (p
, getMin (type^.arrayF.subr
)) ;
6346 assert (isArray (type
)) ;
6347 outText (p
, '].array[') ;
6348 type
:= skipType (getType (type
))
6361 PROCEDURE doProcedure (p
: pretty
; n
: node
) ;
6363 assert (isProcedure (n
)) ;
6364 doFQDNameC (p
, n
, TRUE)
6372 PROCEDURE doRecordfield (p
: pretty
; n
: node
) ;
6374 doDNameC (p
, n
, FALSE)
6382 PROCEDURE doCastC (p
: pretty
; t
, e
: node
) ;
6387 doTypeNameC (p
, t
) ;
6390 et
:= skipType (getType (e
)) ;
6391 IF (et #
NIL) AND isAProcType (et
) AND isAProcType (skipType (t
))
6395 outText (p
, '_t)') ;
6398 outText (p
, '.proc}')
6411 PROCEDURE doSetValueC (p
: pretty
; n
: node
) ;
6416 assert (isSetValue (n
)) ;
6417 lo
:= getSetLow (n
) ;
6418 IF n^.setvalueF.type #
NIL
6421 doTypeNameC (p
, n^.setvalueF.type
) ;
6426 IF HighIndice (n^.setvalueF.values
) = 0
6430 i
:= LowIndice (n^.setvalueF.values
) ;
6431 h
:= HighIndice (n^.setvalueF.values
) ;
6439 doExprC (p
, GetIndice (n^.setvalueF.values
, i
)) ;
6440 doSubtractC (p
, lo
) ;
6457 getSetLow - returns the low value of the set type from
6461 PROCEDURE getSetLow (n
: node
) : node
;
6465 IF getType (n
) = NIL
6467 RETURN makeLiteralInt (makeKey ('0'))
6469 type
:= skipType (getType (n
)) ;
6472 RETURN getMin (skipType (getType (type
)))
6474 RETURN makeLiteralInt (makeKey ('0'))
6481 doInC - performs (((1 << (l)) & (r)) != 0)
6484 PROCEDURE doInC (p
: pretty
; l
, r
: node
) ;
6488 lo
:= getSetLow (r
) ;
6489 outText (p
, '(((1') ;
6495 doSubtractC (p
, lo
) ;
6514 PROCEDURE doThrowC (p
: pretty
; n
: node
) ;
6516 assert (isIntrinsic (n
)) ;
6517 outText (p
, "throw") ;
6520 IF expListLen (n^.intrinsicF.args
) = 1
6522 doExprC (p
, getExpList (n^.intrinsicF.args
, 1))
6532 PROCEDURE doUnreachableC (p
: pretty
; n
: node
) ;
6534 assert (isIntrinsic (n
)) ;
6535 outText (p
, "__builtin_unreachable") ;
6538 assert (expListLen (n^.intrinsicF.args
) = 0) ;
6540 END doUnreachableC
;
6547 PROCEDURE outNull (p
: pretty
) ;
6558 PROCEDURE outTrue (p
: pretty
) ;
6561 IF useBool () AND (lang
= ansiCP
)
6574 PROCEDURE outFalse (p
: pretty
) ;
6577 IF useBool () AND (lang
= ansiCP
)
6579 outText (p
, 'false')
6581 outText (p
, 'FALSE')
6590 PROCEDURE doExprC (p
: pretty
; n
: node
) ;
6595 t
:= getExprType (n
) ;
6600 true
: outTrue (p
) |
6601 false
: outFalse (p
) |
6602 constexp
: doUnary (p
, '', unaryF.arg
, unaryF.resultType
, FALSE, FALSE) |
6603 neg
: doUnary (p
, '-', unaryF.arg
, unaryF.resultType
, FALSE, FALSE) |
6604 not
: doUnary (p
, '!', unaryF.arg
, unaryF.resultType
, FALSE, TRUE) |
6605 val
: doValC (p
, n
) |
6606 adr
: doAdrC (p
, n
) |
6608 tsize
: doSizeC (p
, n
) |
6609 float
: doConvertSC (p
, n
, getCRealType ()) |
6610 trunc
: doConvertC (p
, n
, "int") |
6611 ord
: doConvertC (p
, n
, "unsigned int") |
6612 chr
: doConvertC (p
, n
, "char") |
6613 cap
: doCapC (p
, n
) |
6614 abs
: doAbsC (p
, n
) |
6615 high
: doFuncHighC (p
, n^.unaryF.arg
) |
6616 length
: doLengthC (p
, n
) |
6617 min
: doMinC (p
, n
) |
6618 max
: doMaxC (p
, n
) |
6619 throw
: doThrowC (p
, n
) |
6620 unreachable
: doUnreachableC (p
, n
) |
6623 cmplx
: doCmplx (p
, n
) |
6625 deref
: unaryF.arg
:= doDeRefC (p
, unaryF.arg
) |
6626 equal
: doBinary (p
, '==', binaryF.left
, binaryF.right
, TRUE, TRUE, TRUE) |
6627 notequal
: doBinary (p
, '!=', binaryF.left
, binaryF.right
, TRUE, TRUE, TRUE) |
6628 less
: doBinary (p
, '<', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6629 greater
: doBinary (p
, '>', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6630 greequal
: doBinary (p
, '>=', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6631 lessequal
: doBinary (p
, '<=', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6632 componentref
: doComponentRefC (p
, componentrefF.rec
, componentrefF.field
) |
6633 pointerref
: doPointerRefC (p
, pointerrefF.ptr
, pointerrefF.field
) |
6634 cast
: doCastC (p
, binaryF.left
, binaryF.right
) |
6635 plus
: doPolyBinary (p
, plus
, binaryF.left
, binaryF.right
, FALSE, FALSE) |
6636 sub
: doPolyBinary (p
, sub
, binaryF.left
, binaryF.right
, FALSE, FALSE) |
6637 div
: doBinary (p
, '/', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6638 mod
: doBinary (p
, '%', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6639 mult
: doPolyBinary (p
, mult
, binaryF.left
, binaryF.right
, FALSE, FALSE) |
6640 divide
: doPolyBinary (p
, divide
, binaryF.left
, binaryF.right
, FALSE, FALSE) |
6641 in
: doInC (p
, binaryF.left
, binaryF.right
) |
6642 and
: doBinary (p
, '&&', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6643 or
: doBinary (p
, '||', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6644 literal
: doLiteralC (p
, n
) |
6645 const
: doConstExpr (p
, n
) |
6646 enumerationfield
: doEnumerationField (p
, n
) |
6647 string
: doStringC (p
, n
) |
6648 var
: doVar (p
, n
) |
6649 arrayref
: doArrayRef (p
, n
, FALSE) |
6650 funccall
: doFuncExprC (p
, n
) |
6651 procedure
: doProcedure (p
, n
) |
6652 recordfield
: doRecordfield (p
, n
) |
6653 setvalue
: doSetValueC (p
, n
) |
6669 proc
: doBaseC (p
, n
) |
6675 cssizet
: doSystemC (p
, n
) |
6676 type
: doTypeNameC (p
, n
) |
6677 pointer
: doTypeNameC (p
, n
)
6688 PROCEDURE doExprCup (p
: pretty
; n
: node
;
6689 unpackProc
, uncastConst
: BOOLEAN) : node
;
6693 IF uncastConst
AND isArrayRef (n
)
6695 doArrayRef (p
, n
, TRUE)
6700 type
:= skipType (getExprType (n
)) ;
6701 IF (type #
NIL) AND isAProcType (type
)
6703 outText (p
, '.proc')
6715 PROCEDURE doExprM2 (p
: pretty
; n
: node
) ;
6721 nil
: outText (p
, 'NIL') |
6722 true
: outText (p
, 'TRUE') |
6723 false
: outText (p
, 'FALSE') |
6724 constexp
: doUnary (p
, '', unaryF.arg
, unaryF.resultType
, FALSE, FALSE) |
6725 neg
: doUnary (p
, '-', unaryF.arg
, unaryF.resultType
, FALSE, FALSE) |
6726 not
: doUnary (p
, 'NOT', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6727 adr
: doUnary (p
, 'ADR', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6728 size
: doUnary (p
, 'SIZE', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6729 tsize
: doUnary (p
, 'TSIZE', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6730 float
: doUnary (p
, 'FLOAT', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6731 trunc
: doUnary (p
, 'TRUNC', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6732 ord
: doUnary (p
, 'ORD', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6733 chr
: doUnary (p
, 'CHR', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6734 cap
: doUnary (p
, 'CAP', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6735 high
: doUnary (p
, 'HIGH', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6736 re
: doUnary (p
, 'RE', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6737 im
: doUnary (p
, 'IM', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6738 deref
: doPostUnary (p
, '^', unaryF.arg
) |
6739 equal
: doBinary (p
, '=', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6740 notequal
: doBinary (p
, '#', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6741 less
: doBinary (p
, '<', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6742 greater
: doBinary (p
, '>', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6743 greequal
: doBinary (p
, '>=', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6744 lessequal
: doBinary (p
, '<=', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6745 componentref
: doBinary (p
, '.', componentrefF.rec
, componentrefF.field
, FALSE, FALSE, FALSE) |
6746 pointerref
: doBinary (p
, '^.', pointerrefF.ptr
, pointerrefF.field
, FALSE, FALSE, FALSE) |
6747 cast
: doPreBinary (p
, 'CAST', binaryF.left
, binaryF.right
, TRUE, TRUE) |
6748 val
: doPreBinary (p
, 'VAL', binaryF.left
, binaryF.right
, TRUE, TRUE) |
6749 cmplx
: doPreBinary (p
, 'CMPLX', binaryF.left
, binaryF.right
, TRUE, TRUE) |
6750 plus
: doBinary (p
, '+', binaryF.left
, binaryF.right
, FALSE, FALSE, FALSE) |
6751 sub
: doBinary (p
, '-', binaryF.left
, binaryF.right
, FALSE, FALSE, FALSE) |
6752 div
: doBinary (p
, 'DIV', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6753 mod
: doBinary (p
, 'MOD', binaryF.left
, binaryF.right
, TRUE, TRUE, FALSE) |
6754 mult
: doBinary (p
, '*', binaryF.left
, binaryF.right
, FALSE, FALSE, FALSE) |
6755 divide
: doBinary (p
, '/', binaryF.left
, binaryF.right
, FALSE, FALSE, FALSE) |
6756 literal
: doLiteral (p
, n
) |
6757 const
: doConstExpr (p
, n
) |
6758 enumerationfield
: doEnumerationField (p
, n
) |
6759 string
: doString (p
, n
) |
6760 max
: doUnary (p
, 'MAX', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6761 min
: doUnary (p
, 'MIN', unaryF.arg
, unaryF.resultType
, TRUE, TRUE) |
6773 PROCEDURE doVar (p
: pretty
; n
: node
) ;
6775 assert (isVar (n
)) ;
6776 IF n^.varF.isVarParameter
6779 doFQDNameC (p
, n
, TRUE) ;
6782 doFQDNameC (p
, n
, TRUE)
6791 PROCEDURE doLiteralC (p
: pretty
; n
: node
) ;
6795 assert (isLiteral (n
)) ;
6796 s
:= InitStringCharStar (keyToCharStar (getSymName (n
))) ;
6797 IF n^.literalF.type
=charN
6799 IF DynamicStrings.
char (s
, -1)='C'
6801 s
:= DynamicStrings.
Slice (DynamicStrings.
Mark (s
), 0, -1) ;
6802 IF DynamicStrings.
char (s
, 0)#
'0'
6804 s
:= DynamicStrings.
ConCat (InitString('0'), DynamicStrings.
Mark (s
))
6807 outText (p
, "(char)") ;
6809 ELSIF DynamicStrings.
char (s
, -1) = 'H'
6812 s
:= DynamicStrings.
Slice (DynamicStrings.
Mark (s
), 0, -1)
6813 ELSIF DynamicStrings.
char (s
, -1) = 'B'
6816 s
:= DynamicStrings.
Slice (DynamicStrings.
Mark (s
), 0, -1)
6827 PROCEDURE doLiteral (p
: pretty
; n
: node
) ;
6831 assert (isLiteral (n
)) ;
6832 s
:= InitStringCharStar (keyToCharStar (getSymName (n
))) ;
6833 IF n^.literalF.type
=charN
6835 IF DynamicStrings.
char (s
, -1)='C'
6837 s
:= DynamicStrings.
Slice (DynamicStrings.
Mark (s
), 0, -1) ;
6838 IF DynamicStrings.
char (s
, 0)#
'0'
6840 s
:= DynamicStrings.
ConCat (InitString('0'), DynamicStrings.
Mark (s
))
6843 outText (p
, "(char)") ;
6852 isString - returns TRUE if node, n, is a string.
6855 PROCEDURE isString (n
: node
) : BOOLEAN ;
6858 RETURN n^.kind
=string
6866 PROCEDURE doString (p
: pretty
; n
: node
) ;
6870 assert (isString (n
)) ;
6871 s
:= InitStringCharStar (keyToCharStar (getSymName (n
))) ;
6876 IF DynamicStrings.Index (s, '"', 0)=-1
6881 ELSIF DynamicStrings.Index (s, "'", 0)=-1
6887 metaError1 ('illegal string {%1k}', n)
6894 replaceChar - replace every occurance of, ch, by, a and return modified string, s.
6897 PROCEDURE replaceChar (s
: String
; ch
: CHAR; a
: ARRAY OF CHAR) : String
;
6903 i
:= DynamicStrings.
Index (s
, ch
, i
) ;
6906 s
:= ConCat (InitString (a
), DynamicStrings.
Slice (s
, 1, 0)) ;
6910 s
:= ConCat (ConCat (DynamicStrings.
Slice (s
, 0, i
), Mark (InitString (a
))), DynamicStrings.
Slice (s
, i
+1, 0)) ;
6920 toCstring - translates string, n, into a C string
6921 and returns the new String.
6924 PROCEDURE toCstring (n
: Name
) : String
;
6928 s
:= DynamicStrings.
Slice (InitStringCharStar (keyToCharStar (n
)), 1, -1) ;
6929 RETURN replaceChar (replaceChar (s
, '\', '\\'), '"', '\"')
6937 PROCEDURE toCchar (n: Name) : String ;
6941 s := DynamicStrings.Slice (InitStringCharStar (keyToCharStar (n)), 1, -1) ;
6942 RETURN replaceChar (replaceChar (s, '\', '\\'), "'", "\'")
6950 PROCEDURE countChar (s: String; ch: CHAR) : CARDINAL ;
6958 i := DynamicStrings.Index (s, ch, i) ;
6974 PROCEDURE lenCstring (s: String) : CARDINAL ;
6976 RETURN DynamicStrings.Length (s) - countChar (s, '\')
6984 PROCEDURE outCstring (p
: pretty
; s
: node
; aString
: BOOLEAN) ;
6989 outRawS (p
, s^.stringF.cstring
) ;
6993 outRawS (p
, s^.stringF.cchar
) ;
7003 PROCEDURE doStringC (p
: pretty
; n
: node
) ;
7007 assert (isString (n
)) ;
7008 outCstring (p
, n
, NOT n^.stringF.isCharCompatible
)
7010 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
7011 IF DynamicStrings.Length (s)>3
7013 IF DynamicStrings.Index (s, '"', 0)=-1
7015 s := DynamicStrings.Slice (s, 1, -1) ;
7019 ELSIF DynamicStrings.Index (s, "'", 0)=-1
7021 s := DynamicStrings.Slice (s, 1, -1) ;
7026 metaError1 ('illegal string {%1k}', n)
7028 ELSIF DynamicStrings.Length (s) = 3
7030 s := DynamicStrings.Slice (s, 1, -1) ;
7032 IF DynamicStrings.char (s, 0) = "'"
7035 ELSIF DynamicStrings.char (s, 0) = "\"
7054 PROCEDURE isPunct (ch
: CHAR) : BOOLEAN ;
7056 RETURN (ch
= '.') OR (ch
= '(') OR (ch
= ')') OR
7057 (ch
= '^') OR (ch
= ':') OR (ch
= ';') OR
7058 (ch
= '{') OR (ch
= '}') OR (ch
= ',') OR
7067 PROCEDURE isWhite (ch
: CHAR) : BOOLEAN ;
7069 RETURN (ch
= ' ') OR (ch
= tab
) OR (ch
= lf
)
7077 PROCEDURE outText (p
: pretty
; a
: ARRAY OF CHAR) ;
7081 s
:= InitString (a
) ;
7091 PROCEDURE outRawS (p
: pretty
; s
: String
) ;
7101 PROCEDURE outKm2 (p
: pretty
; a
: ARRAY OF CHAR) : pretty
;
7106 IF StrEqual (a
, 'RECORD')
7108 p
:= pushPretty (p
) ;
7109 i
:= getcurpos (p
) ;
7112 p
:= pushPretty (p
) ;
7113 setindent (p
, i
+ indentation
)
7114 ELSIF StrEqual (a
, 'END')
7116 p
:= popPretty (p
) ;
7128 PROCEDURE outKc (p
: pretty
; a
: ARRAY OF CHAR) : pretty
;
7134 s
:= InitString (a
) ;
7135 i
:= DynamicStrings.
Index (s
, '\', 0) ;
7140 t := DynamicStrings.Slice (s, i, 0) ;
7141 s := DynamicStrings.Slice (Mark (s), 0, i)
7143 IF DynamicStrings.char (s, 0)='{'
7145 p := pushPretty (p) ;
7146 c := getcurpos (p) ;
7149 p := pushPretty (p) ;
7150 setindent (p, c + indentationC)
7151 ELSIF DynamicStrings.char (s, 0)='}'
7153 p := popPretty (p) ;
7158 t := KillString (t) ;
7159 s := KillString (s) ;
7168 PROCEDURE outTextS (p: pretty; s: String) ;
7181 PROCEDURE outCard (p: pretty; c: CARDINAL) ;
7185 s := CardinalToString (c, 0, ' ', 10, FALSE) ;
7195 PROCEDURE outTextN (p: pretty; n: Name) ;
7199 s := InitStringCharStar (keyToCharStar (n)) ;
7206 outputEnumerationC -
7209 PROCEDURE outputEnumerationC (p: pretty; n: node) ;
7215 outText (p, "enum {") ;
7216 i := LowIndice (n^.enumerationF.listOfSons) ;
7217 h := HighIndice (n^.enumerationF.listOfSons) ;
7219 s := GetIndice (n^.enumerationF.listOfSons, i) ;
7220 doFQDNameC (p, s, FALSE) ;
7223 outText (p, ",") ; setNeedSpace (p)
7228 END outputEnumerationC ;
7232 isDeclType - return TRUE if the current module should declare type.
7235 PROCEDURE isDeclType (type: node) : BOOLEAN ;
7241 IF isImp (currentModule)
7243 name := getSymName (type) ;
7246 (* Lookup the matching .def module. *)
7247 def := lookupDef (getSymName (currentModule)) ;
7250 (* Return TRUE if the symbol has not already been declared in the .def. *)
7251 RETURN lookupExported (def, name) = NIL
7263 PROCEDURE doEnumerationC (p: pretty; n: node) ;
7267 outputEnumerationC (p, n)
7269 END doEnumerationC ;
7276 PROCEDURE doNamesC (p: pretty; n: Name) ;
7280 s := InitStringCharStar (keyToCharStar (n)) ;
7290 PROCEDURE doNameC (p: pretty; n: node) ;
7292 IF (n#NIL) AND (getSymName (n)#NulName)
7294 doNamesC (p, getSymName (n))
7303 PROCEDURE initCname (VAR c: cnameT) ;
7313 PROCEDURE doCname (n: Name; VAR c: cnameT; scopes: BOOLEAN) : Name ;
7322 s := keyc.cname (n, scopes) ;
7327 c.name := makekey (DynamicStrings.string (s)) ;
7339 PROCEDURE getDName (n: node; scopes: BOOLEAN) : Name ;
7343 m := getSymName (n) ;
7346 procedure : RETURN doCname (m, n^.procedureF.cname, scopes) |
7347 var : RETURN doCname (m, n^.varF.cname, scopes) |
7348 recordfield : RETURN doCname (m, n^.recordfieldF.cname, scopes) |
7349 enumerationfield: RETURN doCname (m, n^.enumerationfieldF.cname, scopes)
7361 PROCEDURE doDNameC (p: pretty; n: node; scopes: BOOLEAN) ;
7363 IF (n#NIL) AND (getSymName (n)#NulName)
7365 doNamesC (p, getDName (n, scopes))
7374 PROCEDURE doFQDNameC (p: pretty; n: node; scopes: BOOLEAN) ;
7378 s := getFQDstring (n, scopes) ;
7388 PROCEDURE doFQNameC (p: pretty; n: node) ;
7392 s := getFQstring (n) ;
7402 PROCEDURE doNameM2 (p: pretty; n: node) ;
7412 PROCEDURE doUsed (p: pretty; used: BOOLEAN) ;
7417 outText (p, "__attribute__((unused))")
7426 PROCEDURE doHighC (p: pretty; a: node; n: Name; isused: BOOLEAN) ;
7428 IF isArray (a) AND isUnbounded (a)
7430 (* need to display high. *)
7431 print (p, ",") ; setNeedSpace (p) ;
7432 doTypeNameC (p, cardinalN) ; setNeedSpace (p) ;
7433 print (p, "_") ; outTextN (p, n) ; print (p, "_high") ;
7443 PROCEDURE doParamConstCast (p: pretty; n: node) ;
7447 ptype := getType (n) ;
7448 IF isArray (ptype) AND isUnbounded (ptype) AND (lang = ansiCP)
7450 outText (p, "const") ;
7453 END doParamConstCast ;
7457 getParameterVariable - returns the variable which shadows the parameter
7458 named, m, in parameter block, n.
7461 PROCEDURE getParameterVariable (n: node; m: Name) : node ;
7465 assert (isParam (n) OR isVarParam (n)) ;
7468 p := n^.paramF.scope
7470 p := n^.varparamF.scope
7472 assert (isProcedure (p)) ;
7473 RETURN lookupInScope (p, m)
7474 END getParameterVariable ;
7478 doParamTypeEmit - emit parameter type for C/C++. It checks to see if the
7479 parameter type is a procedure type and if it were declared
7480 in a definition module for "C" and if so it uses the "C"
7481 definition for a procedure type, rather than the mc
7485 PROCEDURE doParamTypeEmit (p: pretty; paramnode, paramtype: node) ;
7487 assert (isParam (paramnode) OR isVarParam (paramnode)) ;
7488 IF isForC (paramnode) AND isProcType (skipType (paramtype))
7490 doFQNameC (p, paramtype) ;
7493 doTypeNameC (p, paramtype) ;
7494 doOpaqueModifier (p, paramnode) ;
7496 IF nodeUsesOpaque (paramnode) AND (NOT getNodeOpaqueVoidStar (paramnode))
7498 outText (p, '__opaque
')
7502 END doParamTypeEmit ;
7506 doParamTypeNameModifier - Add an _ to an unbounded parameter which is non var.
7509 PROCEDURE doParamTypeNameModifier (p: pretty; ptype: node; varparam: BOOLEAN) ;
7511 IF (NOT varparam) AND isArray (ptype) AND isUnbounded (ptype)
7515 END doParamTypeNameModifier ;
7519 initOpaqueCastState - assign fields opaque and voidstar in opaquestate.
7522 PROCEDURE initOpaqueCastState (VAR opaquestate: opaqueCastState; opaque, voidstar: BOOLEAN) ;
7524 opaquestate.opaque := opaque ;
7525 opaquestate.voidStar := voidstar
7526 END initOpaqueCastState ;
7530 initNodeOpaqueCastState - assign opaque and currentvoidstar
7533 PROCEDURE initNodeOpaqueCastState (n: node; opaque, voidstar: BOOLEAN) ;
7537 opaquecast : initOpaqueCastState (n^.opaquecastF.opaqueState, opaque, voidstar) |
7538 funccall : initOpaqueCastState (n^.funccallF.opaqueState, opaque, voidstar) |
7539 var : initOpaqueCastState (n^.varF.opaqueState, opaque, voidstar) |
7540 array : initOpaqueCastState (n^.arrayF.opaqueState, opaque, voidstar) |
7541 varparam : initOpaqueCastState (n^.varparamF.opaqueState, opaque, voidstar) |
7542 param : initOpaqueCastState (n^.paramF.opaqueState, opaque, voidstar) |
7543 pointer : initOpaqueCastState (n^.pointerF.opaqueState, opaque, voidstar) |
7544 recordfield : initOpaqueCastState (n^.recordfieldF.opaqueState, opaque, voidstar) |
7545 componentref: initOpaqueCastState (n^.componentrefF.opaqueState, opaque, voidstar) |
7546 pointerref : initOpaqueCastState (n^.pointerrefF.opaqueState, opaque, voidstar) |
7547 arrayref : initOpaqueCastState (n^.arrayrefF.opaqueState, opaque, voidstar) |
7548 procedure : initOpaqueCastState (n^.procedureF.opaqueState, opaque, voidstar) |
7549 proctype : initOpaqueCastState (n^.proctypeF.opaqueState, opaque, voidstar)
7554 END initNodeOpaqueCastState ;
7558 setOpaqueCastState - set the voidStar field in opaquestate.
7561 PROCEDURE setOpaqueCastState (VAR opaquestate: opaqueCastState; voidstar: BOOLEAN) ;
7563 opaquestate.voidStar := voidstar
7564 END setOpaqueCastState ;
7568 setNodeOpaqueVoidStar - sets the voidStar field in node to voidstar.
7571 PROCEDURE setNodeOpaqueVoidStar (n: node; voidstar: BOOLEAN) ;
7573 assert (nodeUsesOpaque (n)) ;
7576 opaquecast : setOpaqueCastState (n^.opaquecastF.opaqueState, voidstar) |
7577 funccall : setOpaqueCastState (n^.funccallF.opaqueState, voidstar) |
7578 var : setOpaqueCastState (n^.varF.opaqueState, voidstar) |
7579 array : setOpaqueCastState (n^.arrayF.opaqueState, voidstar) |
7580 varparam : setOpaqueCastState (n^.varparamF.opaqueState, voidstar) |
7581 param : setOpaqueCastState (n^.paramF.opaqueState, voidstar) |
7582 pointer : setOpaqueCastState (n^.pointerF.opaqueState, voidstar) |
7583 recordfield : setOpaqueCastState (n^.recordfieldF.opaqueState, voidstar) |
7584 componentref: assert (NOT voidstar) ;
7585 setOpaqueCastState (n^.componentrefF.opaqueState, voidstar) |
7586 pointerref : assert (NOT voidstar) ;
7587 setOpaqueCastState (n^.pointerrefF.opaqueState, voidstar) |
7588 arrayref : setOpaqueCastState (n^.arrayrefF.opaqueState, voidstar) |
7589 procedure : setOpaqueCastState (n^.procedureF.opaqueState, voidstar) |
7590 proctype : setOpaqueCastState (n^.proctypeF.opaqueState, voidstar)
7595 END setNodeOpaqueVoidStar ;
7599 nodeUsesOpaque - return TRUE if node n uses an opaque type.
7602 PROCEDURE nodeUsesOpaque (n: node) : BOOLEAN ;
7606 opaquecast : RETURN n^.opaquecastF.opaqueState.opaque |
7607 funccall : RETURN n^.funccallF.opaqueState.opaque |
7608 var : RETURN n^.varF.opaqueState.opaque |
7609 array : RETURN n^.arrayF.opaqueState.opaque |
7610 varparam : RETURN n^.varparamF.opaqueState.opaque |
7611 param : RETURN n^.paramF.opaqueState.opaque |
7612 pointer : RETURN n^.pointerF.opaqueState.opaque |
7613 recordfield : RETURN n^.recordfieldF.opaqueState.opaque |
7614 componentref: RETURN n^.componentrefF.opaqueState.opaque |
7615 pointerref : RETURN n^.pointerrefF.opaqueState.opaque |
7616 arrayref : RETURN n^.arrayrefF.opaqueState.opaque |
7617 procedure : RETURN n^.procedureF.opaqueState.opaque |
7618 proctype : RETURN n^.proctypeF.opaqueState.opaque |
7619 deref : RETURN nodeUsesOpaque (n^.unaryF.arg)
7624 END nodeUsesOpaque ;
7628 getNodeOpaqueVoidStar - return TRUE if the opaque type used by node n is a void *.
7631 PROCEDURE getNodeOpaqueVoidStar (n: node) : BOOLEAN ;
7633 assert (nodeUsesOpaque (n)) ;
7636 opaquecast : RETURN n^.opaquecastF.opaqueState.voidStar |
7637 funccall : RETURN n^.funccallF.opaqueState.voidStar |
7638 var : RETURN n^.varF.opaqueState.voidStar |
7639 array : RETURN n^.arrayF.opaqueState.voidStar |
7640 varparam : RETURN n^.varparamF.opaqueState.voidStar |
7641 param : RETURN n^.paramF.opaqueState.voidStar |
7642 pointer : RETURN n^.pointerF.opaqueState.voidStar |
7643 recordfield : RETURN n^.recordfieldF.opaqueState.voidStar |
7644 componentref: RETURN n^.componentrefF.opaqueState.voidStar |
7645 pointerref : RETURN n^.pointerrefF.opaqueState.voidStar |
7646 arrayref : RETURN n^.arrayrefF.opaqueState.voidStar |
7647 procedure : RETURN n^.procedureF.opaqueState.voidStar |
7648 proctype : RETURN n^.proctypeF.opaqueState.voidStar |
7649 deref : RETURN FALSE
7654 END getNodeOpaqueVoidStar ;
7658 getOpaqueFlushNecessary - return TRUE if the value next differs from the opaque state.
7661 PROCEDURE getOpaqueFlushNecessary (state: opaqueCastState; next: BOOLEAN) : BOOLEAN ;
7663 RETURN state.opaque AND (state.voidStar # next)
7664 END getOpaqueFlushNecessary ;
7668 getNodeOpaqueFlushNecessary - return TRUE if the value of next requires a cast.
7671 PROCEDURE getNodeOpaqueFlushNecessary (n: node; next: BOOLEAN) : BOOLEAN ;
7675 opaquecast : RETURN getOpaqueFlushNecessary (n^.opaquecastF.opaqueState, next) |
7676 funccall : RETURN getOpaqueFlushNecessary (n^.funccallF.opaqueState, next) |
7677 var : RETURN getOpaqueFlushNecessary (n^.varF.opaqueState, next) |
7678 array : RETURN getOpaqueFlushNecessary (n^.arrayF.opaqueState, next) |
7679 varparam : RETURN getOpaqueFlushNecessary (n^.varparamF.opaqueState, next) |
7680 param : RETURN getOpaqueFlushNecessary (n^.paramF.opaqueState, next) |
7681 pointer : RETURN getOpaqueFlushNecessary (n^.pointerF.opaqueState, next) |
7682 recordfield : RETURN getOpaqueFlushNecessary (n^.recordfieldF.opaqueState, next) |
7683 componentref: RETURN getOpaqueFlushNecessary (n^.componentrefF.opaqueState, next) |
7684 pointerref : RETURN getOpaqueFlushNecessary (n^.pointerrefF.opaqueState, next) |
7685 arrayref : RETURN getOpaqueFlushNecessary (n^.arrayrefF.opaqueState, next) |
7686 procedure : RETURN getOpaqueFlushNecessary (n^.procedureF.opaqueState, next) |
7687 proctype : RETURN getOpaqueFlushNecessary (n^.proctypeF.opaqueState, next)
7692 END getNodeOpaqueFlushNecessary ;
7696 makeOpaqueCast - wrap node n with an opaquecast node and assign
7697 voidstar into the new opaque state.
7700 PROCEDURE makeOpaqueCast (n: node; voidstar: BOOLEAN) : node ;
7704 o := newNode (opaquecast) ;
7705 WITH o^.opaquecastF DO
7707 initOpaqueCastState (opaqueState, TRUE, voidstar)
7710 END makeOpaqueCast ;
7714 flushOpaque - perform a cast to voidstar (if necessary) and ignore the new
7715 node which could be created.
7718 PROCEDURE flushOpaque (p: pretty; n: node; toVoidStar: BOOLEAN) ;
7722 o := castOpaque (p, n, toVoidStar)
7727 castOpaque - flushes the opaque type casts if necessary and changes the
7728 voidstar boolean value. If necessary it creates a opaquecast
7729 and returns the new node otherwise return n.
7732 PROCEDURE castOpaque (p: pretty; n: node; toVoidStar: BOOLEAN) : node ;
7736 IF getNodeOpaqueFlushNecessary (n, toVoidStar)
7738 type := getType (n) ;
7741 (* next is true cast to void * opaque type. *)
7742 outText (p, 'static_cast
<') ;
7743 doTypeNameC (p, type) ;
7745 outText (p, '> (') ;
7748 RETURN makeOpaqueCast (n, TRUE)
7750 (* next is false cast to __opaque opaque type. *)
7751 outText (p, 'static_cast
<') ;
7752 doTypeNameC (p, type) ;
7753 outText (p, '__opaque
') ;
7755 outText (p, '> (') ;
7758 RETURN makeOpaqueCast (n, FALSE)
7764 dumpOpaqueState (n) ;
7765 IF nodeUsesOpaque (n)
7767 outText (p, ' /* no difference seen
*/ ')
7769 outText (p, ' /* no opaque used
*/ ')
7779 isTypeOpaqueDefImp - returns TRUE if type is an opaque type by checking
7780 the def/imp pair of modules or fall back to the
7784 PROCEDURE isTypeOpaqueDefImp (type: node) : BOOLEAN ;
7795 scope := getScope (type) ;
7798 def := lookupDef (getSymName (scope)) ;
7801 (* Lookup the type name in the matching definition module. *)
7802 opaque := lookupExported (def, getSymName (type)) ;
7803 RETURN (opaque # NIL) AND isType (opaque) AND isTypeOpaque (opaque)
7806 (* Otherwise just check the definition module. *)
7807 RETURN isTypeOpaque (type)
7811 END isTypeOpaqueDefImp ;
7815 isParamVoidStar - return TRUE if the procedure or proctype opaque type
7816 parameter should be implemented as a (void * ).
7819 PROCEDURE isParamVoidStar (n: node) : BOOLEAN ;
7824 proc := getScope (n) ;
7825 assert (isProcedure (proc) OR isProcType (proc)) ;
7826 type := getType (n) ;
7827 RETURN isReturnVoidStar (proc, type)
7828 END isParamVoidStar ;
7832 isRefVoidStar - returns TRUE if the ref node uses an opaque type which
7833 is represented as a (void * ).
7836 PROCEDURE isRefVoidStar (n: node) : BOOLEAN ;
7840 type := getType (n) ;
7841 IF (NOT isType (type)) OR (NOT isTypeOpaque (type))
7843 (* We should finish the procedure as the ref does not use an opaque. *)
7846 (* We check whether the opaque type was declared in the implementation
7847 module. If it is declared in the implementation module then we
7849 RETURN NOT isDeclInImp (type)
7855 isReturnVoidStar - return TRUE if the procedure or proctype opaque type
7856 return type should be implemented as a (void * ).
7859 PROCEDURE isReturnVoidStar (proc, type: node) : BOOLEAN ;
7863 assert (isProcedure (proc) OR isProcType (proc)) ;
7864 IF isExported (proc)
7868 (* Not exported therefore local, we check whether the opaque type
7869 was declared in the implementation module. *)
7870 IF isImp (currentModule)
7874 RETURN NOT isDeclInImp (type)
7879 (* Always use void * in .def modules. *)
7883 END isReturnVoidStar ;
7887 isVarVoidStar - return TRUE if the variable using an opaque type should
7888 be implemented as a (void * ).
7891 PROCEDURE isVarVoidStar (n: node) : BOOLEAN ;
7895 assert (isVar (n)) ;
7896 type := getType (n) ;
7897 IF (NOT isType (type)) OR (NOT isTypeOpaque (type))
7899 (* We should finish the procedure as the variable does not use an opaque. *)
7901 ELSIF isExported (n)
7903 (* Exported variables using an opaque type will always be implemented
7904 with a (void * ). *)
7907 (* Not exported therefore static to the module (local or global non exported
7908 variable), we check whether the opaque type was declared in the
7909 implementation module. If it is declared in the implementation module
7910 then we return FALSE. *)
7911 RETURN NOT isDeclInImp (type)
7917 initNodeOpaqueState - initialize the node opaque state.
7920 PROCEDURE initNodeOpaqueState (n: node) ;
7926 opaquecast : | (* This must be done when the cast direction is known. *)
7927 funccall : assignNodeOpaqueCastState (n, getFunction (n)) |
7928 var : type := getType (n) ;
7929 IF n^.varF.isParameter OR n^.varF.isVarParameter
7931 (* If the variable is really a parameter then it uses
7932 the state of the parameter. *)
7933 initNodeOpaqueCastState (n, isTypeOpaqueDefImp (type),
7934 isParamVoidStar (n))
7936 initNodeOpaqueCastState (n, isTypeOpaqueDefImp (type),
7939 array : type := getType (n) ;
7940 initNodeOpaqueCastState (n, isTypeOpaqueDefImp (type),
7943 param : assert (isProcedure (getScope (n)) OR isProcType (getScope (n))) ;
7944 type := getType (n) ;
7945 initNodeOpaqueCastState (n, isTypeOpaqueDefImp (type),
7946 isParamVoidStar (n)) |
7951 arrayref : type := getType (n) ;
7952 (* In the future this should be revisited. *)
7953 initNodeOpaqueCastState (n, isTypeOpaqueDefImp (type),
7954 isRefVoidStar (n)) |
7955 (* For the moment treat as never exported. *)
7957 procedure : (* We only consider the return type for a procedure or proctype.
7958 The parameters and local vars are handled separately (see
7960 type := getType (n) ;
7963 (* No return type, therefore no opaque type used. *)
7964 initNodeOpaqueCastState (n, FALSE, FALSE)
7966 (* Init state from the return type. Is type an opaque type?
7967 Is the opaque type declared in this module? *)
7968 initNodeOpaqueCastState (n, isTypeOpaqueDefImp (type),
7969 isReturnVoidStar (n, type))
7978 END initNodeOpaqueState ;
7982 assignNodeOpaqueCastState - copy the opaqueCastState from src into dest.
7985 PROCEDURE assignNodeOpaqueCastState (dest, src: node) ;
7987 IF nodeUsesOpaque (src)
7989 initNodeOpaqueCastState (dest, TRUE, getNodeOpaqueVoidStar (src))
7991 initNodeOpaqueCastState (dest, FALSE, FALSE)
7993 END assignNodeOpaqueCastState ;
7997 assignNodeOpaqueCastFalse - assign the voidstar field of dest to false.
7998 It assigns the opaque field of dest to the value
7999 of the src opaque field.
8002 PROCEDURE assignNodeOpaqueCastFalse (dest, src: node) ;
8004 IF nodeUsesOpaque (src)
8006 initNodeOpaqueCastState (dest, TRUE, FALSE)
8008 initNodeOpaqueCastState (dest, FALSE, FALSE)
8010 END assignNodeOpaqueCastFalse ;
8017 PROCEDURE dumpOpaqueState (n: node) ;
8041 outText (doP, "/* ") ;
8043 outText (doP, " ") ;
8046 opaquecast : outText (doP, "opaquecast") |
8047 funccall : outText (doP, "funccall") |
8048 var : outText (doP, "var") |
8049 array : outText (doP, "array") |
8050 varparam : outText (doP, "varparam") |
8051 param : outText (doP, "param") |
8052 pointer : outText (doP, "pointer") |
8053 recordfield : outText (doP, "recordfield") |
8054 componentref: outText (doP, "componentref") |
8055 pointerref : outText (doP, "pointerref") |
8056 arrayref : outText (doP, "arrayref") |
8057 procedure : outText (doP, "procedure") |
8058 proctype : outText (doP, "proctype")
8062 IF nodeUsesOpaque (o)
8064 IF getNodeOpaqueVoidStar (o)
8066 outText (doP, " uses (void *) opaque")
8068 outText (doP, " uses opaque__full")
8071 outText (doP, " */ \n")
8073 END dumpOpaqueState ;
8077 doParamC - emit parameter for C/C++.
8080 PROCEDURE doParamC (p: pretty; n: node) ;
8088 assert (isParam (n)) ;
8089 ptype := getType (n) ;
8090 IF n^.paramF.namelist = NIL
8092 doParamConstCast (p, n) ;
8093 doTypeNameC (p, ptype) ;
8094 doUsed (p, n^.paramF.isUsed) ;
8095 IF isArray (ptype) AND isUnbounded (ptype)
8097 outText (p, ',') ; setNeedSpace (p) ;
8098 outText (p, 'unsigned int
')
8101 assert (isIdentList (n^.paramF.namelist)) ;
8102 l := n^.paramF.namelist^.identlistF.names ;
8105 doParamConstCast (p, n) ;
8106 doParamTypeEmit (p, n, ptype) ;
8107 IF isArray (ptype) AND isUnbounded (ptype)
8109 doUsed (p, n^.paramF.isUsed) ;
8110 outText (p, ',') ; setNeedSpace (p) ;
8111 outText (p, 'unsigned int
')
8114 t := wlists.noOfItemsInList (l) ;
8117 doParamConstCast (p, n) ;
8118 doParamTypeEmit (p, n, ptype) ;
8119 i := wlists.getItemFromList (l, c) ;
8120 IF isArray (ptype) AND isUnbounded (ptype)
8126 v := getParameterVariable (n, i) ;
8129 doNamesC (p, keyc.cnamen (i, TRUE))
8131 doFQDNameC (p, v, TRUE)
8133 doParamTypeNameModifier (p, ptype, FALSE) ;
8134 doUsed (p, n^.paramF.isUsed) ;
8135 doHighC (p, ptype, i, n^.paramF.isUsed) ;
8138 outText (p, ',') ; setNeedSpace (p)
8148 doVarParamC - emit a VAR parameter for C/C++.
8151 PROCEDURE doVarParamC (p: pretty; n: node) ;
8159 assert (isVarParam (n)) ;
8160 ptype := getType (n) ;
8161 IF n^.varparamF.namelist = NIL
8163 doTypeNameC (p, ptype) ;
8164 (* doTypeC (p, ptype, n) ; *)
8165 IF NOT isArray (ptype)
8170 doUsed (p, n^.varparamF.isUsed) ;
8171 IF isArray (ptype) AND isUnbounded (ptype)
8173 outText (p, ',') ; setNeedSpace (p) ;
8174 outText (p, 'unsigned int
')
8177 assert (isIdentList (n^.varparamF.namelist)) ;
8178 l := n^.varparamF.namelist^.identlistF.names ;
8181 doParamTypeEmit (p, n, ptype) ;
8182 doUsed (p, n^.varparamF.isUsed)
8184 t := wlists.noOfItemsInList (l) ;
8187 doParamTypeEmit (p, n, ptype) ;
8188 IF NOT isArray (ptype)
8193 i := wlists.getItemFromList (l, c) ;
8194 v := getParameterVariable (n, i) ;
8197 doNamesC (p, keyc.cnamen (i, TRUE))
8199 doFQDNameC (p, v, TRUE)
8201 doParamTypeNameModifier (p, ptype, TRUE) ;
8202 doUsed (p, n^.varparamF.isUsed) ;
8203 doHighC (p, ptype, i, n^.varparamF.isUsed) ;
8206 outText (p, ',') ; setNeedSpace (p)
8219 PROCEDURE doOptargC (p: pretty; n: node) ;
8226 assert (isOptarg (n)) ;
8227 ptype := getType (n) ;
8228 assert (n^.optargF.namelist # NIL) ;
8229 assert (isIdentList (n^.paramF.namelist)) ;
8230 l := n^.paramF.namelist^.identlistF.names ;
8232 t := wlists.noOfItemsInList (l) ;
8234 doTypeNameC (p, ptype) ;
8235 i := wlists.getItemFromList (l, 1) ;
8245 PROCEDURE doParameterC (p: pretty; n: node) ;
8250 ELSIF isVarParam (n)
8267 PROCEDURE doProcTypeC (p: pretty; t, n: node) ;
8269 assert (isType (t)) ;
8270 IF isDeclType (t) AND isDeclType (n)
8273 doCompletePartialProcType (p, t, n)
8279 isDeclInImp - returns TRUE if node type is declared as an opaque and
8280 is declared fully in the current implementation module.
8281 This should only be called if isType (type). Its purpose
8282 is specific to a type checking whether it is an opaque type
8283 declared in the .def/.mod pair of the current imp module.
8286 PROCEDURE isDeclInImp (type: node) : BOOLEAN ;
8292 assert (isType (type)) ;
8293 scope := getScope (type) ;
8294 IF isTypeOpaqueDefImp (type) AND isImp (currentModule)
8296 name := getSymName (type) ;
8299 (* Lookup the matching .def module. *)
8300 def := lookupDef (getSymName (currentModule)) ;
8301 IF (def # NIL) AND ((def = scope) OR (currentModule = scope))
8303 (* Return TRUE if the symbol has already been declared in the .def. *)
8304 RETURN lookupExported (def, name) # NIL
8313 doTypeNameModifier - adds the __opaque modifier to the type n provided
8314 it is an opaque type which is being declared in the
8315 implementation module.
8318 PROCEDURE doTypeNameModifier (p: pretty; n: node) ;
8320 IF isTypeOpaqueDefImp (n) AND isImp (currentModule)
8322 outText (p, '__opaque
')
8324 END doTypeNameModifier ;
8328 isGccType - return TRUE if n is tree or location_t.
8331 PROCEDURE isGccType (n: node) : BOOLEAN ;
8333 RETURN (getGccConfigSystem () AND
8334 ((getSymName (n) = makeKey ('location_t
')) OR
8335 (getSymName (n) = makeKey ('tree
'))))
8340 doGccType - record whether we are going to declare tree or location_t
8341 so that the appropriate gcc header can be included instead.
8344 PROCEDURE doGccType (p: pretty; n: node) ;
8346 IF getGccConfigSystem ()
8348 IF getSymName (n) = makeKey ('location_t
')
8350 outText (p, "/* Not going to declare ") ;
8351 doTypeNameC (p, n) ;
8352 outText (p, " as it is declared in the gcc header input.h. */\n\n") ;
8354 ELSIF getSymName (n) = makeKey ('tree
')
8356 outText (p, "/* Not going to declare ") ;
8357 doTypeNameC (p, n) ;
8358 outText (p, " as it is declared in the gcc header tree.h. */\n\n") ;
8366 isCDataType - return true if n is charStar or constCharStar.
8369 PROCEDURE isCDataType (n: node) : BOOLEAN ;
8371 RETURN (n # NIL) AND ((n = charStarN) OR (n = constCharStarN))
8376 isCDataTypes - return TRUE if n is CharStar or ConstCharStar.
8379 PROCEDURE isCDataTypes (n: node) : BOOLEAN ;
8383 scope := getScope (n) ;
8384 RETURN (scope # NIL) AND (getSymName (scope) = makeKey ('CDataTypes
')) AND
8385 ((getSymName (n) = makeKey ('CharStar
')) OR
8386 (getSymName (n) = makeKey ('ConstCharStar
')))
8391 doCDataTypes - if we are going to declare CharStar or ConstCharStar
8392 then generate a comment instead.
8395 PROCEDURE doCDataTypes (p: pretty; n: node) ;
8399 IF getSymName (n) = makeKey ('CharStar
')
8401 outText (p, "/* Not going to declare ") ;
8402 doTypeNameC (p, n) ;
8403 outText (p, " as it is a C type. */\n\n") ;
8405 ELSIF getSymName (n) = makeKey ('ConstCharStar
')
8407 outText (p, "/* Not going to declare ") ;
8408 doTypeNameC (p, n) ;
8409 outText (p, " as it is a C type. */\n\n") ;
8417 doCDataTypesC - generate the C representation of the CDataTypes data types.
8420 PROCEDURE doCDataTypesC (p: pretty; n: node) ;
8424 outText (p, "char *") ;
8426 ELSIF n = constCharStarN
8428 outText (p, "const char *") ;
8435 doTypeOrPointer - only declare type or pointer n providing that
8436 the name is not location_t or tree and
8437 the --gccConfigSystem option is enabled.
8440 PROCEDURE doTypeOrPointer (p: pretty; n: node) ;
8447 ELSIF isCDataTypes (n)
8452 outText (p, "typedef") ; setNeedSpace (p) ;
8458 doTypeNameC (p, n) ;
8459 doTypeNameModifier (p, n) ;
8460 outText (p, ";\n\n")
8462 END doTypeOrPointer ;
8466 doTypedef - generate a typedef for n provuiding it is not
8469 PROCEDURE doTypedef (p: pretty; n: node) ;
8476 ELSIF isCDataTypes (n)
8481 outText (p, "typedef") ; setNeedSpace (p) ;
8487 doTypeNameC (p, n) ;
8488 doTypeNameModifier (p, n) ;
8489 outText (p, ";\n\n")
8498 PROCEDURE doTypesC (n: node) ;
8507 doProcTypeC (doP, n, m)
8508 ELSIF isType (m) OR isPointer (m)
8510 doTypeOrPointer (doP, n)
8511 ELSIF isEnumeration (m)
8515 outText (doP, "typedef") ; setNeedSpace (doP) ;
8516 doTypeC (doP, m, m) ;
8517 setNeedSpace (doP) ;
8518 doTypeNameC (doP, n) ;
8519 outText (doP, ";\n\n")
8529 doCompletePartialC -
8532 PROCEDURE doCompletePartialC (n: node) ;
8541 doCompletePartialRecord (doP, n, m)
8544 doCompletePartialArray (doP, n, m)
8545 ELSIF isProcType (m)
8547 doCompletePartialProcType (doP, n, m)
8550 END doCompletePartialC ;
8554 doCompletePartialRecord -
8557 PROCEDURE doCompletePartialRecord (p: pretty; t, r: node) ;
8562 assert (isRecord (r)) ;
8563 assert (isType (t)) ;
8564 outText (p, "struct") ; setNeedSpace (p) ;
8566 outText (p, "_r") ; setNeedSpace (p) ;
8567 p := outKc (p, "{\n") ;
8568 i := LowIndice (r^.recordF.listOfSons) ;
8569 h := HighIndice (r^.recordF.listOfSons) ;
8571 f := GetIndice (r^.recordF.listOfSons, i) ;
8572 IF isRecordField (f)
8574 IF NOT f^.recordfieldF.tag
8576 doRecordFieldC (p, f) ;
8583 ELSIF isVarientField (f)
8585 doVarientFieldC (p, f)
8589 p := outKc (p, "};\n\n")
8590 END doCompletePartialRecord ;
8594 doCompletePartialArray -
8597 PROCEDURE doCompletePartialArray (p: pretty; t, r: node) ;
8601 assert (isArray (r)) ;
8602 type := r^.arrayF.type ;
8604 outText (p, "struct") ; setNeedSpace (p) ;
8606 outText (p, "_a {") ;
8608 doTypeC (p, type, s) ;
8610 outText (p, "array[") ;
8611 doSubrC (p, r^.arrayF.subr) ;
8615 END doCompletePartialArray ;
8622 PROCEDURE lookupConst (type: node; n: Name) : node ;
8624 RETURN makeLiteralInt (n)
8632 PROCEDURE doMin (n: node) : node ;
8640 RETURN lookupConst (integerN, makeKey ('INT_MIN
'))
8644 RETURN lookupConst (cardinalN, makeKey ('UINT_MIN
'))
8648 RETURN lookupConst (longintN, makeKey ('LONG_MIN
'))
8652 RETURN lookupConst (longcardN, makeKey ('LONG_MIN
'))
8656 RETURN lookupConst (charN, makeKey ('CHAR_MIN
'))
8659 assert (isSubrange (bitnumN)) ;
8660 RETURN bitnumN^.subrangeF.low
8664 RETURN lookupConst (locN, makeKey ('UCHAR_MIN
'))
8668 RETURN lookupConst (byteN, makeKey ('UCHAR_MIN
'))
8672 RETURN lookupConst (wordN, makeKey ('UCHAR_MIN
'))
8675 RETURN lookupConst (addressN, makeKey ('((void *)
0)'))
8677 HALT (* finish the cacading elsif statement. *)
8686 PROCEDURE doMax (n: node) : node ;
8694 RETURN lookupConst (integerN, makeKey ('INT_MAX
'))
8698 RETURN lookupConst (cardinalN, makeKey ('UINT_MAX
'))
8702 RETURN lookupConst (longintN, makeKey ('LONG_MAX
'))
8706 RETURN lookupConst (longcardN, makeKey ('ULONG_MAX
'))
8710 RETURN lookupConst (charN, makeKey ('CHAR_MAX
'))
8713 assert (isSubrange (bitnumN)) ;
8714 RETURN bitnumN^.subrangeF.high
8718 RETURN lookupConst (locN, makeKey ('UCHAR_MAX
'))
8722 RETURN lookupConst (byteN, makeKey ('UCHAR_MAX
'))
8726 RETURN lookupConst (wordN, makeKey ('UINT_MAX
'))
8729 metaError1 ('trying to obtain
MAX ({%1ad
}) is illegal
', n) ;
8732 HALT (* finish the cacading elsif statement. *)
8741 PROCEDURE getMax (n: node) : node ;
8746 RETURN n^.subrangeF.high
8747 ELSIF isEnumeration (n)
8749 RETURN n^.enumerationF.high
8751 assert (isOrdinal (n)) ;
8761 PROCEDURE getMin (n: node) : node ;
8766 RETURN n^.subrangeF.low
8767 ELSIF isEnumeration (n)
8769 RETURN n^.enumerationF.low
8771 assert (isOrdinal (n)) ;
8781 PROCEDURE doSubtractC (p: pretty; s: node) ;
8795 PROCEDURE doSubrC (p: pretty; s: node) ;
8803 high := getMax (s) ;
8805 doSubtractC (p, low) ;
8807 ELSIF isEnumeration (s)
8810 high := getMax (s) ;
8812 doSubtractC (p, low) ;
8815 assert (isSubrange (s)) ;
8816 IF (s^.subrangeF.high = NIL) OR (s^.subrangeF.low = NIL)
8818 doSubrC (p, getType (s))
8820 doExprC (p, s^.subrangeF.high) ;
8821 doSubtractC (p, s^.subrangeF.low) ;
8829 doCompletePartialProcType -
8832 PROCEDURE doCompletePartialProcType (p: pretty; t, n: node) ;
8834 IF isDeclType (t) AND isDeclType (n)
8836 outputCompletePartialProcType (p, t, n)
8838 END doCompletePartialProcType ;
8842 outputCompletePartialProcType -
8845 PROCEDURE outputCompletePartialProcType (p: pretty; t, n: node) ;
8850 assert (isProcType (n)) ;
8852 outText (p, "typedef") ; setNeedSpace (p) ;
8853 doTypeC (p, n^.proctypeF.returnType, u) ;
8854 doOpaqueModifier (p, n) ;
8858 outText (p, "_t) (") ;
8859 i := LowIndice (n^.proctypeF.parameters) ;
8860 h := HighIndice (n^.proctypeF.parameters) ;
8862 v := GetIndice (n^.proctypeF.parameters, i) ;
8863 doParameterC (p, v) ;
8867 outText (p, ",") ; setNeedSpace (p)
8875 outText (p, ");\n") ;
8876 IF isDefForCNode (n)
8878 (* emit a C named type which differs from the m2 proctype. *)
8879 outText (p, "typedef") ; setNeedSpace (p) ;
8881 outText (p, "_t") ; setNeedSpace (p) ;
8883 outText (p, "_C;\n\n")
8885 outText (p, "struct") ; setNeedSpace (p) ;
8887 outText (p, "_p {") ; setNeedSpace (p) ;
8889 outText (p, "_t proc; };\n\n")
8890 END outputCompletePartialProcType ;
8897 PROCEDURE isBase (n: node) : BOOLEAN ;
8928 PROCEDURE doBoolC (p: pretty) ;
8934 outText (p, 'unsigned int
')
8943 PROCEDURE doBaseC (p: pretty; n: node) ;
8947 char : outText (p, 'char
') |
8948 cardinal : outText (p, 'unsigned int
') |
8949 longcard : outText (p, 'long unsigned int
') |
8950 shortcard : outText (p, 'short unsigned int
') |
8951 integer : outText (p, 'int
') |
8952 longint : outText (p, 'long int
') |
8953 shortint : outText (p, 'short int
') |
8954 complex : outText (p, 'double complex
') |
8955 longcomplex : outText (p, 'long double complex
') |
8956 shortcomplex: outText (p, 'float complex
') |
8957 real : outTextS (p, getCRealType ()) |
8958 longreal : outTextS (p, getCLongRealType ()) |
8959 shortreal : outTextS (p, getCShortRealType ()) |
8960 bitset : outText (p, 'unsigned int
') |
8961 boolean : doBoolC (p) |
8962 proc : outText (p, 'PROC')
8973 PROCEDURE isSystem (n: node) : BOOLEAN ;
8977 address: RETURN TRUE |
8979 byte : RETURN TRUE |
8980 word : RETURN TRUE |
8981 csizet : RETURN TRUE |
8982 cssizet: RETURN TRUE
8994 PROCEDURE doSystemC (p: pretty; n: node) ;
8998 address: outText (p, 'void
*') |
8999 loc : outText (p, 'unsigned char
') ; setNeedSpace (p) |
9000 byte : outText (p, 'unsigned char
') ; setNeedSpace (p) |
9001 word : outText (p, 'unsigned int
') ; setNeedSpace (p) |
9002 csizet : outText (p, 'size_t
') ; setNeedSpace (p) ; keyc.useSize_t |
9003 cssizet: outText (p, 'ssize_t
') ; setNeedSpace (p) ; keyc.useSSize_t
9013 PROCEDURE doArrayC (p: pretty; n: node) ;
9017 assert (isArray (n)) ;
9018 t := n^.arrayF.type ;
9019 s := n^.arrayF.subr ;
9027 outText (p, "struct") ;
9033 outText (p, "array[") ;
9034 IF isZero (getMin (s))
9036 doExprC (p, getMax (s))
9038 doExprC (p, getMax (s)) ;
9039 doSubtractC (p, getMin (s))
9053 PROCEDURE doPointerC (p: pretty; n: node; VAR m: node) ;
9057 t := n^.pointerF.type ;
9069 PROCEDURE doRecordFieldC (p: pretty; f: node) ;
9075 doTypeC (p, f^.recordfieldF.type, m) ;
9076 IF isType (f^.recordfieldF.type) AND isDeclInImp (f^.recordfieldF.type)
9078 outText (p, '__opaque
')
9081 doDNameC (p, f, FALSE)
9082 END doRecordFieldC ;
9089 PROCEDURE doVarientFieldC (p: pretty; n: node) ;
9094 assert (isVarientField (n)) ;
9095 IF NOT n^.varientfieldF.simple
9097 outText (p, "struct") ; setNeedSpace (p) ;
9098 p := outKc (p, "{\n")
9100 i := LowIndice (n^.varientfieldF.listOfSons) ;
9101 t := HighIndice (n^.varientfieldF.listOfSons) ;
9103 q := GetIndice (n^.varientfieldF.listOfSons, i) ;
9104 IF isRecordField (q)
9106 IF NOT q^.recordfieldF.tag
9108 doRecordFieldC (p, q) ;
9120 IF NOT n^.varientfieldF.simple
9122 p := outKc (p, "};\n")
9124 END doVarientFieldC ;
9131 PROCEDURE doVarientC (p: pretty; n: node) ;
9136 assert (isVarient (n)) ;
9137 IF n^.varientF.tag # NIL
9139 IF isRecordField (n^.varientF.tag)
9141 doRecordFieldC (p, n^.varientF.tag) ;
9142 outText (p, "; /* case tag */\n")
9143 ELSIF isVarientField (n^.varientF.tag)
9146 (* doVarientFieldC (p, n^.varientF.tag) *)
9151 outText (p, "union") ;
9153 p := outKc (p, "{\n") ;
9154 i := LowIndice (n^.varientF.listOfSons) ;
9155 t := HighIndice (n^.varientF.listOfSons) ;
9157 q := GetIndice (n^.varientF.listOfSons, i) ;
9158 IF isRecordField (q)
9160 IF NOT q^.recordfieldF.tag
9162 doRecordFieldC (p, q) ;
9165 ELSIF isVarientField (q)
9167 doVarientFieldC (p, q)
9181 PROCEDURE doRecordC (p: pretty; n: node; VAR m: node) ;
9186 assert (isRecord (n)) ;
9187 outText (p, "struct") ;
9189 p := outKc (p, "{") ;
9190 i := LowIndice (n^.recordF.listOfSons) ;
9191 h := HighIndice (n^.recordF.listOfSons) ;
9192 setindent (p, getcurpos (p) + indentation) ;
9195 f := GetIndice (n^.recordF.listOfSons, i) ;
9196 IF isRecordField (f)
9198 IF NOT f^.recordfieldF.tag
9200 doRecordFieldC (p, f) ;
9207 ELSIF isVarientField (f)
9209 doVarientFieldC (p, f)
9213 p := outKc (p, "}") ;
9222 PROCEDURE isBitset (n: node) : BOOLEAN ;
9229 isNegative - returns TRUE if expression, n, is negative.
9232 PROCEDURE isNegative (n: node) : BOOLEAN ;
9234 (* --fixme-- needs to be completed. *)
9243 PROCEDURE doSubrangeC (p: pretty; n: node) ;
9245 assert (isSubrange (n)) ;
9246 IF isNegative (n^.subrangeF.low)
9248 outText (p, "int") ; setNeedSpace (p)
9250 outText (p, "unsigned int") ; setNeedSpace (p)
9256 doSetC - generates a C type which holds the set.
9257 Currently we only support sets of size WORD.
9260 PROCEDURE doSetC (p: pretty; n: node) ;
9262 assert (isSet (n)) ;
9263 outText (p, "unsigned int") ; setNeedSpace (p)
9271 PROCEDURE doTypeC (p: pretty; n: node; VAR m: node) ;
9276 ELSIF isCDataTypes (n)
9278 doCDataTypesC (p, n)
9285 ELSIF isEnumeration (n)
9287 doEnumerationC (p, n)
9291 ELSIF isProcType (n)
9293 doProcTypeC (p, n, m)
9302 doPointerC (p, n, m)
9303 ELSIF isSubrange (n)
9309 ELSIF isCDataTypes (n)
9311 doCDataTypesC (p, n)
9313 metaError1 ('expecting a type symbol rather than a
{%1DMd
} {%1DMa
}', n) ;
9315 errorAbort0 ('terminating compilation
')
9321 doArrayNameC - it displays the array declaration (it might be an unbounded).
9324 PROCEDURE doArrayNameC (p: pretty; n: node) ;
9326 doTypeNameC (p, getType (n)) ; setNeedSpace (p) ; outText (p, "*")
9331 doRecordNameC - emit the C/C++ record name <name of n>"_r".
9334 PROCEDURE doRecordNameC (p: pretty; n: node) ;
9338 s := getFQstring (n) ;
9339 s := ConCat (s, Mark (InitString ("_r"))) ;
9346 doPointerNameC - emit the C/C++ pointer type <name of n>*.
9349 PROCEDURE doPointerNameC (p: pretty; n: node) ;
9351 doTypeNameC (p, getType (n)) ; setNeedSpace (p) ; outText (p, "*")
9352 END doPointerNameC ;
9359 PROCEDURE doTypeNameC (p: pretty; n: node) ;
9365 outText (p, "void") ;
9369 outText (p, "char *") ;
9371 ELSIF n = constCharStarN
9373 outText (p, "const char *") ;
9381 ELSIF isEnumeration (n)
9383 print (p, "is enumeration type name required\n")
9387 ELSIF isProcType (n)
9396 doRecordNameC (p, n)
9399 doPointerNameC (p, n)
9400 ELSIF isSubrange (n)
9404 print (p, "is type unknown required\n")
9410 isExternal - returns TRUE if symbol, n, was declared in another module.
9413 PROCEDURE isExternal (n: node) : BOOLEAN ;
9418 RETURN (s # NIL) AND isDef (s) AND
9419 ((isImp (getMainModule ()) AND (s # lookupDef (getSymName (getMainModule ())))) OR
9420 isModule (getMainModule ()))
9425 doOpaqueModifier - adds postfix __opaque providing n uses an opaque type which is
9426 not represented by ( void * ). n is a non type node which might
9427 be using an opaque type. For example a var or param node.
9430 PROCEDURE doOpaqueModifier (p: pretty; n: node) ;
9432 assert (NOT isType (n)) ;
9433 IF isImp (getCurrentModule ()) AND nodeUsesOpaque (n) AND (NOT getNodeOpaqueVoidStar (n))
9435 outText (doP, '__opaque
')
9437 END doOpaqueModifier ;
9444 PROCEDURE doDeclareVarC (n: node) ;
9450 type := getType (n) ;
9451 doTypeC (doP, type, s) ;
9452 doOpaqueModifier (doP, n) ;
9453 setNeedSpace (doP) ;
9454 doFQDNameC (doP, n, FALSE) ;
9460 doVarC - output a variable declaration. Note that we do not generate
9461 a declaration if we are translating the implementation module
9462 and a variable is exported as the variable will be in the .h
9463 file to avoid all -Wodr issues.
9466 PROCEDURE doVarC (n: node) ;
9468 IF isDef (getMainModule ())
9470 print (doP, "EXTERN") ; setNeedSpace (doP) ;
9472 ELSIF (NOT isExported (n)) AND (NOT isLocal (n))
9474 print (doP, "static") ; setNeedSpace (doP) ;
9476 ELSIF getExtendedOpaque ()
9478 (* --fixme-- need to revisit extended opaque. *)
9481 (* different module declared this variable, therefore it is extern. *)
9482 print (doP, "extern") ; setNeedSpace (doP)
9496 PROCEDURE doExternCP (p: pretty) ;
9500 outText (p, 'extern
"C"') ; setNeedSpace (p)
9506 doProcedureCommentText -
9509 PROCEDURE doProcedureCommentText (p: pretty; s: String) ;
9511 (* remove \n from the start of the comment. *)
9512 WHILE (DynamicStrings.Length (s) > 0) AND (DynamicStrings.char (s, 0) = lf) DO
9513 s := DynamicStrings.Slice (s, 1, 0)
9516 END doProcedureCommentText ;
9520 doProcedureComment -
9523 PROCEDURE doProcedureComment (p: pretty; s: String) ;
9527 outText (p, '\n/*\n') ;
9528 doProcedureCommentText (p, s) ;
9529 outText (p, '*/\n\n')
9531 END doProcedureComment ;
9535 doProcedureHeadingC -
9538 PROCEDURE doProcedureHeadingC (n: node; prototype: BOOLEAN) ;
9544 assert (isProcedure (n)) ;
9545 s := getFQstring (n) ;
9546 IF EqualArray (s, 'M2Quads_BuildAssignment
')
9550 s := KillString (s) ;
9552 IF isDef (getMainModule ())
9554 doProcedureComment (doP, getContent (n^.procedureF.defComment)) ;
9555 outText (doP, "EXTERN") ; setNeedSpace (doP)
9556 ELSIF isExported (n)
9558 doProcedureComment (doP, getContent (n^.procedureF.modComment)) ;
9561 doProcedureComment (doP, getContent (n^.procedureF.modComment)) ;
9562 outText (doP, "static") ; setNeedSpace (doP)
9565 doTypeC (doP, n^.procedureF.returnType, q) ;
9567 IF NOT isExported (n)
9569 doTypeNameModifier (doP, n^.procedureF.returnType)
9572 doOpaqueModifier (doP, n) ;
9573 setNeedSpace (doP) ;
9574 doFQDNameC (doP, n, FALSE) ;
9575 setNeedSpace (doP) ;
9576 outText (doP, "(") ;
9577 i := LowIndice (n^.procedureF.parameters) ;
9578 h := HighIndice (n^.procedureF.parameters) ;
9580 p := GetIndice (n^.procedureF.parameters, i) ;
9581 doParameterC (doP, p) ;
9585 print (doP, ",") ; setNeedSpace (doP)
9591 outText (doP, "void")
9594 IF n^.procedureF.noreturn AND prototype AND (NOT getSuppressNoReturn ())
9596 setNeedSpace (doP) ;
9597 outText (doP, "__attribute__ ((noreturn))")
9599 END doProcedureHeadingC ;
9603 checkDeclareUnboundedParamCopyC -
9606 PROCEDURE checkDeclareUnboundedParamCopyC (p: pretty; n: node) : BOOLEAN ;
9615 l := n^.paramF.namelist^.identlistF.names ;
9616 IF isArray (t) AND isUnbounded (t) AND (l#NIL)
9619 c := wlists.noOfItemsInList (l) ;
9622 doTypeNameC (p, t) ;
9624 doNamesC (p, wlists.getItemFromList (l, i)) ;
9626 doNamesC (p, wlists.getItemFromList (l, i)) ;
9627 outText (p, '_high
+1];\n');
9633 END checkDeclareUnboundedParamCopyC ;
9637 checkUnboundedParamCopyC -
9640 PROCEDURE checkUnboundedParamCopyC (p: pretty; n: node) ;
9647 l := n^.paramF.namelist^.identlistF.names ;
9648 IF isArray (t) AND isUnbounded (t) AND (l#NIL)
9650 c := wlists.noOfItemsInList (l) ;
9656 outText (p, 'memcpy (') ;
9657 doNamesC (p, wlists.getItemFromList (l, i)) ;
9660 doNamesC (p, wlists.getItemFromList (l, i)) ;
9661 outText (p, '_
, ') ;
9662 IF (s = charN) OR (s = byteN) OR (s = locN)
9665 doNamesC (p, wlists.getItemFromList (l, i)) ;
9666 outText (p, '_high
+1);\n')
9669 doNamesC (p, wlists.getItemFromList (l, i)) ;
9670 outText (p, '_high
+1)') ;
9672 doMultiplyBySize (p, t) ;
9678 END checkUnboundedParamCopyC ;
9682 doUnboundedParamCopyC -
9685 PROCEDURE doUnboundedParamCopyC (p: pretty; n: node) ;
9691 assert (isProcedure (n)) ;
9692 i := LowIndice (n^.procedureF.parameters) ;
9693 h := HighIndice (n^.procedureF.parameters) ;
9696 q := GetIndice (n^.procedureF.parameters, i) ;
9699 seen := checkDeclareUnboundedParamCopyC (p, q) OR seen
9706 outText (p, "/* make a local copy of each unbounded array. */\n") ;
9707 i := LowIndice (n^.procedureF.parameters) ;
9709 q := GetIndice (n^.procedureF.parameters, i) ;
9712 checkUnboundedParamCopyC (p, q)
9717 END doUnboundedParamCopyC ;
9724 PROCEDURE doPrototypeC (n: node) ;
9726 IF NOT isExported (n)
9728 keyc.enterScope (n) ;
9729 doProcedureHeadingC (n, TRUE) ;
9730 print (doP, ";\n") ;
9737 addTodo - adds, n, to the todo list.
9740 PROCEDURE addTodo (n: node) ;
9743 (NOT alists.isItemInList (globalGroup^.partialQ, n)) AND
9744 (NOT alists.isItemInList (globalGroup^.doneQ, n))
9746 assert (NOT isVarient (n)) ;
9747 assert (NOT isVarientField (n)) ;
9748 assert (NOT isDef (n)) ;
9749 alists.includeItemIntoList (globalGroup^.todoQ, n)
9758 PROCEDURE addVariablesTodo (n: node) ;
9762 IF n^.varF.isParameter OR n^.varF.isVarParameter
9765 addTodo (getType (n))
9770 END addVariablesTodo ;
9777 PROCEDURE addTypesTodo (n: node) ;
9792 PROCEDURE tempName () : String ;
9795 RETURN Sprintf1 (InitString ("_T%d"), tempCount) ;
9800 makeIntermediateType -
9803 PROCEDURE makeIntermediateType (s: String; p: node) : node ;
9808 n := makekey (DynamicStrings.string (s)) ;
9809 enterScope (getScope (p)) ;
9811 p := makeType (makekey (DynamicStrings.string (s))) ;
9813 putTypeInternal (p) ;
9816 END makeIntermediateType ;
9823 PROCEDURE simplifyType (l: alist; VAR p: node) ;
9827 IF (p#NIL) AND (isRecord (p) OR isArray (p) OR isProcType (p)) AND (NOT isUnbounded (p))
9830 p := makeIntermediateType (s, p) ;
9831 s := KillString (s) ;
9842 PROCEDURE simplifyVar (l: alist; n: node) ;
9848 assert (isVar (n)) ;
9850 simplifyType (l, n^.varF.type) ;
9853 (* simplification has occurred, make sure that all other variables of this type
9854 use the new type. *)
9856 assert (isVarDecl (d)) ;
9857 t := wlists.noOfItemsInList (d^.vardeclF.names) ;
9860 v := lookupInScope (n^.varF.scope, wlists.getItemFromList (d^.vardeclF.names, i)) ;
9861 assert (isVar (v)) ;
9862 v^.varF.type := n^.varF.type ;
9873 PROCEDURE simplifyRecord (l: alist; n: node) ;
9878 i := LowIndice (n^.recordF.listOfSons) ;
9879 t := HighIndice (n^.recordF.listOfSons) ;
9881 q := GetIndice (n^.recordF.listOfSons, i) ;
9882 simplifyNode (l, q) ;
9885 END simplifyRecord ;
9892 PROCEDURE simplifyVarient (l: alist; n: node) ;
9897 simplifyNode (l, n^.varientF.tag) ;
9898 i := LowIndice (n^.varientF.listOfSons) ;
9899 t := HighIndice (n^.varientF.listOfSons) ;
9901 q := GetIndice (n^.varientF.listOfSons, i) ;
9902 simplifyNode (l, q) ;
9905 END simplifyVarient ;
9909 simplifyVarientField -
9912 PROCEDURE simplifyVarientField (l: alist; n: node) ;
9917 i := LowIndice (n^.varientfieldF.listOfSons) ;
9918 t := HighIndice (n^.varientfieldF.listOfSons) ;
9920 q := GetIndice (n^.varientfieldF.listOfSons, i) ;
9921 simplifyNode (l, q) ;
9924 END simplifyVarientField ;
9931 PROCEDURE doSimplifyNode (l: alist; n: node) ;
9938 (* no need to simplify a type. *)
9939 simplifyNode (l, getType (n))
9945 simplifyRecord (l, n)
9946 ELSIF isRecordField (n)
9948 simplifyType (l, n^.recordfieldF.type)
9951 simplifyType (l, n^.arrayF.type)
9954 simplifyVarient (l, n)
9955 ELSIF isVarientField (n)
9957 simplifyVarientField (l, n)
9960 simplifyType (l, n^.pointerF.type)
9962 END doSimplifyNode ;
9969 PROCEDURE simplifyNode (l: alist; n: node) ;
9971 IF NOT alists.isItemInList (l, n)
9973 alists.includeItemIntoList (l, n) ;
9974 doSimplifyNode (l, n)
9983 PROCEDURE doSimplify (n: node) ;
9987 l := alists.initList () ;
9988 simplifyNode (l, n) ;
9997 PROCEDURE simplifyTypes (s: scopeT) ;
10000 simplified := TRUE ;
10001 ForeachIndiceInIndexDo (s.types, doSimplify) ;
10002 ForeachIndiceInIndexDo (s.variables, doSimplify)
10004 END simplifyTypes ;
10011 PROCEDURE outDeclsDefC (p: pretty; n: node) ;
10015 s := n^.defF.decls ;
10016 simplifyTypes (s) ;
10017 includeConstType (s) ;
10021 topologicallyOut (doConstC, doTypesC, doVarC,
10023 doNone, doCompletePartialC, doNone) ;
10025 (* try and output types, constants before variables and procedures. *)
10026 includeDefVarProcedure (n) ;
10028 topologicallyOut (doConstC, doTypesC, doVarC,
10030 doNone, doCompletePartialC, doNone) ;
10032 ForeachIndiceInIndexDo (s.procedures, doPrototypeC)
10040 PROCEDURE includeConstType (s: scopeT) ;
10042 ForeachIndiceInIndexDo (s.constants, addTodo) ;
10043 ForeachIndiceInIndexDo (s.types, addTypesTodo)
10044 END includeConstType ;
10048 includeVarProcedure -
10051 PROCEDURE includeVarProcedure (s: scopeT) ;
10053 ForeachIndiceInIndexDo (s.procedures, addTodo) ;
10054 ForeachIndiceInIndexDo (s.variables, addVariablesTodo)
10055 END includeVarProcedure ;
10062 PROCEDURE includeVar (s: scopeT) ;
10064 ForeachIndiceInIndexDo (s.variables, addTodo)
10072 PROCEDURE includeExternals (n: node) ;
10076 l := alists.initList () ;
10077 visitNode (l, n, addExported) ;
10078 alists.killList (l)
10079 END includeExternals ;
10083 checkSystemInclude -
10086 PROCEDURE checkSystemInclude (n: node) ;
10089 END checkSystemInclude ;
10096 PROCEDURE addExported (n: node) ;
10100 s := getScope (n) ;
10101 IF (s # NIL) AND isDef (s) AND (s # defModule)
10103 IF isType (n) OR isVar (n) OR isConst (n)
10112 addExternal - only adds, n, if this symbol is external to the
10113 implementation module and is not a hidden type.
10116 PROCEDURE addExternal (n: node) ;
10118 IF (getScope (n) = defModule) AND isType (n) AND
10119 isTypeHidden (n) AND (NOT getExtendedOpaque ())
10122 ELSIF NOT isDef (n)
10130 includeDefConstType -
10133 PROCEDURE includeDefConstType (n: node) ;
10139 defModule := lookupDef (getSymName (n)) ;
10142 simplifyTypes (defModule^.defF.decls) ;
10143 includeConstType (defModule^.defF.decls) ;
10144 foreachNodeDo (defModule^.defF.decls.symbols, addExternal)
10147 END includeDefConstType ;
10151 runIncludeDefConstType -
10154 PROCEDURE runIncludeDefConstType (n: node) ;
10160 simplifyTypes (n^.defF.decls) ;
10161 includeConstType (n^.defF.decls) ;
10162 foreachNodeDo (n^.defF.decls.symbols, addExternal)
10164 END runIncludeDefConstType ;
10168 joinProcedures - copies procedures from definition module,
10169 d, into implementation module, i.
10172 PROCEDURE joinProcedures (i, d: node) ;
10176 assert (isDef (d)) ;
10177 assert (isImp (i)) ;
10179 h := HighIndice (d^.defF.decls.procedures) ;
10181 IncludeIndiceIntoIndex (i^.impF.decls.procedures,
10182 GetIndice (d^.defF.decls.procedures, j)) ;
10185 END joinProcedures ;
10189 includeDefVarProcedure -
10192 PROCEDURE includeDefVarProcedure (n: node) ;
10198 defModule := lookupDef (getSymName (n)) ;
10202 includeVar (defModule^.defF.decls) ;
10203 simplifyTypes (defModule^.defF.decls) ;
10205 joinProcedures (n, defModule)
10209 includeVar (n^.defF.decls) ;
10210 simplifyTypes (n^.defF.decls)
10212 END includeDefVarProcedure ;
10219 PROCEDURE foreachModuleDo (n: node; p: performOperation) ;
10221 foreachDefModuleDo (p) ;
10222 foreachModModuleDo (p)
10223 END foreachModuleDo ;
10230 PROCEDURE outDeclsImpC (p: pretty; s: scopeT) ;
10232 simplifyTypes (s) ;
10233 includeConstType (s) ;
10237 topologicallyOut (doConstC, doTypesC, doVarC,
10239 doNone, doCompletePartialC, doNone) ;
10241 (* try and output types, constants before variables and procedures. *)
10242 includeVarProcedure (s) ;
10244 topologicallyOut (doConstC, doTypesC, doVarC,
10246 doNone, doCompletePartialC, doNone) ;
10252 doStatementSequenceC -
10255 PROCEDURE doStatementSequenceC (p: pretty; s: node) ;
10259 assert (isStatementSequence (s)) ;
10260 h := HighIndice (s^.stmtF.statements) ;
10263 doStatementsC (p, GetIndice (s^.stmtF.statements, i)) ;
10266 END doStatementSequenceC ;
10270 isStatementSequenceEmpty -
10273 PROCEDURE isStatementSequenceEmpty (s: node) : BOOLEAN ;
10275 assert (isStatementSequence (s)) ;
10276 RETURN HighIndice (s^.stmtF.statements) = 0
10277 END isStatementSequenceEmpty ;
10281 isSingleStatement - returns TRUE if the statement sequence, s, has
10282 only one statement.
10285 PROCEDURE isSingleStatement (s: node) : BOOLEAN ;
10289 assert (isStatementSequence (s)) ;
10290 h := HighIndice (s^.stmtF.statements) ;
10291 IF (h = 0) OR (h > 1)
10295 s := GetIndice (s^.stmtF.statements, 1) ;
10296 RETURN (NOT isStatementSequence (s)) OR isSingleStatement (s)
10297 END isSingleStatement ;
10304 PROCEDURE doCommentC (p: pretty; s: node) ;
10310 assert (isComment (s)) ;
10311 IF NOT isProcedureComment (s^.commentF.content)
10313 IF isAfterComment (s^.commentF.content)
10316 outText (p, " /* ")
10320 c := getContent (s^.commentF.content) ;
10321 c := RemoveWhitePrefix (RemoveWhitePostfix (c)) ;
10323 outText (p, " */\n")
10330 doAfterCommentC - emit an after comment, c, or a newline if, c, is empty.
10333 PROCEDURE doAfterCommentC (p: pretty; c: node) ;
10341 END doAfterCommentC ;
10345 doReturnC - issue a return statement and also place in an after comment if one exists.
10348 PROCEDURE doReturnC (p: pretty; s: node) ;
10352 assert (isReturn (s)) ;
10353 doCommentC (p, s^.returnF.returnComment.body) ;
10354 outText (p, "return") ;
10355 IF (s^.returnF.scope#NIL) AND (s^.returnF.exp#NIL)
10358 IF (NOT isProcedure (s^.returnF.scope)) OR (getType (s^.returnF.scope)=NIL)
10360 metaError1 ('{%1DMad
} has no return type
', s^.returnF.scope) ;
10362 IF isProcedure (s^.returnF.scope) AND nodeUsesOpaque (s^.returnF.scope)
10364 forceCastOpaque (p, s^.returnF.scope, s^.returnF.exp,
10365 getNodeOpaqueVoidStar (s^.returnF.scope))
10367 doExprCastC (p, s^.returnF.exp, getType (s^.returnF.scope))
10372 doAfterCommentC (p, s^.returnF.returnComment.after)
10377 isZtypeEquivalent -
10380 PROCEDURE isZtypeEquivalent (type: node) : BOOLEAN ;
10390 ztype : RETURN TRUE
10395 END isZtypeEquivalent ;
10399 isEquivalentType - returns TRUE if type1 and type2 are equivalent.
10402 PROCEDURE isEquivalentType (type1, type2: node) : BOOLEAN ;
10404 type1 := skipType (type1) ;
10405 type2 := skipType (type2) ;
10406 RETURN ((type1 = type2) OR
10407 (isZtypeEquivalent (type1) AND isZtypeEquivalent (type2)))
10408 END isEquivalentType ;
10412 doExprCastC - build a cast if necessary.
10415 PROCEDURE doExprCastC (p: pretty; e, type: node) ;
10419 stype := skipType (type) ;
10420 IF (NOT isEquivalentType (type, getExprType (e))) AND
10421 (NOT ((e^.kind = nil) AND (isPointer (stype) OR (stype^.kind = address))))
10425 (* potentially a cast is required. *)
10426 IF isPointer (type) OR (type = addressN)
10428 outText (p, 'static_cast
<') ;
10429 doTypeNameC (p, type) ;
10431 outText (p, '> (') ;
10436 outText (p, 'static_cast
<') ;
10437 IF isProcType (skipType (type))
10439 doTypeNameC (p, type) ;
10442 doTypeNameC (p, type)
10445 outText (p, '> (') ;
10457 requiresUnpackProc - returns TRUE if either the expr is a procedure or the proctypes differ.
10460 PROCEDURE requiresUnpackProc (s: node) : BOOLEAN ;
10462 assert (isAssignment (s)) ;
10463 RETURN isProcedure (s^.assignmentF.expr) OR
10464 (skipType (getType (s^.assignmentF.des)) # skipType (getType (s^.assignmentF.expr)))
10465 END requiresUnpackProc ;
10472 PROCEDURE forceCastOpaque (p: pretty; des, expr: node; toVoidStar: BOOLEAN) ;
10474 IF nodeUsesOpaque (expr)
10476 flushOpaque (p, expr, getNodeOpaqueVoidStar (des))
10478 forceReintCastOpaque (p, des, expr, toVoidStar)
10480 END forceCastOpaque ;
10484 forceReintCastOpaque -
10487 PROCEDURE forceReintCastOpaque (p: pretty; des, expr: node; toVoidStar: BOOLEAN) ;
10491 type := getType (des) ;
10494 (* next is true cast to void * opaque type. *)
10495 outText (p, 'static_cast
<') ;
10496 doTypeNameC (p, type) ;
10498 outText (p, '> (') ;
10499 doExprC (p, expr) ;
10502 (* next is false cast to __opaque opaque type. *)
10503 outText (p, 'static_cast
<') ;
10504 doTypeNameC (p, type) ;
10505 outText (p, '__opaque
') ;
10507 outText (p, '> (') ;
10508 doExprC (p, expr) ;
10511 END forceReintCastOpaque ;
10515 doUnConstCastUnbounded - if node n type is an unbounded array then
10516 use const_cast to remove the const parameter
10517 to allow the unbounded array to be modified.
10520 PROCEDURE doUnConstCastUnbounded (p: pretty; n: node) ;
10526 IF isVar (n^.arrayrefF.array)
10528 v := n^.arrayrefF.array ;
10529 IF (v^.varF.isParameter OR v^.varF.isVarParameter) AND
10530 isUnbounded (getType (v))
10532 type := getType (v) ;
10533 outText (p, " /* const_cast<") ;
10534 doTypeNameC (p, type) ;
10535 outText (p, "> is needed */ ") ;
10539 END doUnConstCastUnbounded ;
10546 PROCEDURE doAssignmentC (p: pretty; s: node) ;
10548 assert (isAssignment (s)) ;
10549 doCommentC (p, s^.assignmentF.assignComment.body) ;
10552 outText (p, " /* des: */ ") ;
10553 dumpOpaqueState (s^.assignmentF.des) ;
10554 outText (p, " /* expr: */ ") ;
10555 dumpOpaqueState (s^.assignmentF.expr)
10557 s^.assignmentF.des := doExprCup (p, s^.assignmentF.des,
10558 requiresUnpackProc (s), TRUE) ;
10561 outText (p, "\n /* after doExprCup des: */ ") ;
10562 dumpOpaqueState (s^.assignmentF.des) ;
10568 IF nodeUsesOpaque (s^.assignmentF.des)
10570 forceCastOpaque (p, s^.assignmentF.des, s^.assignmentF.expr,
10571 getNodeOpaqueVoidStar (s^.assignmentF.des))
10575 outText (p, " /* no opaque des seen */ ")
10577 doExprCastC (p, s^.assignmentF.expr, getType (s^.assignmentF.des))
10580 doAfterCommentC (p, s^.assignmentF.assignComment.after)
10581 END doAssignmentC ;
10585 containsStatement -
10588 PROCEDURE containsStatement (s: node) : BOOLEAN ;
10590 RETURN (s # NIL) AND isStatementSequence (s) AND (NOT isStatementSequenceEmpty (s))
10591 END containsStatement ;
10598 PROCEDURE doCompoundStmt (p: pretty; s: node) ;
10600 IF (s = NIL) OR (isStatementSequence (s) AND isStatementSequenceEmpty (s))
10602 p := pushPretty (p) ;
10603 setindent (p, getindent (p) + indentationC) ;
10604 outText (p, "{} /* empty. */\n") ;
10606 ELSIF isStatementSequence (s) AND isSingleStatement (s) AND (NOT forceCompoundStatement)
10608 p := pushPretty (p) ;
10609 setindent (p, getindent (p) + indentationC) ;
10610 doStatementSequenceC (p, s) ;
10613 p := pushPretty (p) ;
10614 setindent (p, getindent (p) + indentationC) ;
10615 outText (p, "{\n") ;
10616 p := pushPretty (p) ;
10617 setindent (p, getindent (p) + indentationC) ;
10618 doStatementSequenceC (p, s) ;
10619 p := popPretty (p) ;
10620 outText (p, "}\n") ;
10623 END doCompoundStmt ;
10630 PROCEDURE doElsifC (p: pretty; s: node) ;
10632 assert (isElsif (s)) ;
10633 outText (p, "else if") ;
10636 doExprC (p, s^.elsifF.expr) ;
10637 outText (p, ")\n") ;
10638 assert ((s^.elsifF.else = NIL) OR (s^.elsifF.elsif = NIL)) ;
10639 IF forceCompoundStatement OR
10640 (hasIfAndNoElse (s^.elsifF.then) AND
10641 ((s^.elsifF.else # NIL) OR (s^.elsifF.elsif # NIL)))
10643 (* avoid dangling else. *)
10644 p := pushPretty (p) ;
10645 setindent (p, getindent (p) + indentationC) ;
10646 outText (p, "{\n") ;
10647 p := pushPretty (p) ;
10648 setindent (p, getindent (p) + indentationC) ;
10649 outText (p, "/* avoid dangling else. */\n") ;
10650 doStatementSequenceC (p, s^.elsifF.then) ;
10651 p := popPretty (p) ;
10652 outText (p, "}\n") ;
10655 doCompoundStmt (p, s^.elsifF.then)
10657 IF containsStatement (s^.elsifF.else)
10659 outText (p, "else\n") ;
10660 IF forceCompoundStatement
10662 (* avoid dangling else. *)
10663 p := pushPretty (p) ;
10664 setindent (p, getindent (p) + indentationC) ;
10665 outText (p, "{\n") ;
10666 p := pushPretty (p) ;
10667 setindent (p, getindent (p) + indentationC) ;
10668 outText (p, "/* avoid dangling else. */\n") ;
10669 doStatementSequenceC (p, s^.elsifF.else) ;
10670 p := popPretty (p) ;
10671 outText (p, "}\n") ;
10674 doCompoundStmt (p, s^.elsifF.else)
10676 ELSIF (s^.elsifF.elsif#NIL) AND isElsif (s^.elsifF.elsif)
10678 doElsifC (p, s^.elsifF.elsif)
10687 PROCEDURE noIfElse (n: node) : BOOLEAN ;
10689 RETURN (n # NIL) AND isIf (n) AND (n^.ifF.else = NIL) AND (n^.ifF.elsif = NIL)
10694 noIfElseChained - returns TRUE if, n, is an IF statement which
10695 has no associated ELSE statement. An IF with an
10696 ELSIF is also checked for no ELSE and will result
10697 in a return value of TRUE.
10700 PROCEDURE noIfElseChained (n: node) : BOOLEAN ;
10708 IF n^.ifF.else # NIL
10710 (* we do have an else, continue to check this statement. *)
10711 RETURN hasIfAndNoElse (n^.ifF.else)
10712 ELSIF n^.ifF.elsif = NIL
10714 (* neither else or elsif. *)
10717 (* test elsif for lack of else. *)
10718 e := n^.ifF.elsif ;
10719 assert (isElsif (e)) ;
10720 RETURN noIfElseChained (e)
10724 IF n^.elsifF.else # NIL
10726 (* we do have an else, continue to check this statement. *)
10727 RETURN hasIfAndNoElse (n^.elsifF.else)
10728 ELSIF n^.elsifF.elsif = NIL
10730 (* neither else or elsif. *)
10733 (* test elsif for lack of else. *)
10734 e := n^.elsifF.elsif ;
10735 assert (isElsif (e)) ;
10736 RETURN noIfElseChained (e)
10741 END noIfElseChained ;
10748 PROCEDURE hasIfElse (n: node) : BOOLEAN ;
10752 IF isStatementSequence (n)
10754 IF isStatementSequenceEmpty (n)
10757 ELSIF isSingleStatement (n)
10759 n := GetIndice (n^.stmtF.statements, 1) ;
10760 RETURN isIfElse (n)
10772 PROCEDURE isIfElse (n: node) : BOOLEAN ;
10774 RETURN (n # NIL) AND isIf (n) AND ((n^.ifF.else # NIL) OR (n^.ifF.elsif # NIL))
10779 hasIfAndNoElse - returns TRUE if statement, n, is a single statement
10780 which is an IF and it has no else statement.
10783 PROCEDURE hasIfAndNoElse (n: node) : BOOLEAN ;
10787 IF isStatementSequence (n)
10789 IF isStatementSequenceEmpty (n)
10792 ELSIF isSingleStatement (n)
10794 n := GetIndice (n^.stmtF.statements, 1) ;
10795 RETURN hasIfAndNoElse (n)
10797 n := GetIndice (n^.stmtF.statements, HighIndice (n^.stmtF.statements)) ;
10798 RETURN hasIfAndNoElse (n)
10800 ELSIF isElsif (n) OR isIf (n)
10802 RETURN noIfElseChained (n)
10806 END hasIfAndNoElse ;
10810 doIfC - issue an if statement and also place in an after comment if one exists.
10811 The if statement might contain an else or elsif which are also handled.
10814 PROCEDURE doIfC (p: pretty; s: node) ;
10816 assert (isIf (s)) ;
10817 doCommentC (p, s^.ifF.ifComment.body) ;
10818 outText (p, "if") ;
10821 doExprC (p, s^.ifF.expr) ;
10823 doAfterCommentC (p, s^.ifF.ifComment.after) ;
10824 IF hasIfAndNoElse (s^.ifF.then) AND
10825 ((s^.ifF.else # NIL) OR (s^.ifF.elsif # NIL))
10827 (* avoid dangling else. *)
10828 p := pushPretty (p) ;
10829 setindent (p, getindent (p) + indentationC) ;
10830 outText (p, "{\n") ;
10831 p := pushPretty (p) ;
10832 setindent (p, getindent (p) + indentationC) ;
10833 outText (p, "/* avoid dangling else. */\n") ;
10834 doStatementSequenceC (p, s^.ifF.then) ;
10835 p := popPretty (p) ;
10836 outText (p, "}\n") ;
10838 ELSIF noIfElse (s) AND hasIfElse (s^.ifF.then)
10840 (* gcc does not like legal non dangling else, as it is poor style.
10841 So we will avoid getting a warning. *)
10842 p := pushPretty (p) ;
10843 setindent (p, getindent (p) + indentationC) ;
10844 outText (p, "{\n") ;
10845 p := pushPretty (p) ;
10846 setindent (p, getindent (p) + indentationC) ;
10847 outText (p, "/* avoid gcc warning by using compound statement even if not strictly necessary. */\n") ;
10848 doStatementSequenceC (p, s^.ifF.then) ;
10849 p := popPretty (p) ;
10850 outText (p, "}\n") ;
10853 doCompoundStmt (p, s^.ifF.then)
10855 assert ((s^.ifF.else = NIL) OR (s^.ifF.elsif = NIL)) ;
10856 IF containsStatement (s^.ifF.else)
10858 doCommentC (p, s^.ifF.elseComment.body) ;
10859 outText (p, "else") ;
10860 doAfterCommentC (p, s^.ifF.elseComment.after) ;
10861 doCompoundStmt (p, s^.ifF.else)
10862 ELSIF (s^.ifF.elsif#NIL) AND isElsif (s^.ifF.elsif)
10864 doCommentC (p, s^.ifF.elseComment.body) ;
10865 doCommentC (p, s^.ifF.elseComment.after) ;
10866 doElsifC (p, s^.ifF.elsif)
10868 doCommentC (p, s^.ifF.endComment.after) ;
10869 doCommentC (p, s^.ifF.endComment.body)
10877 PROCEDURE doForIncCP (p: pretty; s: node) ;
10881 assert (isFor (s)) ;
10882 t := skipType (getType (s^.forF.des)) ;
10883 IF isEnumeration (t)
10885 IF s^.forF.increment = NIL
10887 doExprC (p, s^.forF.des) ;
10888 outText (p, "= static_cast<") ;
10889 doTypeNameC (p, getType (s^.forF.des)) ;
10891 outText (p, ">(static_cast<int>(") ;
10892 doExprC (p, s^.forF.des) ;
10893 outText (p, "+1))")
10895 doExprC (p, s^.forF.des) ;
10896 outText (p, "= static_cast<") ;
10897 doTypeNameC (p, getType (s^.forF.des)) ;
10899 outText (p, ">(static_cast<int>(") ;
10900 doExprC (p, s^.forF.des) ;
10902 doExprC (p, s^.forF.increment) ;
10915 PROCEDURE doForIncC (p: pretty; s: node) ;
10917 IF s^.forF.increment = NIL
10919 doExprC (p, s^.forF.des) ;
10922 doExprC (p, s^.forF.des) ;
10924 doExprC (p, s^.forF.des) ;
10926 doExprC (p, s^.forF.increment)
10935 PROCEDURE doForInc (p: pretty; s: node) ;
10950 PROCEDURE doForC (p: pretty; s: node) ;
10952 assert (isFor (s)) ;
10953 outText (p, "for (") ;
10954 doExprC (p, s^.forF.des) ;
10956 doExprC (p, s^.forF.start) ;
10959 doExprC (p, s^.forF.des) ;
10960 outText (p, "<=") ;
10961 doExprC (p, s^.forF.end) ;
10965 outText (p, ")\n") ;
10966 doCompoundStmt (p, s^.forF.statements)
10974 PROCEDURE doRepeatC (p: pretty; s: node) ;
10976 assert (isRepeat (s)) ;
10977 doCommentC (p, s^.repeatF.repeatComment.body) ;
10978 outText (p, "do {") ;
10979 doAfterCommentC (p, s^.repeatF.repeatComment.after) ;
10980 p := pushPretty (p) ;
10981 setindent (p, getindent (p) + indentationC) ;
10982 doStatementSequenceC (p, s^.repeatF.statements) ;
10983 doCommentC (p, s^.repeatF.untilComment.body) ;
10984 p := popPretty (p) ;
10985 outText (p, "} while (! (") ;
10986 doExprC (p, s^.repeatF.expr) ;
10987 outText (p, "));") ;
10988 doAfterCommentC (p, s^.repeatF.untilComment.after)
10996 PROCEDURE doWhileC (p: pretty; s: node) ;
10998 assert (isWhile (s)) ;
10999 doCommentC (p, s^.whileF.doComment.body) ;
11000 outText (p, "while (") ;
11001 doExprC (p, s^.whileF.expr) ;
11003 doAfterCommentC (p, s^.whileF.doComment.after) ;
11004 doCompoundStmt (p, s^.whileF.statements) ;
11005 doCommentC (p, s^.whileF.endComment.body) ;
11006 doCommentC (p, s^.whileF.endComment.after)
11014 PROCEDURE doFuncHighC (p: pretty; a: node) ;
11018 IF isLiteral (a) AND (getType (a) = charN)
11023 outCard (p, a^.stringF.length-2)
11024 ELSIF isConst (a) AND isString (a^.constF.value)
11026 doFuncHighC (p, a^.constF.value)
11027 ELSIF isUnbounded (getType (a))
11030 outTextN (p, getSymName (a)) ;
11031 outText (p, '_high
')
11032 ELSIF isArray (skipType (getType (a)))
11034 n := skipType (getType (a)) ;
11035 s := n^.arrayF.subr ;
11036 IF isZero (getMin (s))
11038 doExprC (p, getMax (s))
11041 doExprC (p, getMax (s)) ;
11042 doSubtractC (p, getMin (s)) ;
11046 (* output sizeof (a) in bytes for the high. *)
11047 outText (p, '(sizeof
') ;
11051 outText (p, ')-1)')
11060 PROCEDURE doMultiplyBySize (p: pretty; a: node) ;
11062 IF (a # charN) AND (a # byteN) AND (a # locN)
11065 outText (p, '* sizeof (') ;
11066 doTypeNameC (p, a) ;
11070 END doMultiplyBySize ;
11077 PROCEDURE doTotype (p: pretty; a, t: node) ;
11079 IF (NOT isString (a)) AND (NOT isLiteral (a))
11083 IF (a^.varF.isParameter OR a^.varF.isVarParameter) AND
11084 isUnbounded (getType (a)) AND (skipType (getType (getType (a))) = skipType (getType (t)))
11086 (* do not multiply by size as the existing high value is correct. *)
11092 doMultiplyBySize (p, skipType (getType (a)))
11099 outText (p, '/ sizeof (') ;
11100 doTypeNameC (p, wordN) ;
11111 PROCEDURE doFuncUnbounded (p: pretty; actual, formalParam, formal, func: node) ;
11116 assert (isUnbounded (formal)) ;
11118 IF (lang = ansiCP) AND isParam (formalParam)
11120 outText (p, "const") ;
11123 doTypeC (p, getType (formal), formal) ;
11125 outText (p, '*)
') ;
11127 IF isLiteral (actual) AND (getType (actual) = charN)
11129 outText (p, '"\0') ;
11130 s := InitStringCharStar (keyToCharStar (actual^.literalF.name)) ;
11131 s := DynamicStrings.Slice (DynamicStrings.Mark (s), 0, -1) ;
11134 s := KillString (s)
11135 ELSIF isString (actual)
11137 outCstring (p, actual, TRUE)
11138 ELSIF isConst (actual)
11140 actual := resolveString (actual) ;
11141 assert (isString (actual)) ;
11142 outCstring (p, actual, TRUE)
11143 ELSIF isFuncCall (actual)
11145 IF getExprType (actual) = NIL
11147 metaError3 ('there is no return type to the procedure function
{%3ad
} which is being passed as the parameter
{%1ad
} to
{%2ad
}', formal, func, actual)
11150 doExprC (p, actual)
11152 ELSIF isUnbounded (getType (actual))
11154 doFQNameC (p, actual)
11155 (* doExprC (p, actual). *)
11158 doExprC (p, actual) ;
11159 IF isArray (skipType (getType (actual)))
11161 outText (p, '.array
[0]')
11164 IF NOT (enableDefForCStrings AND isDefForC (getScope (func)))
11168 doFuncHighC (p, actual) ;
11169 doTotype (p, actual, formal)
11171 END doFuncUnbounded ;
11175 doProcedureParamC -
11178 PROCEDURE doProcedureParamC (p: pretty; actual, formal: node) ;
11183 doFQNameC (p, getType (formal)) ;
11184 outText (p, "_C") ;
11187 doExprC (p, actual)
11190 doTypeNameC (p, getType (formal)) ;
11195 doFQNameC (p, getType (formal)) ;
11196 outText (p, '_t
)') ;
11198 doExprC (p, actual) ;
11201 END doProcedureParamC ;
11208 PROCEDURE doAdrExprC (p: pretty; n: node) ;
11212 (* No point in issuing & ( * n ). *)
11213 doExprC (p, n^.unaryF.arg)
11214 ELSIF isVar (n) AND n^.varF.isVarParameter
11216 (* No point in issuing & ( * n ). *)
11229 PROCEDURE typePair (a, b, x, y: node) : BOOLEAN ;
11231 RETURN ((a = x) AND (b = y)) OR ((a = y) AND (b = x))
11236 needsCast - return TRUE if the actual type parameter needs to be cast to
11240 PROCEDURE needsCast (at, ft: node) : BOOLEAN ;
11242 at := skipType (at) ;
11243 ft := skipType (ft) ;
11244 IF (at = nilN) OR (at^.kind = nil) OR
11246 typePair (at, ft, cardinalN, wordN) OR
11247 typePair (at, ft, cardinalN, ztypeN) OR
11248 typePair (at, ft, integerN, ztypeN) OR
11249 typePair (at, ft, longcardN, ztypeN) OR
11250 typePair (at, ft, shortcardN, ztypeN) OR
11251 typePair (at, ft, longintN, ztypeN) OR
11252 typePair (at, ft, shortintN, ztypeN) OR
11253 typePair (at, ft, realN, rtypeN) OR
11254 typePair (at, ft, longrealN, rtypeN) OR
11255 typePair (at, ft, shortrealN, rtypeN)
11265 castDestType - emit the destination type ft
11268 PROCEDURE castDestType (p: pretty; formal, ft: node) ;
11270 doTypeNameC (p, ft) ;
11271 IF isVarParam (formal)
11282 PROCEDURE identifyPointer (type: node) : node ;
11284 IF isPointer (type)
11286 IF skipType (getType (type)) = charN
11289 ELSIF (skipType (getType (type)) = byteN) OR
11290 (skipType (getType (type)) = locN)
11296 END identifyPointer ;
11300 castPointer - provides a six way cast between ADDRESS (ie void * ),
11301 char * and const char *.
11304 PROCEDURE castPointer (p: pretty; actual, formal, at, ft: node) : CARDINAL ;
11307 parenth : CARDINAL ;
11312 sat := identifyPointer (skipType (at)) ;
11313 sft := identifyPointer (skipType (ft)) ;
11318 outText (p, 'reinterpret_cast
<') ;
11319 castDestType (p, formal, ft) ;
11321 ELSIF sft = constCharStarN
11323 outText (p, 'const_cast
<') ;
11324 castDestType (p, formal, ft) ;
11325 outText (p, '> (static_cast
<') ;
11326 doTypeNameC (p, charStarN) ;
11330 outText (p, 'reinterpret_cast
<') ;
11331 castDestType (p, formal, ft) ;
11334 ELSIF sat = charStarN
11338 outText (p, 'reinterpret_cast
<') ;
11339 castDestType (p, formal, ft) ;
11341 ELSIF sft = constCharStarN
11343 outText (p, 'const_cast
<') ;
11344 castDestType (p, formal, ft) ;
11347 outText (p, 'reinterpret_cast
<') ;
11348 castDestType (p, formal, ft) ;
11351 ELSIF sat = constCharStarN
11355 outText (p, 'static_cast
<') ;
11356 castDestType (p, formal, ft) ;
11357 outText (p, '> (const_cast
<') ;
11358 doTypeNameC (p, charStarN) ;
11361 ELSIF sft = charStarN
11363 outText (p, 'const_cast
<') ;
11364 castDestType (p, formal, ft) ;
11367 outText (p, 'reinterpret_cast
<') ;
11368 castDestType (p, formal, ft) ;
11372 outText (p, 'reinterpret_cast
<') ;
11373 castDestType (p, formal, ft) ;
11385 checkSystemCast - checks to see if we are passing to/from
11386 a system generic type (WORD, BYTE, ADDRESS)
11387 and if so emit a cast. It returns the number of
11391 PROCEDURE checkSystemCast (p: pretty; actual, formal: node) : CARDINAL ;
11395 at := getExprType (actual) ;
11396 ft := getType (formal) ;
11397 IF needsCast (at, ft)
11401 IF isString (actual) AND isCDataType (skipType (ft))
11403 (* Nothing to do. *)
11405 ELSIF isString (actual) AND (skipType (ft) = addressN)
11407 outText (p, "const_cast<void*> (static_cast<const void*> (") ;
11409 ELSIF isPointer (skipType (ft)) OR (skipType (ft) = addressN) OR
11410 isCDataType (skipType (ft))
11414 IF isVarParam (formal)
11416 metaError1 ('NIL is being passed to a
VAR parameter
{%1DMad
}', formal)
11418 (* NULL is compatible with pointers/address. *)
11421 RETURN castPointer (p, actual, formal, at, ft)
11424 outText (p, 'static_cast
<') ;
11425 doTypeNameC (p, ft) ;
11426 IF isVarParam (formal)
11436 doTypeNameC (p, ft) ;
11437 IF isVarParam (formal)
11447 END checkSystemCast ;
11454 PROCEDURE emitN (p: pretty; a: ARRAY OF CHAR; n: CARDINAL) ;
11464 isForC - return true if node n is a varparam, param or procedure
11465 which was declared inside a definition module for "C".
11468 PROCEDURE isForC (n: node) : BOOLEAN ;
11472 RETURN n^.varparamF.isForC
11475 RETURN n^.paramF.isForC
11476 ELSIF isProcedure (n)
11478 RETURN n^.procedureF.isForC
11485 isDefForCNode - return TRUE if node n was declared inside a definition module for "C".
11488 PROCEDURE isDefForCNode (n: node) : BOOLEAN ;
11492 WHILE (n # NIL) AND (NOT (isImp (n) OR isDef (n) OR isModule (n))) DO
11495 IF (n # NIL) AND isImp (n)
11497 name := getSymName (n) ;
11498 n := lookupDef (name) ;
11500 RETURN (n # NIL) AND isDef (n) AND isDefForC (n)
11501 END isDefForCNode ;
11505 doFuncVarParam - detect whether the formal uses an opaque and ensure that the address of
11506 the actual parameter is cast to the formal type.
11509 PROCEDURE doFuncVarParam (p: pretty; actual, formal: node) ;
11513 IF nodeUsesOpaque (formal) AND
11514 getNodeOpaqueFlushNecessary (actual, getNodeOpaqueVoidStar (formal))
11516 type := getType (formal) ;
11517 outText (p, 'reinterpret_cast
<') ;
11518 IF getNodeOpaqueVoidStar (formal)
11520 doTypeNameC (p, type) ;
11522 outText (p, '*> (&') ;
11523 doExprC (p, actual) ;
11525 actual := makeOpaqueCast (actual, TRUE)
11527 doTypeNameC (p, type) ;
11529 outText (p, '__opaque
*> (&') ;
11530 doExprC (p, actual) ;
11532 actual := makeOpaqueCast (actual, FALSE)
11535 doAdrExprC (p, actual)
11537 END doFuncVarParam ;
11544 PROCEDURE doFuncParamC (p: pretty; actual, formal, func: node) ;
11551 doExprC (p, actual)
11553 ft := skipType (getType (formal)) ;
11554 IF isUnbounded (ft)
11556 doFuncUnbounded (p, actual, formal, ft, func)
11558 IF isAProcType (ft) AND isProcedure (actual)
11560 IF isVarParam (formal)
11562 metaError1 ('{%1MDad
} cannot be passed as a
VAR parameter
', actual)
11564 doProcedureParamC (p, actual, formal)
11566 ELSIF (getType (actual) # NIL) AND isProcType (skipType (getType (actual))) AND isAProcType (ft) AND isForC (formal)
11568 IF isVarParam (formal)
11570 metaError2 ('{%1MDad
} cannot be passed as a
VAR parameter to the definition for C module as the parameter requires a cast to the formal type
{%2MDtad
}',
11574 doFQNameC (p, getType (formal)) ;
11575 outText (p, "_C") ;
11578 doExprC (p, actual) ;
11579 outText (p, ".proc")
11581 ELSIF (getType (actual) # NIL) AND isProcType (skipType (getType (actual))) AND (getType (actual) # getType (formal))
11583 IF isVarParam (formal)
11585 metaError2 ('{%1MDad
} cannot be passed as a
VAR parameter as the parameter requires a cast to the formal type
{%2MDtad
}',
11588 doCastC (p, getType (formal), actual)
11591 IF isVarParam (formal)
11593 lbr := checkSystemCast (p, actual, formal) ;
11594 doFuncVarParam (p, actual, formal) ;
11595 emitN (p, ")", lbr)
11597 IF nodeUsesOpaque (formal)
11599 forceCastOpaque (p, formal, actual,
11600 getNodeOpaqueVoidStar (formal))
11602 lbr := checkSystemCast (p, actual, formal) ;
11603 doExprC (p, actual) ;
11604 emitN (p, ")", lbr)
11614 getNthParamType - return the type of parameter, i, in list, l.
11615 If the parameter is a vararg NIL is returned.
11618 PROCEDURE getNthParamType (l: Index; i: CARDINAL) : node ;
11622 p := getNthParam (l, i) ;
11628 END getNthParamType ;
11632 getNthParam - return the parameter, i, in list, l.
11633 If the parameter is a vararg NIL is returned.
11636 PROCEDURE getNthParam (l: Index; i: CARDINAL) : node ;
11639 j, k, h: CARDINAL ;
11643 j := LowIndice (l) ;
11644 h := HighIndice (l) ;
11646 p := GetIndice (l, j) ;
11649 k := identListLen (p^.paramF.namelist)
11650 ELSIF isVarParam (p)
11652 k := identListLen (p^.varparamF.namelist)
11654 assert (isVarargs (p)) ;
11674 PROCEDURE doFuncArgsC (p: pretty; s: node; l: Index; needParen: BOOLEAN) ;
11676 actual, formal: node ;
11683 IF s^.funccallF.args # NIL
11686 n := expListLen (s^.funccallF.args) ;
11688 actual := getExpList (s^.funccallF.args, i) ;
11689 formal := getNthParam (l, i) ;
11690 doFuncParamC (p, actual, formal, s^.funccallF.function) ;
11711 PROCEDURE doProcTypeArgsC (p: pretty; s: node; args: Index; needParen: BOOLEAN) ;
11720 IF s^.funccallF.args # NIL
11723 n := expListLen (s^.funccallF.args) ;
11725 a := getExpList (s^.funccallF.args, i) ;
11726 b := GetIndice (args, i) ;
11727 doFuncParamC (p, a, b, s^.funccallF.function) ;
11741 END doProcTypeArgsC ;
11748 PROCEDURE doAdrArgC (p: pretty; n: node) ;
11752 (* & and * cancel each other out. *)
11753 doExprC (p, n^.unaryF.arg)
11754 ELSIF isVar (n) AND (n^.varF.isVarParameter)
11756 (* & and * cancel each other out. *)
11757 outTextN (p, getSymName (n)) (* --fixme-- does the caller need to cast it? *)
11758 ELSIF isString (n) OR (isArray (getType (n)) AND isUnbounded (getType (n)))
11762 outText (p, "const_cast<void*> (static_cast<const void*>") ;
11780 PROCEDURE doAdrC (p: pretty; n: node) ;
11782 assert (isUnary (n)) ;
11783 doAdrArgC (p, n^.unaryF.arg)
11791 PROCEDURE doInc (p: pretty; n: node) ;
11793 assert (isIntrinsic (n)) ;
11796 doIncDecCP (p, n, "+")
11798 doIncDecC (p, n, "+=")
11807 PROCEDURE doDec (p: pretty; n: node) ;
11809 assert (isIntrinsic (n)) ;
11812 doIncDecCP (p, n, "-")
11814 doIncDecC (p, n, "-=")
11823 PROCEDURE doIncDecC (p: pretty; n: node; op: ARRAY OF CHAR) ;
11825 assert (isIntrinsic (n)) ;
11826 IF n^.intrinsicF.args # NIL
11828 doExprC (p, getExpList (n^.intrinsicF.args, 1)) ;
11832 IF expListLen (n^.intrinsicF.args) = 1
11836 doExprC (p, getExpList (n^.intrinsicF.args, 2))
11846 PROCEDURE doIncDecCP (p: pretty; n: node; op: ARRAY OF CHAR) ;
11851 assert (isIntrinsic (n)) ;
11852 IF n^.intrinsicF.args # NIL
11854 lhs := getExpList (n^.intrinsicF.args, 1) ;
11857 type := getType (lhs) ;
11858 IF isPointer (type) OR (type = addressN)
11860 (* cast to (char * ) and then back again after the arithmetic is complete. *)
11863 outText (p, 'reinterpret_cast
<') ;
11864 doTypeNameC (p, type) ;
11866 outText (p, '> (reinterpret_cast
<char
*> (') ;
11871 IF expListLen (n^.intrinsicF.args) = 1
11875 doExprC (p, getExpList (n^.intrinsicF.args, 2))
11878 ELSIF isEnumeration (skipType (type))
11880 outText (p, "= static_cast<") ;
11881 doTypeNameC (p, type) ;
11883 outText (p, ">(static_cast<int>(") ;
11887 IF expListLen (n^.intrinsicF.args) = 1
11891 doExprC (p, getExpList (n^.intrinsicF.args, 2))
11898 IF expListLen (n^.intrinsicF.args) = 1
11902 doExprC (p, getExpList (n^.intrinsicF.args, 2))
11913 PROCEDURE doInclC (p: pretty; n: node) ;
11917 assert (isIntrinsic (n)) ;
11918 IF n^.intrinsicF.args # NIL
11920 IF expListLen (n^.intrinsicF.args) = 2
11922 doExprC (p, getExpList (n^.intrinsicF.args, 1)) ;
11923 lo := getSetLow (getExpList (n^.intrinsicF.args, 1)) ;
11925 outText (p, '|
=') ;
11927 outText (p, '(1') ;
11929 outText (p, '<<') ;
11932 doExprC (p, getExpList (n^.intrinsicF.args, 2)) ;
11933 doSubtractC (p, lo) ;
11937 HALT (* metaError0 ('expecting two parameters to
INCL') *)
11947 PROCEDURE doExclC (p: pretty; n: node) ;
11951 assert (isIntrinsic (n)) ;
11952 IF n^.intrinsicF.args # NIL
11954 IF expListLen (n^.intrinsicF.args) = 2
11956 doExprC (p, getExpList (n^.intrinsicF.args, 1)) ;
11957 lo := getSetLow (getExpList (n^.intrinsicF.args, 1)) ;
11959 outText (p, '&=') ;
11961 outText (p, '(~
(1') ;
11963 outText (p, '<<') ;
11966 doExprC (p, getExpList (n^.intrinsicF.args, 2)) ;
11967 doSubtractC (p, lo) ;
11971 HALT (* metaError0 ('expecting two parameters to
EXCL') *)
11981 PROCEDURE doNewC (p: pretty; n: node) ;
11985 assert (isIntrinsic (n)) ;
11986 IF n^.intrinsicF.args = NIL
11990 IF expListLen (n^.intrinsicF.args) = 1
11993 outText (p, 'Storage_ALLOCATE
') ;
11995 outText (p, '((void
**)
') ;
11998 doExprC (p, getExpList (n^.intrinsicF.args, 1)) ;
12001 t := skipType (getType (getExpList (n^.intrinsicF.args, 1))) ;
12005 outText (p, 'sizeof
') ;
12008 doTypeNameC (p, t) ;
12012 metaError1 ('expecting a pointer type variable as the argument to
NEW, rather than
{%1ad
}', t)
12023 PROCEDURE doDisposeC (p: pretty; n: node) ;
12027 assert (isIntrinsic (n)) ;
12028 IF n^.intrinsicF.args = NIL
12032 IF expListLen (n^.intrinsicF.args) = 1
12035 outText (p, 'Storage_DEALLOCATE
') ;
12037 outText (p, '((void
**)
') ;
12040 doExprC (p, getExpList (n^.intrinsicF.args, 1)) ;
12043 t := skipType (getType (getExpList (n^.intrinsicF.args, 1))) ;
12047 outText (p, 'sizeof
') ;
12050 doTypeNameC (p, t) ;
12054 metaError1 ('expecting a pointer type variable as the argument to
DISPOSE, rather than
{%1ad
}', t)
12057 HALT (* metaError0 ('expecting a single parameter to
DISPOSE') *)
12067 PROCEDURE doCapC (p: pretty; n: node) ;
12069 assert (isUnary (n)) ;
12070 IF n^.unaryF.arg = NIL
12072 HALT (* metaError0 ('expecting a single parameter to
CAP') *)
12075 IF getGccConfigSystem ()
12077 outText (p, 'TOUPPER
')
12079 outText (p, 'toupper
')
12083 doExprC (p, n^.unaryF.arg) ;
12093 PROCEDURE doLengthC (p: pretty; n: node) ;
12095 assert (isUnary (n)) ;
12096 IF n^.unaryF.arg = NIL
12098 HALT (* metaError0 ('expecting a single parameter to LENGTH
') *)
12101 outText (p, 'M2RTS_Length
') ;
12104 doExprC (p, n^.unaryF.arg) ;
12107 doFuncHighC (p, n^.unaryF.arg) ;
12117 PROCEDURE doAbsC (p: pretty; n: node) ;
12121 assert (isUnary (n)) ;
12122 IF n^.unaryF.arg = NIL
12126 t := getExprType (n)
12131 outText (p, "labs")
12139 outText (p, "fabs")
12140 ELSIF t = longrealN
12143 outText (p, "fabsl")
12144 ELSIF t = cardinalN
12152 doExprC (p, n^.unaryF.arg) ;
12161 PROCEDURE doValC (p: pretty; n: node) ;
12163 assert (isBinary (n)) ;
12165 doTypeNameC (p, n^.binaryF.left) ;
12169 doExprC (p, n^.binaryF.right) ;
12178 PROCEDURE doMinC (p: pretty; n: node) ;
12182 assert (isUnary (n)) ;
12183 t := getExprType (n^.unaryF.arg) ;
12184 doExprC (p, getMin (t)) ;
12192 PROCEDURE doMaxC (p: pretty; n: node) ;
12196 assert (isUnary (n)) ;
12197 t := getExprType (n^.unaryF.arg) ;
12198 doExprC (p, getMax (t)) ;
12203 isIntrinsic - returns if, n, is an intrinsic procedure.
12204 The intrinsic functions are represented as unary and binary nodes.
12207 PROCEDURE isIntrinsic (n: node) : BOOLEAN ;
12231 PROCEDURE doHalt (p: pretty; n: node) ;
12233 assert (n^.kind = halt) ;
12234 IF (n^.intrinsicF.args = NIL) OR (expListLen (n^.intrinsicF.args) = 0)
12236 outText (p, 'M2RTS_HALT
') ;
12238 outText (p, '(-1)')
12239 ELSIF expListLen (n^.intrinsicF.args) = 1
12241 outText (p, 'M2RTS_HALT
') ;
12244 doExprC (p, getExpList (n^.intrinsicF.args, 1)) ;
12251 doCreal - emit the appropriate creal function.
12254 PROCEDURE doCreal (p: pretty; t: node) ;
12258 complex : keyc.useComplex ;
12259 outText (p, "creal") |
12260 longcomplex : keyc.useComplex ;
12261 outText (p, "creall") |
12262 shortcomplex: keyc.useComplex ;
12263 outText (p, "crealf")
12270 doCimag - emit the appropriate cimag function.
12273 PROCEDURE doCimag (p: pretty; t: node) ;
12277 complex : keyc.useComplex ;
12278 outText (p, "cimag") |
12279 longcomplex : keyc.useComplex ;
12280 outText (p, "cimagl") |
12281 shortcomplex: keyc.useComplex ;
12282 outText (p, "cimagf")
12292 PROCEDURE doReC (p: pretty; n: node) ;
12296 assert (n^.kind = re) ;
12297 IF n^.unaryF.arg # NIL
12299 t := getExprType (n^.unaryF.arg)
12306 doExprC (p, n^.unaryF.arg) ;
12315 PROCEDURE doImC (p: pretty; n: node) ;
12319 assert (n^.kind = im) ;
12320 IF n^.unaryF.arg # NIL
12322 t := getExprType (n^.unaryF.arg)
12329 doExprC (p, n^.unaryF.arg) ;
12338 PROCEDURE doCmplx (p: pretty; n: node) ;
12340 assert (isBinary (n)) ;
12344 doExprC (p, n^.binaryF.left) ;
12350 doExprC (p, n^.binaryF.right) ;
12363 PROCEDURE doIntrinsicC (p: pretty; n: node) ;
12365 assert (isIntrinsic (n)) ;
12366 doCommentC (p, n^.intrinsicF.intrinsicComment.body) ;
12369 unreachable: doUnreachableC (p, n) |
12370 throw : doThrowC (p, n) |
12371 halt : doHalt (p, n) |
12372 inc : doInc (p, n) |
12373 dec : doDec (p, n) |
12374 incl : doInclC (p, n) |
12375 excl : doExclC (p, n) |
12376 new : doNewC (p, n) |
12377 dispose : doDisposeC (p, n)
12381 doAfterCommentC (p, n^.intrinsicF.intrinsicComment.after)
12386 isIntrinsicFunction - returns true if, n, is an instrinsic function.
12389 PROCEDURE isIntrinsicFunction (n: node) : BOOLEAN ;
12414 END isIntrinsicFunction ;
12421 PROCEDURE doSizeC (p: pretty; n: node) ;
12423 assert (isUnary (n)) ;
12424 outText (p, "sizeof (") ;
12425 doExprC (p, n^.unaryF.arg) ;
12434 PROCEDURE doConvertC (p: pretty; n: node; conversion: ARRAY OF CHAR) ;
12438 s := InitString (conversion) ;
12439 doConvertSC (p, n, s) ;
12440 s := KillString (s)
12448 PROCEDURE doConvertSC (p: pretty; n: node; conversion: String) ;
12450 assert (isUnary (n)) ;
12452 outText (p, "((") ;
12453 outTextS (p, conversion) ;
12457 doExprC (p, n^.unaryF.arg) ;
12463 val: doValC (p, n) |
12464 adr: doAdrC (p, n) |
12466 tsize: doSizeC (p, n) |
12467 float: doConvertC (p, n, "(double)") |
12468 trunc: doConvertC (p, n, "(int)") |
12469 ord: doConvertC (p, n, "(unsigned int)") |
12470 chr: doConvertC (p, n, "(char)") |
12471 cap: doCapC (p, n) |
12472 abs: doAbsC (p, n) |
12473 high: doFuncHighC (p, n^.unaryF.arg, 1)) |
12474 length: doLengthC (p, n) |
12475 min: doMinC (p, n) |
12476 max: doMaxC (p, n) |
12477 throw: doThrowC (p, n) |
12480 cmplx: doCmplx (p, n)
12485 getFunction - return the function associate with funccall node n.
12488 PROCEDURE getFunction (n: node) : node ;
12490 assert (isFuncCall (n)) ;
12493 funccall: RETURN n^.funccallF.function
12505 PROCEDURE getFuncFromExpr (n: node) : node ;
12507 n := skipType (getType (n)) ;
12508 WHILE (n # procN) AND (NOT isProcType (n)) DO
12509 n := skipType (getType (n))
12512 END getFuncFromExpr ;
12519 PROCEDURE doFuncExprC (p: pretty; n: node) ;
12523 assert (isFuncCall (n)) ;
12524 IF isProcedure (n^.funccallF.function)
12526 doFQDNameC (p, n^.funccallF.function, TRUE) ;
12528 doFuncArgsC (p, n, n^.funccallF.function^.procedureF.parameters, TRUE)
12530 outText (p, "(*") ;
12531 doExprC (p, n^.funccallF.function) ;
12532 outText (p, ".proc") ;
12534 t := getFuncFromExpr (n^.funccallF.function) ;
12538 doProcTypeArgsC (p, n, NIL, TRUE)
12540 assert (isProcType (t)) ;
12541 doProcTypeArgsC (p, n, t^.proctypeF.parameters, TRUE)
12551 PROCEDURE doFuncCallC (p: pretty; n: node) ;
12553 doCommentC (p, n^.funccallF.funccallComment.body) ;
12554 doFuncExprC (p, n) ;
12556 doAfterCommentC (p, n^.funccallF.funccallComment.after)
12564 PROCEDURE doCaseStatementC (p: pretty; n: node; needBreak: BOOLEAN) ;
12566 p := pushPretty (p) ;
12567 setindent (p, getindent (p) + indentationC) ;
12568 doStatementSequenceC (p, n) ;
12571 outText (p, "break;\n")
12574 END doCaseStatementC ;
12581 PROCEDURE doExceptionC (p: pretty; a: ARRAY OF CHAR; n: node) ;
12585 w := getDeclaredMod (n) ;
12588 outText (p, '("') ;
12589 outTextS (p, findFileNameFromToken (w, 0)) ;
12590 outText (p, '",') ;
12592 outCard (p, tokenToLineNo (w, 0)) ;
12595 outCard (p, tokenToColumnNo (w, 0)) ;
12596 outText (p, ');\n') ;
12597 outText (p, '__builtin_unreachable ();\n')
12605 PROCEDURE doExceptionCP (p: pretty; a: ARRAY OF CHAR; n: node) ;
12609 w := getDeclaredMod (n) ;
12612 outText (p, '("') ;
12613 outTextS (p, findFileNameFromToken (w, 0)) ;
12614 outText (p, '",') ;
12616 outCard (p, tokenToLineNo (w, 0)) ;
12619 outCard (p, tokenToColumnNo (w, 0)) ;
12620 outText (p, ');\n') ;
12621 outText (p, '__builtin_unreachable ();\n')
12622 END doExceptionCP ;
12629 PROCEDURE doException (p: pretty; a: ARRAY OF CHAR; n: node) ;
12631 keyc.useException ;
12634 doExceptionCP (p, a, n)
12636 doExceptionC (p, a, n)
12645 PROCEDURE doRangeListC (p: pretty; c: node) ;
12650 assert (isCaseList (c)) ;
12652 h := HighIndice (c^.caselistF.rangePairs) ;
12654 r := GetIndice (c^.caselistF.rangePairs, i) ;
12655 assert ((r^.rangeF.hi = NIL) OR (r^.rangeF.lo = r^.rangeF.hi)) ;
12656 outText (p, "case") ;
12658 doExprC (p, r^.rangeF.lo) ;
12659 outText (p, ":\n") ;
12669 PROCEDURE doRangeIfListC (p: pretty; e, c: node) ;
12674 assert (isCaseList (c)) ;
12676 h := HighIndice (c^.caselistF.rangePairs) ;
12678 r := GetIndice (c^.caselistF.rangePairs, i) ;
12679 IF (r^.rangeF.lo # r^.rangeF.hi) AND (r^.rangeF.hi # NIL)
12681 outText (p, "((") ;
12685 outText (p, ">=") ;
12687 doExprC (p, r^.rangeF.lo) ;
12690 outText (p, "&&") ;
12692 outText (p, "((") ;
12696 outText (p, "<=") ;
12698 doExprC (p, r^.rangeF.hi) ;
12701 outText (p, "((") ;
12705 outText (p, "==") ;
12707 doExprC (p, r^.rangeF.lo) ;
12713 outText (p, "||") ;
12718 END doRangeIfListC ;
12725 PROCEDURE doCaseLabels (p: pretty; n: node; needBreak: BOOLEAN) ;
12727 assert (isCaseLabelList (n)) ;
12728 doRangeListC (p, n^.caselabellistF.caseList) ;
12729 p := pushPretty (p) ;
12730 setindent (p, getindent (p) + indentationC) ;
12731 doStatementSequenceC (p, n^.caselabellistF.statements) ;
12734 outText (p, "break;\n\n")
12744 PROCEDURE doCaseLabelListC (p: pretty; n: node; haveElse: BOOLEAN) ;
12749 assert (isCase (n)) ;
12751 h := HighIndice (n^.caseF.caseLabelList) ;
12753 c := GetIndice (n^.caseF.caseLabelList, i) ;
12754 doCaseLabels (p, c, (i<h) OR haveElse OR caseException) ;
12757 END doCaseLabelListC ;
12764 PROCEDURE doCaseIfLabels (p: pretty; e, n: node;
12767 assert (isCaseLabelList (n)) ;
12770 outText (p, "else") ;
12773 outText (p, "if") ;
12776 doRangeIfListC (p, e, n^.caselabellistF.caseList) ;
12777 outText (p, ")\n") ;
12780 doCompoundStmt (p, n^.caselabellistF.statements)
12782 outText (p, "{\n") ;
12783 doStatementSequenceC (p, n^.caselabellistF.statements) ;
12786 END doCaseIfLabels ;
12790 doCaseIfLabelListC -
12793 PROCEDURE doCaseIfLabelListC (p: pretty; n: node) ;
12798 assert (isCase (n)) ;
12800 h := HighIndice (n^.caseF.caseLabelList) ;
12802 c := GetIndice (n^.caseF.caseLabelList, i) ;
12803 doCaseIfLabels (p, n^.caseF.expression, c, i, h) ;
12806 END doCaseIfLabelListC ;
12813 PROCEDURE doCaseElseC (p: pretty; n: node) ;
12815 assert (isCase (n)) ;
12816 IF n^.caseF.else = NIL
12820 outText (p, "\ndefault:\n") ;
12821 p := pushPretty (p) ;
12822 setindent (p, getindent (p) + indentationC) ;
12823 doException (p, 'CaseException
', n) ;
12827 outText (p, "\ndefault:\n") ;
12828 doCaseStatementC (p, n^.caseF.else, TRUE)
12837 PROCEDURE doCaseIfElseC (p: pretty; n: node) ;
12839 assert (isCase (n)) ;
12840 IF n^.caseF.else = NIL
12844 outText (p, "\n") ;
12845 outText (p, "else {\n") ;
12846 p := pushPretty (p) ;
12847 setindent (p, getindent (p) + indentationC) ;
12848 doException (p, 'CaseException
', n) ;
12849 p := popPretty (p) ;
12853 outText (p, "\n") ;
12854 outText (p, "else {\n") ;
12855 doCaseStatementC (p, n^.caseF.else, FALSE) ;
12858 END doCaseIfElseC ;
12862 canUseSwitchCaseLabels - returns TRUE if all the case labels are
12863 single values and not ranges.
12866 PROCEDURE canUseSwitchCaseLabels (n: node) : BOOLEAN ;
12871 assert (isCaseLabelList (n)) ;
12872 l := n^.caselabellistF.caseList ;
12874 h := HighIndice (l^.caselistF.rangePairs) ;
12876 r := GetIndice (l^.caselistF.rangePairs, i) ;
12877 IF (r^.rangeF.hi # NIL) AND (r^.rangeF.lo # r^.rangeF.hi)
12884 END canUseSwitchCaseLabels ;
12888 canUseSwitch - returns TRUE if the case statement can be implement
12889 by a switch statement. This will be TRUE if all case
12890 selectors are single values rather than ranges.
12893 PROCEDURE canUseSwitch (n: node) : BOOLEAN ;
12898 assert (isCase (n)) ;
12900 h := HighIndice (n^.caseF.caseLabelList) ;
12902 c := GetIndice (n^.caseF.caseLabelList, i) ;
12903 IF NOT canUseSwitchCaseLabels (c)
12917 PROCEDURE doCaseC (p: pretty; n: node) ;
12921 assert (isCase (n)) ;
12922 IF canUseSwitch (n)
12924 i := getindent (p) ;
12925 outText (p, "switch") ;
12928 doExprC (p, n^.caseF.expression) ;
12929 p := pushPretty (p) ;
12931 setindent (p, i + indentationC) ;
12932 outText (p, "\n{\n") ;
12933 p := pushPretty (p) ;
12934 setindent (p, getindent (p) + indentationC) ;
12935 doCaseLabelListC (p, n, n^.caseF.else # NIL) ;
12936 doCaseElseC (p, n) ;
12937 p := popPretty (p) ;
12938 outText (p, "}\n") ;
12941 doCaseIfLabelListC (p, n) ;
12942 doCaseIfElseC (p, n)
12951 PROCEDURE doLoopC (p: pretty; s: node) ;
12953 assert (isLoop (s)) ;
12954 outText (p, 'for (;;)\n') ;
12955 outText (p, "{\n") ;
12956 p := pushPretty (p) ;
12957 setindent (p, getindent (p) + indentationC) ;
12958 doStatementSequenceC (p, s^.loopF.statements) ;
12959 p := popPretty (p) ;
12968 PROCEDURE doExitC (p: pretty; s: node) ;
12970 assert (isExit (s)) ;
12971 outText (p, "/* exit. */\n")
12979 PROCEDURE doStatementsC (p: pretty; s: node) ;
12984 ELSIF isStatementSequence (s)
12986 doStatementSequenceC (p, s)
12987 ELSIF isComment (s)
12996 ELSIF isAssignment (s)
12998 doAssignmentC (p, s)
13011 ELSIF isIntrinsic (s)
13013 doIntrinsicC (p, s)
13014 ELSIF isFuncCall (s)
13027 HALT (* need to handle another s^.kind. *)
13029 END doStatementsC ;
13032 PROCEDURE localstop ;
13040 PROCEDURE doLocalVarC (p: pretty; s: scopeT) ;
13042 includeVarProcedure (s) ;
13044 topologicallyOut (doConstC, doTypesC, doVarC,
13046 doNone, doCompletePartialC, doNone)
13051 doLocalConstTypesC -
13054 PROCEDURE doLocalConstTypesC (p: pretty; s: scopeT) ;
13056 simplifyTypes (s) ;
13057 includeConstType (s) ;
13061 topologicallyOut (doConstC, doTypesC, doVarC,
13063 doNone, doCompletePartialC, doNone) ;
13065 END doLocalConstTypesC ;
13072 PROCEDURE addParamDone (n: node) ;
13074 IF isVar (n) AND n^.varF.isParameter
13077 addDone (getType (n))
13083 includeParameters -
13086 PROCEDURE includeParameters (n: node) ;
13088 assert (isProcedure (n)) ;
13089 ForeachIndiceInIndexDo (n^.procedureF.decls.variables, addParamDone)
13090 END includeParameters ;
13097 PROCEDURE isHalt (n: node) : BOOLEAN ;
13099 RETURN n^.kind = halt
13107 PROCEDURE isReturnOrHalt (n: node) : BOOLEAN ;
13109 RETURN isHalt (n) OR isReturn (n)
13110 END isReturnOrHalt ;
13114 isLastStatementReturn -
13117 PROCEDURE isLastStatementReturn (n: node) : BOOLEAN ;
13119 RETURN isLastStatement (n, isReturnOrHalt)
13120 END isLastStatementReturn ;
13124 isLastStatementSequence -
13127 PROCEDURE isLastStatementSequence (n: node; q: isNodeF) : BOOLEAN ;
13131 assert (isStatementSequence (n)) ;
13132 h := HighIndice (n^.stmtF.statements) ;
13135 RETURN isLastStatement (GetIndice (n^.stmtF.statements, h), q)
13138 END isLastStatementSequence ;
13142 isLastStatementIf -
13145 PROCEDURE isLastStatementIf (n: node; q: isNodeF) : BOOLEAN ;
13149 assert (isIf (n)) ;
13151 IF (n^.ifF.elsif # NIL) AND ret
13153 ret := isLastStatement (n^.ifF.elsif, q)
13155 IF (n^.ifF.then # NIL) AND ret
13157 ret := isLastStatement (n^.ifF.then, q)
13159 IF (n^.ifF.else # NIL) AND ret
13161 ret := isLastStatement (n^.ifF.else, q)
13164 END isLastStatementIf ;
13168 isLastStatementElsif -
13171 PROCEDURE isLastStatementElsif (n: node; q: isNodeF) : BOOLEAN ;
13175 assert (isElsif (n)) ;
13177 IF (n^.elsifF.elsif # NIL) AND ret
13179 ret := isLastStatement (n^.elsifF.elsif, q)
13181 IF (n^.elsifF.then # NIL) AND ret
13183 ret := isLastStatement (n^.elsifF.then, q)
13185 IF (n^.elsifF.else # NIL) AND ret
13187 ret := isLastStatement (n^.elsifF.else, q)
13190 END isLastStatementElsif ;
13194 isLastStatementCase -
13197 PROCEDURE isLastStatementCase (n: node; q: isNodeF) : BOOLEAN ;
13204 assert (isCase (n)) ;
13206 h := HighIndice (n^.caseF.caseLabelList) ;
13208 c := GetIndice (n^.caseF.caseLabelList, i) ;
13209 assert (isCaseLabelList (c)) ;
13210 ret := ret AND isLastStatement (c^.caselabellistF.statements, q) ;
13213 IF n^.caseF.else # NIL
13215 ret := ret AND isLastStatement (n^.caseF.else, q)
13218 END isLastStatementCase ;
13222 isLastStatement - returns TRUE if the last statement in, n, is, q.
13225 PROCEDURE isLastStatement (n: node; q: isNodeF) : BOOLEAN ;
13232 ELSIF isStatementSequence (n)
13234 RETURN isLastStatementSequence (n, q)
13235 ELSIF isProcedure (n)
13237 assert (isProcedure (n)) ;
13238 RETURN isLastStatement (n^.procedureF.beginStatements, q)
13241 RETURN isLastStatementIf (n, q)
13244 RETURN isLastStatementElsif (n, q)
13247 RETURN isLastStatementCase (n, q)
13253 END isLastStatement ;
13260 PROCEDURE doProcedureC (n: node) ;
13264 outText (doP, "\n") ;
13265 includeParameters (n) ;
13267 keyc.enterScope (n) ;
13269 doProcedureHeadingC (n, FALSE) ;
13270 outText (doP, "\n") ;
13271 doP := outKc (doP, "{\n") ;
13272 s := getcurline (doP) ;
13273 doLocalConstTypesC (doP, n^.procedureF.decls) ;
13274 doLocalVarC (doP, n^.procedureF.decls) ;
13275 doUnboundedParamCopyC (doP, n) ;
13277 IF s # getcurline (doP)
13279 outText (doP, "\n")
13282 doStatementsC (doP, n^.procedureF.beginStatements) ;
13283 IF n^.procedureF.returnType # NIL
13287 IF isLastStatementReturn (n)
13289 outText (doP, "/* static analysis guarentees a RETURN statement will be used before here. */\n") ;
13290 outText (doP, "__builtin_unreachable ();\n") ;
13292 doException (doP, 'ReturnException
', n)
13296 doP := outKc (doP, "}\n") ;
13297 keyc.leaveScope (n)
13305 PROCEDURE outProceduresC (p: pretty; s: scopeT) ;
13310 printf ("seen %d procedures\n", HighIndice (s.procedures))
13313 ForeachIndiceInIndexDo (s.procedures, doProcedureC)
13314 END outProceduresC ;
13321 PROCEDURE output (n: node; c, t, v: nodeProcedure) ;
13339 PROCEDURE allDependants (n: node) : dependentState ;
13342 s: dependentState ;
13344 l := alists.initList () ;
13345 s := walkDependants (l, n) ;
13346 alists.killList (l) ;
13348 END allDependants ;
13355 PROCEDURE walkDependants (l: alist; n: node) : dependentState ;
13357 IF (n=NIL) OR alists.isItemInList (globalGroup^.doneQ, n)
13360 ELSIF alists.isItemInList (l, n)
13364 alists.includeItemIntoList (l, n) ;
13365 RETURN doDependants (l, n)
13367 END walkDependants ;
13374 PROCEDURE walkType (l: alist; n: node) : dependentState ;
13379 IF alists.isItemInList (globalGroup^.doneQ, t)
13382 ELSIF alists.isItemInList (globalGroup^.partialQ, t)
13396 PROCEDURE db (a: ARRAY OF CHAR; n: node) ;
13398 IF getDebugTopological ()
13403 outTextS (doP, gen (n))
13413 PROCEDURE dbt (a: ARRAY OF CHAR) ;
13415 IF getDebugTopological ()
13426 PROCEDURE dbs (s: dependentState; n: node) ;
13428 IF getDebugTopological ()
13432 completed: outText (doP, '{completed
') |
13433 blocked : outText (doP, '{blocked
') |
13434 partial : outText (doP, '{partial
') |
13435 recursive: outText (doP, '{recursive
')
13440 outTextS (doP, gen (n))
13442 outText (doP, '}\n')
13451 PROCEDURE dbq (n: node) ;
13453 IF getDebugTopological ()
13455 IF alists.isItemInList (globalGroup^.todoQ, n)
13457 db ('{T
', n) ; outText (doP, '}')
13458 ELSIF alists.isItemInList (globalGroup^.partialQ, n)
13460 db ('{P
', n) ; outText (doP, '}')
13461 ELSIF alists.isItemInList (globalGroup^.doneQ, n)
13463 db ('{D
', n) ; outText (doP, '}')
13473 PROCEDURE walkRecord (l: alist; n: node) : dependentState ;
13475 s : dependentState ;
13480 i := LowIndice (n^.recordF.listOfSons) ;
13481 t := HighIndice (n^.recordF.listOfSons) ;
13482 db ('\nwalking
', n) ; o := getindent (doP) ; setindent (doP, getcurpos (doP)+3) ;
13485 q := GetIndice (n^.recordF.listOfSons, i) ;
13487 IF isRecordField (q) AND q^.recordfieldF.tag
13489 (* do nothing as it is a tag selector processed in the varient. *)
13491 s := walkDependants (l, q) ;
13498 setindent (doP, o) ;
13504 db ('{completed
', n) ; dbt ('}\n') ;
13505 setindent (doP, o) ;
13514 PROCEDURE walkVarient (l: alist; n: node) : dependentState ;
13516 s : dependentState ;
13520 db ('\nwalking
', n) ;
13521 s := walkDependants (l, n^.varientF.tag) ;
13524 dbs (s, n^.varientF.tag) ;
13525 dbq (n^.varientF.tag) ;
13529 i := LowIndice (n^.varientF.listOfSons) ;
13530 t := HighIndice (n^.varientF.listOfSons) ;
13532 q := GetIndice (n^.varientF.listOfSons, i) ;
13534 s := walkDependants (l, q) ;
13543 db ('{completed
', n) ; dbt ('}\n') ;
13552 PROCEDURE queueBlocked (n: node) ;
13554 IF NOT (alists.isItemInList (globalGroup^.doneQ, n) OR
13555 alists.isItemInList (globalGroup^.partialQ, n))
13566 PROCEDURE walkVar (l: alist; n: node) : dependentState ;
13571 IF alists.isItemInList (globalGroup^.doneQ, t)
13585 PROCEDURE walkEnumeration (l: alist; n: node) : dependentState ;
13587 s : dependentState ;
13591 i := LowIndice (n^.enumerationF.listOfSons) ;
13592 t := HighIndice (n^.enumerationF.listOfSons) ;
13595 q := GetIndice (n^.enumerationF.listOfSons, i) ;
13596 s := walkDependants (l, q) ;
13604 END walkEnumeration ;
13611 PROCEDURE walkSubrange (l: alist; n: node) : dependentState ;
13613 s: dependentState ;
13615 WITH n^.subrangeF DO
13616 s := walkDependants (l, low) ;
13621 s := walkDependants (l, high) ;
13626 s := walkDependants (l, type) ;
13640 PROCEDURE walkSubscript (l: alist; n: node) : dependentState ;
13642 s: dependentState ;
13644 WITH n^.subscriptF DO
13645 s := walkDependants (l, expr) ;
13650 s := walkDependants (l, type) ;
13657 END walkSubscript ;
13664 PROCEDURE walkPointer (l: alist; n: node) : dependentState ;
13668 (* if the type of, n, is done or partial then we can output pointer. *)
13670 IF alists.isItemInList (globalGroup^.partialQ, t) OR
13671 alists.isItemInList (globalGroup^.doneQ, t)
13673 (* pointer to partial can always generate a complete type. *)
13676 RETURN walkType (l, n)
13684 PROCEDURE walkArray (l: alist; n: node) : dependentState ;
13686 s: dependentState ;
13690 s := walkDependants (l, type) ;
13696 (* an array can only be declared if its data type has already been emitted. *)
13697 IF NOT alists.isItemInList (globalGroup^.doneQ, type)
13699 s := walkDependants (l, type) ;
13700 queueBlocked (type) ;
13703 (* downgrade the completed to partial as it has not yet been written. *)
13709 RETURN walkDependants (l, subr)
13718 PROCEDURE walkConst (l: alist; n: node) : dependentState ;
13720 s: dependentState ;
13723 s := walkDependants (l, type) ;
13728 s := walkDependants (l, value) ;
13742 PROCEDURE walkVarParam (l: alist; n: node) : dependentState ;
13747 IF alists.isItemInList (globalGroup^.partialQ, t)
13749 (* parameter can be issued from a partial. *)
13752 RETURN walkDependants (l, t)
13760 PROCEDURE walkParam (l: alist; n: node) : dependentState ;
13765 IF alists.isItemInList (globalGroup^.partialQ, t)
13767 (* parameter can be issued from a partial. *)
13770 RETURN walkDependants (l, t)
13778 PROCEDURE walkOptarg (l: alist; n: node) : dependentState ;
13783 IF alists.isItemInList (globalGroup^.partialQ, t)
13785 (* parameter can be issued from a partial. *)
13788 RETURN walkDependants (l, t)
13796 PROCEDURE walkRecordField (l: alist; n: node) : dependentState ;
13799 s: dependentState ;
13801 assert (isRecordField (n)) ;
13803 IF alists.isItemInList (globalGroup^.partialQ, t)
13807 ELSIF alists.isItemInList (globalGroup^.doneQ, t)
13809 dbs (completed, n) ;
13816 (* s := walkDependants (l, t) *)
13819 END walkRecordField ;
13826 PROCEDURE walkVarientField (l: alist; n: node) : dependentState ;
13828 s : dependentState ;
13832 i := LowIndice (n^.varientfieldF.listOfSons) ;
13833 t := HighIndice (n^.varientfieldF.listOfSons) ;
13836 q := GetIndice (n^.varientfieldF.listOfSons, i) ;
13837 s := walkDependants (l, q) ;
13845 n^.varientfieldF.simple := (t <= 1) ;
13848 END walkVarientField ;
13852 walkEnumerationField -
13855 PROCEDURE walkEnumerationField (l: alist; n: node) : dependentState ;
13858 END walkEnumerationField ;
13865 PROCEDURE walkSet (l: alist; n: node) : dependentState ;
13867 RETURN walkDependants (l, getType (n))
13875 PROCEDURE walkProcType (l: alist; n: node) : dependentState ;
13877 s: dependentState ;
13881 IF alists.isItemInList (globalGroup^.partialQ, t)
13883 (* proctype can be generated from partial types. *)
13885 s := walkDependants (l, t) ;
13891 RETURN walkParameters (l, n^.proctypeF.parameters)
13899 PROCEDURE walkProcedure (l: alist; n: node) : dependentState ;
13901 s: dependentState ;
13903 s := walkDependants (l, getType (n)) ;
13908 RETURN walkParameters (l, n^.procedureF.parameters)
13909 END walkProcedure ;
13916 PROCEDURE walkParameters (l: alist; p: Index) : dependentState ;
13918 s : dependentState ;
13922 i := LowIndice (p) ;
13923 h := HighIndice (p) ;
13925 q := GetIndice (p, i) ;
13926 s := walkDependants (l, q) ;
13934 END walkParameters ;
13941 PROCEDURE walkFuncCall (l: alist; n: node) : dependentState ;
13951 PROCEDURE walkUnary (l: alist; n: node) : dependentState ;
13953 s: dependentState ;
13956 s := walkDependants (l, arg) ;
13961 RETURN walkDependants (l, resultType)
13970 PROCEDURE walkBinary (l: alist; n: node) : dependentState ;
13972 s: dependentState ;
13975 s := walkDependants (l, left) ;
13980 s := walkDependants (l, right) ;
13985 RETURN walkDependants (l, resultType)
13994 PROCEDURE walkComponentRef (l: alist; n: node) : dependentState ;
13996 s: dependentState ;
13998 WITH n^.componentrefF DO
13999 s := walkDependants (l, rec) ;
14004 s := walkDependants (l, field) ;
14009 RETURN walkDependants (l, resultType)
14011 END walkComponentRef ;
14018 PROCEDURE walkPointerRef (l: alist; n: node) : dependentState ;
14020 s: dependentState ;
14022 WITH n^.pointerrefF DO
14023 s := walkDependants (l, ptr) ;
14028 s := walkDependants (l, field) ;
14033 RETURN walkDependants (l, resultType)
14035 END walkPointerRef ;
14042 PROCEDURE walkSetValue (l: alist; n: node) : dependentState ;
14044 s : dependentState ;
14047 assert (isSetValue (n)) ;
14048 WITH n^.setvalueF DO
14049 s := walkDependants (l, type) ;
14054 i := LowIndice (values) ;
14055 j := HighIndice (values) ;
14057 s := walkDependants (l, GetIndice (values, i)) ;
14070 doDependants - return the dependentState depending upon whether
14071 all dependants have been declared.
14074 PROCEDURE doDependants (l: alist; n: node) : dependentState ;
14079 throw, (* --fixme-- *)
14105 proc : RETURN completed |
14106 (* language features and compound type attributes. *)
14107 type : RETURN walkType (l, n) |
14108 record : RETURN walkRecord (l, n) |
14109 varient : RETURN walkVarient (l, n) |
14110 var : RETURN walkVar (l, n) |
14111 enumeration : RETURN walkEnumeration (l, n) |
14112 subrange : RETURN walkSubrange (l, n) |
14113 pointer : RETURN walkPointer (l, n) |
14114 array : RETURN walkArray (l, n) |
14115 string : RETURN completed |
14116 const : RETURN walkConst (l, n) |
14117 literal : RETURN completed |
14118 varparam : RETURN walkVarParam (l, n) |
14119 param : RETURN walkParam (l, n) |
14120 optarg : RETURN walkOptarg (l, n) |
14121 recordfield : RETURN walkRecordField (l, n) |
14122 varientfield : RETURN walkVarientField (l, n) |
14123 enumerationfield: RETURN walkEnumerationField (l, n) |
14124 set : RETURN walkSet (l, n) |
14125 proctype : RETURN walkProcType (l, n) |
14126 subscript : RETURN walkSubscript (l, n) |
14128 procedure : RETURN walkProcedure (l, n) |
14139 assignment : HALT |
14141 componentref : RETURN walkComponentRef (l, n) |
14142 pointerref : RETURN walkPointerRef (l, n) |
14152 high : RETURN walkUnary (l, n) |
14160 divide : RETURN walkBinary (l, n) |
14166 deref : RETURN walkUnary (l, n) |
14172 lessequal : RETURN walkBinary (l, n) |
14173 funccall : RETURN walkFuncCall (l, n) |
14174 setvalue : RETURN walkSetValue (l, n)
14182 tryComplete - returns TRUE if node, n, can be and was completed.
14185 PROCEDURE tryComplete (n: node; c, t, v: nodeProcedure) : BOOLEAN ;
14187 IF isEnumeration (n)
14189 (* can always emit enumerated types. *)
14190 output (n, c, t, v) ;
14192 ELSIF isType (n) AND isTypeHidden (n) AND (getType (n)=NIL)
14194 (* can always emit hidden types. *)
14197 ELSIF allDependants (n) = completed
14199 output (n, c, t, v) ;
14207 tryCompleteFromPartial -
14210 PROCEDURE tryCompleteFromPartial (n: node; t: nodeProcedure) : BOOLEAN ;
14212 IF isType (n) AND (getType (n)#NIL) AND isPointer (getType (n)) AND (allDependants (getType (n)) = completed)
14214 (* alists.includeItemIntoList (globalGroup^.partialQ, getType (n)) ; *)
14215 outputHiddenComplete (n) ;
14217 ELSIF allDependants (n) = completed
14223 END tryCompleteFromPartial ;
14227 visitIntrinsicFunction -
14230 PROCEDURE visitIntrinsicFunction (v: alist; n: node; p: nodeProcedure) ;
14232 assert (isIntrinsicFunction (n)) ;
14236 cmplx: WITH n^.binaryF DO
14237 visitNode (v, left, p) ;
14238 visitNode (v, right, p) ;
14239 visitNode (v, resultType, p)
14255 im : WITH n^.unaryF DO
14256 visitNode (v, arg, p) ;
14257 visitNode (v, resultType, p)
14261 END visitIntrinsicFunction ;
14268 PROCEDURE visitUnary (v: alist; n: node; p: nodeProcedure) ;
14270 assert (isUnary (n)) ;
14272 visitNode (v, arg, p) ;
14273 visitNode (v, resultType, p)
14282 PROCEDURE visitBinary (v: alist; n: node; p: nodeProcedure) ;
14285 visitNode (v, left, p) ;
14286 visitNode (v, right, p) ;
14287 visitNode (v, resultType, p)
14296 PROCEDURE visitBoolean (v: alist; n: node; p: nodeProcedure) ;
14298 visitNode (v, falseN, p) ;
14299 visitNode (v, trueN, p)
14307 PROCEDURE visitScope (v: alist; n: node; p: nodeProcedure) ;
14311 visitNode (v, n, p)
14320 PROCEDURE visitType (v: alist; n: node; p: nodeProcedure) ;
14322 assert (isType (n)) ;
14323 visitNode (v, n^.typeF.type, p) ;
14324 visitScope (v, n^.typeF.scope, p)
14332 PROCEDURE visitIndex (v: alist; i: Index; p: nodeProcedure) ;
14337 h := HighIndice (i) ;
14339 visitNode (v, GetIndice (i, j), p) ;
14349 PROCEDURE visitRecord (v: alist; n: node; p: nodeProcedure) ;
14351 assert (isRecord (n)) ;
14352 visitScope (v, n^.recordF.scope, p) ;
14353 visitIndex (v, n^.recordF.listOfSons, p)
14361 PROCEDURE visitVarient (v: alist; n: node; p: nodeProcedure) ;
14363 assert (isVarient (n)) ;
14364 visitIndex (v, n^.varientF.listOfSons, p) ;
14365 visitNode (v, n^.varientF.varient, p) ;
14366 visitNode (v, n^.varientF.tag, p) ;
14367 visitScope (v, n^.varientF.scope, p)
14375 PROCEDURE visitVar (v: alist; n: node; p: nodeProcedure) ;
14377 assert (isVar (n)) ;
14378 visitNode (v, n^.varF.type, p) ;
14379 visitNode (v, n^.varF.decl, p) ;
14380 visitScope (v, n^.varF.scope, p)
14388 PROCEDURE visitEnumeration (v: alist; n: node; p: nodeProcedure) ;
14390 assert (isEnumeration (n)) ;
14391 visitIndex (v, n^.enumerationF.listOfSons, p) ;
14392 visitScope (v, n^.enumerationF.scope, p)
14393 END visitEnumeration ;
14400 PROCEDURE visitSubrange (v: alist; n: node; p: nodeProcedure) ;
14402 assert (isSubrange (n)) ;
14403 visitNode (v, n^.subrangeF.low, p) ;
14404 visitNode (v, n^.subrangeF.high, p) ;
14405 visitNode (v, n^.subrangeF.type, p) ;
14406 visitScope (v, n^.subrangeF.scope, p)
14407 END visitSubrange ;
14414 PROCEDURE visitPointer (v: alist; n: node; p: nodeProcedure) ;
14416 assert (isPointer (n)) ;
14417 visitNode (v, n^.pointerF.type, p) ;
14418 visitScope (v, n^.pointerF.scope, p)
14426 PROCEDURE visitArray (v: alist; n: node; p: nodeProcedure) ;
14428 assert (isArray (n)) ;
14429 visitNode (v, n^.arrayF.subr, p) ;
14430 visitNode (v, n^.arrayF.type, p) ;
14431 visitScope (v, n^.arrayF.scope, p)
14439 PROCEDURE visitConst (v: alist; n: node; p: nodeProcedure) ;
14441 assert (isConst (n)) ;
14442 visitNode (v, n^.constF.type, p) ;
14443 visitNode (v, n^.constF.value, p) ;
14444 visitScope (v, n^.constF.scope, p)
14452 PROCEDURE visitVarParam (v: alist; n: node; p: nodeProcedure) ;
14454 assert (isVarParam (n)) ;
14455 visitNode (v, n^.varparamF.namelist, p) ;
14456 visitNode (v, n^.varparamF.type, p) ;
14457 visitScope (v, n^.varparamF.scope, p)
14458 END visitVarParam ;
14465 PROCEDURE visitParam (v: alist; n: node; p: nodeProcedure) ;
14467 assert (isParam (n)) ;
14468 visitNode (v, n^.paramF.namelist, p) ;
14469 visitNode (v, n^.paramF.type, p) ;
14470 visitScope (v, n^.paramF.scope, p)
14478 PROCEDURE visitOptarg (v: alist; n: node; p: nodeProcedure) ;
14480 assert (isOptarg (n)) ;
14481 visitNode (v, n^.optargF.namelist, p) ;
14482 visitNode (v, n^.optargF.type, p) ;
14483 visitNode (v, n^.optargF.init, p) ;
14484 visitScope (v, n^.optargF.scope, p)
14492 PROCEDURE visitRecordField (v: alist; n: node; p: nodeProcedure) ;
14494 assert (isRecordField (n)) ;
14495 visitNode (v, n^.recordfieldF.type, p) ;
14496 visitNode (v, n^.recordfieldF.parent, p) ;
14497 visitNode (v, n^.recordfieldF.varient, p) ;
14498 visitScope (v, n^.recordfieldF.scope, p)
14499 END visitRecordField ;
14503 visitVarientField -
14506 PROCEDURE visitVarientField (v: alist; n: node; p: nodeProcedure) ;
14508 assert (isVarientField (n)) ;
14509 visitNode (v, n^.varientfieldF.parent, p) ;
14510 visitNode (v, n^.varientfieldF.varient, p) ;
14511 visitIndex (v, n^.varientfieldF.listOfSons, p) ;
14512 visitScope (v, n^.varientfieldF.scope, p)
14513 END visitVarientField ;
14517 visitEnumerationField -
14520 PROCEDURE visitEnumerationField (v: alist; n: node; p: nodeProcedure) ;
14522 assert (isEnumerationField (n)) ;
14523 visitNode (v, n^.enumerationfieldF.type, p) ;
14524 visitScope (v, n^.enumerationfieldF.scope, p)
14525 END visitEnumerationField ;
14532 PROCEDURE visitSet (v: alist; n: node; p: nodeProcedure) ;
14534 assert (isSet (n)) ;
14535 visitNode (v, n^.setF.type, p) ;
14536 visitScope (v, n^.setF.scope, p)
14544 PROCEDURE visitProcType (v: alist; n: node; p: nodeProcedure) ;
14546 assert (isProcType (n)) ;
14547 visitIndex (v, n^.proctypeF.parameters, p) ;
14548 visitNode (v, n^.proctypeF.optarg, p) ;
14549 visitNode (v, n^.proctypeF.returnType, p) ;
14550 visitScope (v, n^.proctypeF.scope, p)
14551 END visitProcType ;
14558 PROCEDURE visitSubscript (v: alist; n: node; p: nodeProcedure) ;
14561 assert (isSubscript (n)) ;
14562 visitNode (v, n^.subscriptF.type, p) ;
14563 visitNode (v, n^.subscriptF.expr, p)
14565 END visitSubscript ;
14572 PROCEDURE visitDecls (v: alist; s: scopeT; p: nodeProcedure) ;
14574 visitIndex (v, s.constants, p) ;
14575 visitIndex (v, s.types, p) ;
14576 visitIndex (v, s.procedures, p) ;
14577 visitIndex (v, s.variables, p)
14585 PROCEDURE visitProcedure (v: alist; n: node; p: nodeProcedure) ;
14587 assert (isProcedure (n)) ;
14588 visitDecls (v, n^.procedureF.decls, p) ;
14589 visitScope (v, n^.procedureF.scope, p) ;
14590 visitIndex (v, n^.procedureF.parameters, p) ;
14591 visitNode (v, n^.procedureF.optarg, p) ;
14592 visitNode (v, n^.procedureF.returnType, p) ;
14593 visitNode (v, n^.procedureF.beginStatements, p)
14594 END visitProcedure ;
14601 PROCEDURE visitDef (v: alist; n: node; p: nodeProcedure) ;
14603 assert (isDef (n)) ;
14604 visitDecls (v, n^.defF.decls, p)
14612 PROCEDURE visitImp (v: alist; n: node; p: nodeProcedure) ;
14614 assert (isImp (n)) ;
14615 visitDecls (v, n^.impF.decls, p) ;
14616 visitNode (v, n^.impF.beginStatements, p) ;
14617 visitNode (v, n^.impF.finallyStatements, p)
14618 (* --fixme-- do we need to visit definitionModule? *)
14626 PROCEDURE visitModule (v: alist; n: node; p: nodeProcedure) ;
14628 assert (isModule (n)) ;
14629 visitDecls (v, n^.moduleF.decls, p) ;
14630 visitNode (v, n^.moduleF.beginStatements, p) ;
14631 visitNode (v, n^.moduleF.finallyStatements, p)
14639 PROCEDURE visitLoop (v: alist; n: node; p: nodeProcedure) ;
14641 assert (isLoop (n)) ;
14642 visitNode (v, n^.loopF.statements, p)
14650 PROCEDURE visitWhile (v: alist; n: node; p: nodeProcedure) ;
14652 assert (isWhile (n)) ;
14653 visitNode (v, n^.whileF.expr, p) ;
14654 visitNode (v, n^.whileF.statements, p)
14662 PROCEDURE visitRepeat (v: alist; n: node; p: nodeProcedure) ;
14664 assert (isRepeat (n)) ;
14665 visitNode (v, n^.repeatF.expr, p) ;
14666 visitNode (v, n^.repeatF.statements, p)
14674 PROCEDURE visitCase (v: alist; n: node; p: nodeProcedure) ;
14676 assert (isCase (n)) ;
14677 visitNode (v, n^.caseF.expression, p) ;
14678 visitIndex (v, n^.caseF.caseLabelList, p) ;
14679 visitNode (v, n^.caseF.else, p)
14684 visitCaseLabelList -
14687 PROCEDURE visitCaseLabelList (v: alist; n: node; p: nodeProcedure) ;
14689 assert (isCaseLabelList (n)) ;
14690 visitNode (v, n^.caselabellistF.caseList, p) ;
14691 visitNode (v, n^.caselabellistF.statements, p)
14692 END visitCaseLabelList ;
14699 PROCEDURE visitCaseList (v: alist; n: node; p: nodeProcedure) ;
14701 assert (isCaseList (n)) ;
14702 visitIndex (v, n^.caselistF.rangePairs, p)
14703 END visitCaseList ;
14710 PROCEDURE visitRange (v: alist; n: node; p: nodeProcedure) ;
14712 assert (isRange (n)) ;
14713 visitNode (v, n^.rangeF.lo, p) ;
14714 visitNode (v, n^.rangeF.hi, p)
14722 PROCEDURE visitIf (v: alist; n: node; p: nodeProcedure) ;
14724 assert (isIf (n)) ;
14725 visitNode (v, n^.ifF.expr, p) ;
14726 visitNode (v, n^.ifF.elsif, p) ;
14727 visitNode (v, n^.ifF.then, p) ;
14728 visitNode (v, n^.ifF.else, p)
14736 PROCEDURE visitElsif (v: alist; n: node; p: nodeProcedure) ;
14738 assert (isElsif (n)) ;
14739 visitNode (v, n^.elsifF.expr, p) ;
14740 visitNode (v, n^.elsifF.elsif, p) ;
14741 visitNode (v, n^.elsifF.then, p) ;
14742 visitNode (v, n^.elsifF.else, p)
14750 PROCEDURE visitFor (v: alist; n: node; p: nodeProcedure) ;
14752 assert (isFor (n)) ;
14753 visitNode (v, n^.forF.des, p) ;
14754 visitNode (v, n^.forF.start, p) ;
14755 visitNode (v, n^.forF.end, p) ;
14756 visitNode (v, n^.forF.increment, p) ;
14757 visitNode (v, n^.forF.statements, p)
14765 PROCEDURE visitAssignment (v: alist; n: node; p: nodeProcedure) ;
14767 assert (isAssignment (n)) ;
14768 visitNode (v, n^.assignmentF.des, p) ;
14769 visitNode (v, n^.assignmentF.expr, p)
14770 END visitAssignment ;
14774 visitComponentRef -
14777 PROCEDURE visitComponentRef (v: alist; n: node; p: nodeProcedure) ;
14779 assert (isComponentRef (n)) ;
14780 visitNode (v, n^.componentrefF.rec, p) ;
14781 visitNode (v, n^.componentrefF.field, p) ;
14782 visitNode (v, n^.componentrefF.resultType, p)
14783 END visitComponentRef ;
14790 PROCEDURE visitPointerRef (v: alist; n: node; p: nodeProcedure) ;
14792 assert (isPointerRef (n)) ;
14793 visitNode (v, n^.pointerrefF.ptr, p) ;
14794 visitNode (v, n^.pointerrefF.field, p) ;
14795 visitNode (v, n^.pointerrefF.resultType, p)
14796 END visitPointerRef ;
14803 PROCEDURE visitArrayRef (v: alist; n: node; p: nodeProcedure) ;
14805 assert (isArrayRef (n)) ;
14806 visitNode (v, n^.arrayrefF.array, p) ;
14807 visitNode (v, n^.arrayrefF.index, p) ;
14808 visitNode (v, n^.arrayrefF.resultType, p)
14809 END visitArrayRef ;
14816 PROCEDURE visitFunccall (v: alist; n: node; p: nodeProcedure) ;
14818 assert (isFuncCall (n)) ;
14819 visitNode (v, n^.funccallF.function, p) ;
14820 visitNode (v, n^.funccallF.args, p) ;
14821 visitNode (v, n^.funccallF.type, p)
14822 END visitFunccall ;
14829 PROCEDURE visitVarDecl (v: alist; n: node; p: nodeProcedure) ;
14831 assert (isVarDecl (n)) ;
14832 visitNode (v, n^.vardeclF.type, p) ;
14833 visitScope (v, n^.vardeclF.scope, p)
14841 PROCEDURE visitExplist (v: alist; n: node; p: nodeProcedure) ;
14843 assert (isExpList (n)) ;
14844 visitIndex (v, n^.explistF.exp, p)
14852 PROCEDURE visitExit (v: alist; n: node; p: nodeProcedure) ;
14854 assert (isExit (n)) ;
14855 visitNode (v, n^.exitF.loop, p)
14863 PROCEDURE visitReturn (v: alist; n: node; p: nodeProcedure) ;
14865 assert (isReturn (n)) ;
14866 visitNode (v, n^.returnF.exp, p)
14874 PROCEDURE visitStmtSeq (v: alist; n: node; p: nodeProcedure) ;
14876 assert (isStatementSequence (n)) ;
14877 visitIndex (v, n^.stmtF.statements, p)
14885 PROCEDURE visitVarargs (v: alist; n: node; p: nodeProcedure) ;
14887 assert (isVarargs (n)) ;
14888 visitScope (v, n^.varargsF.scope, p)
14896 PROCEDURE visitSetValue (v: alist; n: node; p: nodeProcedure) ;
14898 assert (isSetValue (n)) ;
14899 visitNode (v, n^.setvalueF.type, p) ;
14900 visitIndex (v, n^.setvalueF.values, p)
14901 END visitSetValue ;
14908 PROCEDURE visitIntrinsic (v: alist; n: node; p: nodeProcedure) ;
14910 assert (isIntrinsic (n)) ;
14911 visitNode (v, n^.intrinsicF.args, p)
14912 END visitIntrinsic ;
14916 visitDependants - helper procedure function called from visitNode.
14917 node n has just been visited, this procedure will
14918 visit node, n, dependants.
14921 PROCEDURE visitDependants (v: alist; n: node; p: nodeProcedure) ;
14924 assert (alists.isItemInList (v, n)) ;
14927 explist : visitExplist (v, n, p) |
14928 funccall : visitFunccall (v, n, p) |
14929 exit : visitExit (v, n, p) |
14930 return : visitReturn (v, n, p) |
14931 stmtseq : visitStmtSeq (v, n, p) |
14933 length : visitIntrinsicFunction (v, n, p) |
14942 excl : visitIntrinsic (v, n, p) |
14943 boolean : visitBoolean (v, n, p) |
14947 varargs : visitVarargs (v, n, p) |
14972 (* language features and compound type attributes. *)
14973 type : visitType (v, n, p) |
14974 record : visitRecord (v, n, p) |
14975 varient : visitVarient (v, n, p) |
14976 var : visitVar (v, n, p) |
14977 enumeration : visitEnumeration (v, n, p) |
14978 subrange : visitSubrange (v, n, p) |
14979 pointer : visitPointer (v, n, p) |
14980 array : visitArray (v, n, p) |
14982 const : visitConst (v, n, p) |
14984 varparam : visitVarParam (v, n, p) |
14985 param : visitParam (v, n, p) |
14986 optarg : visitOptarg (v, n, p) |
14987 recordfield : visitRecordField (v, n, p) |
14988 varientfield : visitVarientField (v, n, p) |
14989 enumerationfield: visitEnumerationField (v, n, p) |
14990 set : visitSet (v, n, p) |
14991 proctype : visitProcType (v, n, p) |
14992 subscript : visitSubscript (v, n, p) |
14994 procedure : visitProcedure (v, n, p) |
14995 def : visitDef (v, n, p) |
14996 imp : visitImp (v, n, p) |
14997 module : visitModule (v, n, p) |
14999 loop : visitLoop (v, n, p) |
15000 while : visitWhile (v, n, p) |
15001 for : visitFor (v, n, p) |
15002 repeat : visitRepeat (v, n, p) |
15003 case : visitCase (v, n, p) |
15004 caselabellist : visitCaseLabelList (v, n, p) |
15005 caselist : visitCaseList (v, n, p) |
15006 range : visitRange (v, n, p) |
15007 if : visitIf (v, n, p) |
15008 elsif : visitElsif (v, n, p) |
15009 assignment : visitAssignment (v, n, p) |
15011 componentref : visitComponentRef (v, n, p) |
15012 pointerref : visitPointerRef (v, n, p) |
15013 arrayref : visitArrayRef (v, n, p) |
15031 divide : visitBinary (v, n, p) |
15032 re : visitUnary (v, n, p) |
15033 im : visitUnary (v, n, p) |
15034 abs : visitUnary (v, n, p) |
15035 chr : visitUnary (v, n, p) |
15036 cap : visitUnary (v, n, p) |
15037 high : visitUnary (v, n, p) |
15038 ord : visitUnary (v, n, p) |
15039 float : visitUnary (v, n, p) |
15040 trunc : visitUnary (v, n, p) |
15041 not : visitUnary (v, n, p) |
15042 neg : visitUnary (v, n, p) |
15043 adr : visitUnary (v, n, p) |
15044 size : visitUnary (v, n, p) |
15045 tsize : visitUnary (v, n, p) |
15046 min : visitUnary (v, n, p) |
15047 max : visitUnary (v, n, p) |
15048 constexp : visitUnary (v, n, p) |
15049 deref : visitUnary (v, n, p) |
15051 vardecl : visitVarDecl (v, n, p) |
15052 setvalue : visitSetValue (v, n, p)
15055 END visitDependants ;
15059 visitNode - visits node, n, if it is not already in the alist, v.
15060 It calls p(n) if the node is unvisited.
15063 PROCEDURE visitNode (v: alist; n: node; p: nodeProcedure) ;
15065 IF (n#NIL) AND (NOT alists.isItemInList (v, n))
15067 alists.includeItemIntoList (v, n) ;
15069 visitDependants (v, n, p)
15075 genKind - returns a string depending upon the kind of node, n.
15078 PROCEDURE genKind (n: node) : String ;
15082 (* types, no need to generate a kind string as it it contained in the name. *)
15109 shortcomplex : RETURN NIL |
15111 (* language features and compound type attributes. *)
15112 type : RETURN InitString ('type
') |
15113 record : RETURN InitString ('record
') |
15114 varient : RETURN InitString ('varient
') |
15115 var : RETURN InitString ('var
') |
15116 enumeration : RETURN InitString ('enumeration
') |
15117 subrange : RETURN InitString ('subrange
') |
15118 array : RETURN InitString ('array
') |
15119 subscript : RETURN InitString ('subscript
') |
15120 string : RETURN InitString ('string
') |
15121 const : RETURN InitString ('const
') |
15122 literal : RETURN InitString ('literal
') |
15123 varparam : RETURN InitString ('varparam
') |
15124 param : RETURN InitString ('param
') |
15125 varargs : RETURN InitString ('varargs
') |
15126 pointer : RETURN InitString ('pointer
') |
15127 recordfield : RETURN InitString ('recordfield
') |
15128 varientfield : RETURN InitString ('varientfield
') |
15129 enumerationfield: RETURN InitString ('enumerationfield
') |
15130 set : RETURN InitString ('set
') |
15131 proctype : RETURN InitString ('proctype
') |
15133 procedure : RETURN InitString ('procedure
') |
15134 def : RETURN InitString ('def
') |
15135 imp : RETURN InitString ('imp
') |
15136 module : RETURN InitString ('module
') |
15138 loop : RETURN InitString ('loop
') |
15139 while : RETURN InitString ('while
') |
15140 for : RETURN InitString ('for
') |
15141 repeat : RETURN InitString ('repeat
') |
15142 assignment : RETURN InitString ('assignment
') |
15143 if : RETURN InitString ('if
') |
15144 elsif : RETURN InitString ('elsif
') |
15146 constexp : RETURN InitString ('constexp
') |
15147 neg : RETURN InitString ('neg
') |
15148 cast : RETURN InitString ('cast
') |
15149 val : RETURN InitString ('val
') |
15150 plus : RETURN InitString ('plus
') |
15151 sub : RETURN InitString ('sub
') |
15152 div : RETURN InitString ('div
') |
15153 mod : RETURN InitString ('mod
') |
15154 mult : RETURN InitString ('mult
') |
15155 divide : RETURN InitString ('divide
') |
15156 adr : RETURN InitString ('adr
') |
15157 size : RETURN InitString ('size
') |
15158 tsize : RETURN InitString ('tsize
') |
15159 chr : RETURN InitString ('chr
') |
15160 ord : RETURN InitString ('ord
') |
15161 float : RETURN InitString ('float
') |
15162 trunc : RETURN InitString ('trunc
') |
15163 high : RETURN InitString ('high
') |
15164 componentref : RETURN InitString ('componentref
') |
15165 pointerref : RETURN InitString ('pointerref
') |
15166 arrayref : RETURN InitString ('arrayref
') |
15167 deref : RETURN InitString ('deref
') |
15168 equal : RETURN InitString ('equal
') |
15169 notequal : RETURN InitString ('notequal
') |
15170 less : RETURN InitString ('less
') |
15171 greater : RETURN InitString ('greater
') |
15172 greequal : RETURN InitString ('greequal
') |
15173 lessequal : RETURN InitString ('lessequal
') |
15174 lsl : RETURN InitString ('lsl
') |
15175 lsr : RETURN InitString ('lsr
') |
15176 lor : RETURN InitString ('lor
') |
15177 land : RETURN InitString ('land
') |
15178 lnot : RETURN InitString ('lnot
') |
15179 lxor : RETURN InitString ('lxor
') |
15180 and : RETURN InitString ('and
') |
15181 or : RETURN InitString ('or
') |
15182 not : RETURN InitString ('not
') |
15183 identlist : RETURN InitString ('identlist
') |
15184 vardecl : RETURN InitString ('vardecl
')
15192 gen - generate a small string describing node, n.
15195 PROCEDURE gen (n: node) : String ;
15200 d := VAL (CARDINAL, VAL (LONGCARD, n)) ;
15201 s := Sprintf1 (InitString ('< %d
'), d) ; (* use 0x%x once FormatStrings has been released. *)
15202 s := ConCat (s, genKind (n)) ;
15203 s := ConCat (s, InitString (' ')) ;
15204 s := ConCat (s, getFQstring (n)) ;
15205 s := ConCat (s, InitString (' >')) ;
15214 PROCEDURE dumpQ (q: ARRAY OF CHAR; l: alist) ;
15221 m := Sprintf0 (InitString ('Queue
')) ;
15222 m := KillString (WriteS (StdOut, m)) ;
15223 m := Sprintf0 (InitString (q)) ;
15224 m := KillString (WriteS (StdOut, m)) ;
15225 m := Sprintf0 (InitString ('\n')) ;
15226 m := KillString (WriteS (StdOut, m)) ;
15228 h := alists.noOfItemsInList (l) ;
15230 n := alists.getItemFromList (l, i) ;
15231 m := KillString (WriteS (StdOut, gen (n))) ;
15234 m := Sprintf0 (InitString ('\n')) ;
15235 m := KillString (WriteS (StdOut, m))
15243 PROCEDURE dumpLists ;
15245 IF getDebugTopological () AND FALSE
15247 dumpQ ('todo
', globalGroup^.todoQ) ;
15248 dumpQ ('partial
', globalGroup^.partialQ) ;
15249 dumpQ ('done
', globalGroup^.doneQ)
15258 PROCEDURE outputHidden (n: node) ;
15260 outText (doP, "#if !defined (") ; doFQNameC (doP, n) ; outText (doP, "_D)\n") ;
15261 outText (doP, "# define ") ; doFQNameC (doP, n) ; outText (doP, "_D\n") ;
15262 outText (doP, " typedef void *") ; doFQNameC (doP, n) ; outText (doP, ";\n") ;
15263 outText (doP, "#endif\n\n")
15268 outputHiddenComplete -
15271 PROCEDURE outputHiddenComplete (n: node) ;
15275 assert (isType (n)) ;
15277 assert (isPointer (t)) ;
15278 outText (doP, "#define ") ; doFQNameC (doP, n) ; outText (doP, "_D\n") ;
15279 outText (doP, "typedef ") ; doTypeNameC (doP, getType (t)) ;
15280 setNeedSpace (doP) ; outText (doP, "*") ; doFQNameC (doP, n) ; outText (doP, ";\n")
15281 END outputHiddenComplete ;
15288 PROCEDURE tryPartial (n: node; pt: nodeProcedure) : BOOLEAN ;
15291 seenPointer: BOOLEAN ;
15293 IF (n#NIL) AND isType (n)
15295 seenPointer := FALSE ;
15297 WHILE isPointer (q) DO
15298 seenPointer := TRUE ;
15303 IF isRecord (q) OR isProcType (q)
15308 ELSIF isArray (q) AND (seenPointer OR
15309 alists.isItemInList (globalGroup^.doneQ, getType (q)))
15314 ELSIF isType (q) AND seenPointer
15331 PROCEDURE tryPartial (n: node; pt: nodeProcedure) : BOOLEAN ;
15335 IF (n#NIL) AND isType (n)
15338 WHILE isPointer (q) DO
15343 IF isRecord (q) OR isProcType (q)
15361 outputPartialRecordArrayProcType -
15364 PROCEDURE outputPartialRecordArrayProcType (n, q: node; indirection: CARDINAL) ;
15368 outText (doP, "typedef struct") ; setNeedSpace (doP) ;
15369 s := getFQstring (n) ;
15372 s := ConCat (s, Mark (InitString ("_r")))
15375 s := ConCat (s, Mark (InitString ("_a")))
15376 ELSIF isProcType (q)
15378 s := ConCat (s, Mark (InitString ("_p")))
15380 outTextS (doP, s) ;
15381 setNeedSpace (doP) ;
15382 s := KillString (s) ;
15383 WHILE indirection>0 DO
15384 outText (doP, "*") ;
15387 doFQNameC (doP, n) ;
15388 outText (doP, ";\n\n")
15389 END outputPartialRecordArrayProcType ;
15396 PROCEDURE outputPartial (n: node) ;
15399 indirection: CARDINAL ;
15403 WHILE isPointer (q) DO
15407 outputPartialRecordArrayProcType (n, q, indirection)
15408 END outputPartial ;
15415 PROCEDURE tryOutputTodo (c, t, v, pt: nodeProcedure) ;
15421 n := alists.noOfItemsInList (globalGroup^.todoQ) ;
15423 d := alists.getItemFromList (globalGroup^.todoQ, i) ;
15424 IF tryComplete (d, c, t, v)
15426 alists.removeItemFromList (globalGroup^.todoQ, d) ;
15429 ELSIF tryPartial (d, pt)
15431 alists.removeItemFromList (globalGroup^.todoQ, d) ;
15432 alists.includeItemIntoList (globalGroup^.partialQ, d) ;
15437 n := alists.noOfItemsInList (globalGroup^.todoQ)
15439 END tryOutputTodo ;
15446 PROCEDURE tryOutputPartial (t: nodeProcedure) ;
15452 n := alists.noOfItemsInList (globalGroup^.partialQ) ;
15454 d := alists.getItemFromList (globalGroup^.partialQ, i) ;
15455 IF tryCompleteFromPartial (d, t)
15457 alists.removeItemFromList (globalGroup^.partialQ, d) ;
15465 END tryOutputPartial ;
15472 PROCEDURE debugList (listName, symName: ARRAY OF CHAR; l: alist) ;
15477 h := alists.noOfItemsInList (l) ;
15482 n := alists.getItemFromList (l, i) ;
15483 dbg (listName, symName, n) ;
15494 PROCEDURE debugLists ;
15496 IF getDebugTopological ()
15498 debugList ('todo
', 'decl_node
', globalGroup^.todoQ) ;
15499 debugList ('partial
', 'decl_node
', globalGroup^.partialQ) ;
15500 debugList ('done
', 'decl_node
', globalGroup^.doneQ)
15509 PROCEDURE addEnumConst (n: node) ;
15513 IF isConst (n) OR isEnumeration (n)
15524 PROCEDURE populateTodo (p: nodeProcedure) ;
15530 h := alists.noOfItemsInList (globalGroup^.todoQ) ;
15533 n := alists.getItemFromList (globalGroup^.todoQ, i) ;
15534 l := alists.initList () ;
15535 visitNode (l, n, p) ;
15536 alists.killList (l) ;
15537 h := alists.noOfItemsInList (globalGroup^.todoQ) ;
15544 topologicallyOut - keep trying to resolve the todoQ and partialQ
15545 until there is no change from the global group.
15548 PROCEDURE topologicallyOut (c, t, v, tp,
15549 pc, pt, pv: nodeProcedure) ;
15553 populateTodo (addEnumConst) ;
15556 before := dupGroup (before) ; (* Get a copy of the globalGroup and free before. *)
15558 tryOutputTodo (c, t, v, tp) ;
15560 tryOutputPartial (pt)
15561 UNTIL equalGroup (before, globalGroup) ;
15562 killGroup (before) ;
15565 END topologicallyOut ;
15572 PROCEDURE scaffoldStatic (p: pretty; n: node) ;
15574 outText (p, "\n") ;
15576 outText (p, "void") ;
15578 outText (p, "_M2_") ;
15580 outText (p, "_init") ;
15582 outText (p, "(__attribute__((unused)) int argc,") ;
15584 outText (p, "__attribute__((unused)) char *argv[],") ;
15586 outText (p, "__attribute__((unused)) char *envp[])\n");
15587 p := outKc (p, "{\n") ;
15588 doStatementsC (p, n^.impF.beginStatements) ;
15589 p := outKc (p, "}\n") ;
15590 outText (p, "\n") ;
15592 outText (p, "void") ;
15594 outText (p, "_M2_") ;
15596 outText (p, "_fini") ;
15598 outText (p, "(__attribute__((unused)) int argc,") ;
15600 outText (p, "__attribute__((unused)) char *argv[],") ;
15602 outText (p, "__attribute__((unused)) char *envp[])\n");
15603 p := outKc (p, "{\n") ;
15604 doStatementsC (p, n^.impF.finallyStatements) ;
15605 p := outKc (p, "}\n")
15606 END scaffoldStatic ;
15613 PROCEDURE emitCtor (p: pretty; n: node) ;
15617 outText (p, "\n") ;
15618 outText (p, "static void") ;
15620 outText (p, "ctorFunction ()\n") ;
15622 p := outKc (p, "{\n") ;
15623 outText (p, 'M2RTS_RegisterModule ("') ;
15624 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
15626 outText (p, '",\n') ;
15627 outText (p, 'init
, fini
, dependencies
);\n') ;
15628 p := outKc (p, "}\n\n") ;
15629 p := outKc (p, "struct ") ;
15631 p := outKc (p, "_module_m2 { ") ;
15633 p := outKc (p, "_module_m2 (); ~") ;
15635 p := outKc (p, "_module_m2 (); } global_module_") ;
15637 outText (p, ';\n\n') ;
15639 p := outKc (p, "_module_m2::") ;
15641 p := outKc (p, "_module_m2 ()\n") ;
15642 p := outKc (p, "{\n") ;
15643 outText (p, 'M2RTS_RegisterModule ("') ;
15645 outText (p, '", init
, fini
, dependencies
);') ;
15646 p := outKc (p, "}\n") ;
15648 p := outKc (p, "_module_m2::~") ;
15650 p := outKc (p, "_module_m2 ()\n") ;
15651 p := outKc (p, "{\n") ;
15652 p := outKc (p, "}\n") ;
15653 s := KillString (s)
15661 PROCEDURE scaffoldDynamic (p: pretty; n: node) ;
15663 outText (p, "\n") ;
15665 outText (p, "void") ;
15667 outText (p, "_M2_") ;
15669 outText (p, "_init") ;
15671 outText (p, "(__attribute__((unused)) int argc,") ;
15673 outText (p, "__attribute__((unused)) char *argv[],") ;
15675 outText (p, "__attribute__((unused)) char *envp[])\n") ;
15676 p := outKc (p, "{\n") ;
15677 doStatementsC (p, n^.impF.beginStatements) ;
15678 p := outKc (p, "}\n") ;
15679 outText (p, "\n") ;
15681 outText (p, "void") ;
15683 outText (p, "_M2_") ;
15685 outText (p, "_fini") ;
15687 outText (p, "(__attribute__((unused)) int argc,") ;
15689 outText (p, "__attribute__((unused)) char *argv[],") ;
15691 outText (p, "__attribute__((unused)) char *envp[])\n") ;
15692 p := outKc (p, "{\n") ;
15693 doStatementsC (p, n^.impF.finallyStatements) ;
15694 p := outKc (p, "}\n") ;
15696 END scaffoldDynamic ;
15703 PROCEDURE scaffoldMain (p: pretty; n: node) ;
15707 outText (p, "int\n") ;
15708 outText (p, "main") ;
15710 outText (p, "(int argc, char *argv[], char *envp[])\n") ;
15711 p := outKc (p, "{\n") ;
15712 outText (p, "M2RTS_ConstructModules (") ;
15713 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
15715 outText (p, ", argc, argv, envp);\n");
15716 outText (p, "M2RTS_DeconstructModules (") ;
15718 outText (p, ", argc, argv, envp);\n");
15719 outText (p, "return 0;") ;
15720 p := outKc (p, "}\n") ;
15721 s := KillString (s)
15726 outImpInitC - emit the init/fini functions and main function if required.
15729 PROCEDURE outImpInitC (p: pretty; n: node) ;
15731 IF getScaffoldDynamic ()
15733 scaffoldDynamic (p, n)
15735 scaffoldStatic (p, n)
15737 IF getScaffoldMain ()
15739 scaffoldMain (p, n)
15748 PROCEDURE runSimplifyTypes (n: node) ;
15752 simplifyTypes (n^.impF.decls)
15755 simplifyTypes (n^.moduleF.decls)
15758 simplifyTypes (n^.defF.decls)
15760 END runSimplifyTypes ;
15767 PROCEDURE outDefC (p: pretty; n: node) ;
15771 assert (isDef (n)) ;
15772 outputFile := mcStream.openFrag (1) ; (* first fragment. *)
15773 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
15774 print (p, "/* do not edit automatically generated by mc from ") ;
15775 prints (p, s) ; print (p, ". */\n") ;
15776 writeGPLheader (outputFile) ;
15777 doCommentC (p, n^.defF.com.body) ;
15778 print (p, "\n\n#if !defined (_") ; prints (p, s) ; print (p, "_H)\n") ;
15779 print (p, "# define _") ; prints (p, s) ; print (p, "_H\n\n") ;
15781 keyc.genConfigSystem (p) ;
15783 print (p, "# ifdef __cplusplus\n") ;
15784 print (p, 'extern
"C" {\n') ;
15785 print (p, "# endif\n") ;
15787 outputFile := mcStream.openFrag (3) ; (* third fragment. *)
15790 ForeachIndiceInIndexDo (n^.defF.importedModules, doIncludeC) ;
15793 print (p, "# if defined (_") ; prints (p, s) ; print (p, "_C)\n") ;
15794 print (p, "# define EXTERN\n") ;
15795 print (p, "# else\n") ;
15796 print (p, '# define EXTERN extern
\n') ;
15797 print (p, "# endif\n\n") ;
15799 outDeclsDefC (p, n) ;
15800 runPrototypeDefC (n) ;
15802 print (p, "# ifdef __cplusplus\n") ;
15804 print (p, "# endif\n") ;
15807 print (p, "# undef EXTERN\n") ;
15808 print (p, "#endif\n") ;
15810 outputFile := mcStream.openFrag (2) ; (* second fragment. *)
15813 s := KillString (s)
15818 runPrototypeExported -
15821 PROCEDURE runPrototypeExported (n: node) ;
15825 keyc.enterScope (n) ;
15826 doProcedureHeadingC (n, TRUE) ;
15827 print (doP, ";\n") ;
15828 keyc.leaveScope (n)
15830 END runPrototypeExported ;
15837 PROCEDURE runPrototypeDefC (n: node) ;
15841 ForeachIndiceInIndexDo (n^.defF.decls.procedures, runPrototypeExported)
15843 END runPrototypeDefC ;
15850 PROCEDURE outImpC (p: pretty; n: node) ;
15855 assert (isImp (n)) ;
15856 outputFile := mcStream.openFrag (1) ; (* first fragment. *)
15857 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
15858 print (p, "/* do not edit automatically generated by mc from ") ;
15859 prints (p, s) ; print (p, ". */\n") ;
15860 writeGPLheader (outputFile) ;
15861 doCommentC (p, n^.impF.com.body) ;
15862 outText (p, "\n") ;
15863 outputFile := mcStream.openFrag (3) ; (* third fragment. *)
15864 IF getExtendedOpaque ()
15867 (* ForeachIndiceInIndexDo (n^.impF.importedModules, doIncludeC) ; *)
15869 includeExternals (n) ;
15870 foreachModuleDo (n, runSimplifyTypes) ;
15871 printf ("/* --extended-opaque seen therefore no #include will be used and everything will be declared in full. */\n") ;
15872 foreachDefModuleDo (runIncludeDefConstType) ;
15873 includeDefVarProcedure (n) ;
15874 outDeclsImpC (p, n^.impF.decls) ;
15875 foreachDefModuleDo (runPrototypeDefC)
15877 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
15878 (* Inform the source that this code belongs to the implementation module. *)
15879 print (p, "#define _") ; prints (p, s) ; print (p, "_C\n\n") ;
15880 (* Include the definition module for any opaque types. *)
15881 print (doP, '#include
"') ;
15882 prints (p, getHPrefix ()) ;
15884 print (p, '.h"\n') ;
15885 s := KillString (s) ;
15888 ForeachIndiceInIndexDo (n^.impF.importedModules, doIncludeC) ;
15890 includeDefConstType (n) ;
15891 includeDefVarProcedure (n) ;
15892 outDeclsImpC (p, n^.impF.decls) ;
15894 defModule := lookupDef (getSymName (n)) ;
15897 runPrototypeDefC (defModule)
15901 ForeachIndiceInIndexDo (n^.impF.decls.procedures, doPrototypeC) ;
15903 outProceduresC (p, n^.impF.decls) ;
15904 outImpInitC (p, n) ;
15906 outputFile := mcStream.openFrag (2) ; (* second fragment. *)
15907 keyc.genConfigSystem (p) ;
15916 PROCEDURE outDeclsModuleC (p: pretty; s: scopeT) ;
15918 simplifyTypes (s) ;
15919 includeConstType (s) ;
15923 topologicallyOut (doConstC, doTypesC, doVarC,
15925 doNone, doCompletePartialC, doNone) ;
15927 (* try and output types, constants before variables and procedures. *)
15928 includeVarProcedure (s) ;
15930 topologicallyOut (doConstC, doTypesC, doVarC,
15932 doNone, doCompletePartialC, doNone) ;
15934 ForeachIndiceInIndexDo (s.procedures, doPrototypeC)
15935 END outDeclsModuleC ;
15942 PROCEDURE outModuleInitC (p: pretty; n: node) ;
15944 outText (p, "\n") ;
15946 outText (p, "void") ;
15948 outText (p, "_M2_") ;
15950 outText (p, "_init") ;
15952 outText (p, "(__attribute__((unused)) int argc") ;
15953 outText (p, ",__attribute__((unused)) char *argv[]") ;
15954 outText (p, ",__attribute__((unused)) char *envp[])\n");
15955 p := outKc (p, "{\n") ;
15956 doStatementsC (p, n^.moduleF.beginStatements) ;
15957 p := outKc (p, "}\n") ;
15958 outText (p, "\n") ;
15960 outText (p, "void") ;
15962 outText (p, "_M2_") ;
15964 outText (p, "_fini") ;
15966 outText (p, "(__attribute__((unused)) int argc") ;
15967 outText (p, ",__attribute__((unused)) char *argv[]") ;
15968 outText (p, ",__attribute__((unused)) char *envp[])\n");
15969 p := outKc (p, "{\n") ;
15970 doStatementsC (p, n^.moduleF.finallyStatements) ;
15971 p := outKc (p, "}\n")
15972 END outModuleInitC ;
15979 PROCEDURE outModuleC (p: pretty; n: node) ;
15983 assert (isModule (n)) ;
15984 outputFile := mcStream.openFrag (1) ; (* first fragment. *)
15985 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
15986 print (p, "/* do not edit automatically generated by mc from ") ;
15987 prints (p, s) ; print (p, ". */\n") ;
15988 writeGPLheader (outputFile) ;
15989 doCommentC (p, n^.moduleF.com.body) ;
15990 outText (p, "\n") ;
15991 outputFile := mcStream.openFrag (3) ; (* third fragment. *)
15992 IF getExtendedOpaque ()
15995 includeExternals (n) ;
15996 foreachModuleDo (n, runSimplifyTypes) ;
15997 printf ("/* --extended-opaque seen therefore no #include will be used and everything will be declared in full. */\n") ;
15998 foreachDefModuleDo (runIncludeDefConstType) ;
15999 outDeclsModuleC (p, n^.moduleF.decls) ;
16000 foreachDefModuleDo (runPrototypeDefC)
16003 ForeachIndiceInIndexDo (n^.moduleF.importedModules, doIncludeC) ;
16005 outDeclsModuleC (p, n^.moduleF.decls)
16008 ForeachIndiceInIndexDo (n^.moduleF.decls.procedures, doPrototypeC) ;
16010 outProceduresC (p, n^.moduleF.decls) ;
16011 outModuleInitC (p, n) ;
16013 outputFile := mcStream.openFrag (2) ; (* second fragment. *)
16014 keyc.genConfigSystem (p) ;
16023 PROCEDURE outC (p: pretty; n: node) ;
16025 keyc.enterScope (n) ;
16038 keyc.leaveScope (n)
16043 doIncludeM2 - include modules in module, n.
16046 PROCEDURE doIncludeM2 (n: node) ;
16050 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
16051 print (doP, 'IMPORT ') ;
16053 print (doP, ' ;\n') ;
16054 s := KillString (s) ;
16058 foreachNodeDo (n^.defF.decls.symbols, addDone)
16061 foreachNodeDo (n^.impF.decls.symbols, addDone)
16064 foreachNodeDo (n^.moduleF.decls.symbols, addDone)
16073 PROCEDURE doConstM2 (n: node) ;
16075 print (doP, "CONST\n") ;
16076 doFQNameC (doP, n) ;
16077 setNeedSpace (doP) ;
16078 doExprC (doP, n^.constF.value) ;
16087 PROCEDURE doProcTypeM2 (p: pretty; n: node) ;
16089 outText (p, "proc type to do..")
16097 PROCEDURE doRecordFieldM2 (p: pretty; f: node) ;
16102 doTypeM2 (p, getType (f)) ;
16104 END doRecordFieldM2 ;
16111 PROCEDURE doVarientFieldM2 (p: pretty; n: node) ;
16116 assert (isVarientField (n)) ;
16120 i := LowIndice (n^.varientfieldF.listOfSons) ;
16121 t := HighIndice (n^.varientfieldF.listOfSons) ;
16123 q := GetIndice (n^.varientfieldF.listOfSons, i) ;
16124 IF isRecordField (q)
16126 doRecordFieldM2 (p, q) ;
16128 ELSIF isVarient (q)
16130 doVarientM2 (p, q) ;
16137 END doVarientFieldM2 ;
16144 PROCEDURE doVarientM2 (p: pretty; n: node) ;
16149 assert (isVarient (n)) ;
16150 outText (p, "CASE") ; setNeedSpace (p) ;
16151 IF n^.varientF.tag # NIL
16153 IF isRecordField (n^.varientF.tag)
16155 doRecordFieldM2 (p, n^.varientF.tag)
16156 ELSIF isVarientField (n^.varientF.tag)
16158 doVarientFieldM2 (p, n^.varientF.tag)
16164 outText (p, "OF\n") ;
16165 i := LowIndice (n^.varientF.listOfSons) ;
16166 t := HighIndice (n^.varientF.listOfSons) ;
16168 q := GetIndice (n^.varientF.listOfSons, i) ;
16169 IF isRecordField (q)
16171 IF NOT q^.recordfieldF.tag
16173 doRecordFieldM2 (p, q) ;
16176 ELSIF isVarientField (q)
16178 doVarientFieldM2 (p, q)
16184 outText (p, "END") ; setNeedSpace (p)
16192 PROCEDURE doRecordM2 (p: pretty; n: node) ;
16197 assert (isRecord (n)) ;
16198 p := outKm2 (p, "RECORD") ;
16199 i := LowIndice (n^.recordF.listOfSons) ;
16200 h := HighIndice (n^.recordF.listOfSons) ;
16201 outText (p, "\n") ;
16203 f := GetIndice (n^.recordF.listOfSons, i) ;
16204 IF isRecordField (f)
16206 IF NOT f^.recordfieldF.tag
16208 doRecordFieldM2 (p, f) ;
16211 ELSIF isVarient (f)
16213 doVarientM2 (p, f) ;
16215 ELSIF isVarientField (f)
16217 doVarientFieldM2 (p, f)
16221 p := outKm2 (p, "END") ; setNeedSpace (p)
16229 PROCEDURE doPointerM2 (p: pretty; n: node) ;
16231 outText (p, "POINTER TO") ;
16232 setNeedSpace (doP) ;
16233 doTypeM2 (p, getType (n)) ;
16243 PROCEDURE doTypeAliasM2 (p: pretty; n: node) ;
16245 doTypeNameC (p, n) ;
16247 outText (doP, "=") ;
16249 doTypeM2 (p, getType (n)) ;
16252 END doTypeAliasM2 ;
16259 PROCEDURE doEnumerationM2 (p: pretty; n: node) ;
16266 i := LowIndice (n^.enumerationF.listOfSons) ;
16267 h := HighIndice (n^.enumerationF.listOfSons) ;
16269 s := GetIndice (n^.enumerationF.listOfSons, i) ;
16273 outText (p, ",") ; setNeedSpace (p)
16278 END doEnumerationM2 ;
16285 PROCEDURE doBaseM2 (p: pretty; n: node) ;
16304 proc : doNameM2 (p, n)
16315 PROCEDURE doSystemM2 (p: pretty; n: node) ;
16324 cssizet: doNameM2 (p, n)
16334 PROCEDURE doTypeM2 (p: pretty; n: node) ;
16344 doTypeAliasM2 (p, n)
16345 ELSIF isProcType (n)
16347 doProcTypeM2 (p, n)
16348 ELSIF isPointer (n)
16351 ELSIF isEnumeration (n)
16353 doEnumerationM2 (p, n)
16365 PROCEDURE doTypesM2 (n: node) ;
16369 outText (doP, "TYPE\n") ;
16378 PROCEDURE doVarM2 (n: node) ;
16380 assert (isVar (n)) ;
16382 outText (doP, ":") ;
16383 setNeedSpace (doP) ;
16384 doTypeM2 (doP, getType (n)) ;
16385 setNeedSpace (doP) ;
16386 outText (doP, ";\n")
16394 PROCEDURE doVarsM2 (n: node) ;
16398 outText (doP, "VAR\n") ;
16407 PROCEDURE doTypeNameM2 (p: pretty; n: node) ;
16417 PROCEDURE doParamM2 (p: pretty; n: node) ;
16424 assert (isParam (n)) ;
16425 ptype := getType (n) ;
16426 IF n^.paramF.namelist = NIL
16428 doTypeNameM2 (p, ptype)
16430 assert (isIdentList (n^.paramF.namelist)) ;
16431 l := n^.paramF.namelist^.identlistF.names ;
16434 doTypeNameM2 (p, ptype)
16436 t := wlists.noOfItemsInList (l) ;
16439 i := wlists.getItemFromList (l, c) ;
16444 outText (p, ',') ; setNeedSpace (p)
16448 outText (p, ':') ; setNeedSpace (p) ;
16449 doTypeNameM2 (p, ptype)
16459 PROCEDURE doVarParamM2 (p: pretty; n: node) ;
16466 assert (isVarParam (n)) ;
16467 outText (p, 'VAR') ; setNeedSpace (p) ;
16468 ptype := getType (n) ;
16469 IF n^.varparamF.namelist = NIL
16471 doTypeNameM2 (p, ptype)
16473 assert (isIdentList (n^.varparamF.namelist)) ;
16474 l := n^.varparamF.namelist^.identlistF.names ;
16477 doTypeNameM2 (p, ptype)
16479 t := wlists.noOfItemsInList (l) ;
16482 i := wlists.getItemFromList (l, c) ;
16487 outText (p, ',') ; setNeedSpace (p)
16491 outText (p, ':') ; setNeedSpace (p) ;
16492 doTypeNameM2 (p, ptype)
16502 PROCEDURE doParameterM2 (p: pretty; n: node) ;
16507 ELSIF isVarParam (n)
16509 doVarParamM2 (p, n)
16510 ELSIF isVarargs (n)
16514 END doParameterM2 ;
16521 PROCEDURE doPrototypeM2 (n: node) ;
16526 assert (isProcedure (n)) ;
16529 doNameM2 (doP, n) ;
16530 setNeedSpace (doP) ;
16531 outText (doP, "(") ;
16532 i := LowIndice (n^.procedureF.parameters) ;
16533 h := HighIndice (n^.procedureF.parameters) ;
16535 p := GetIndice (n^.procedureF.parameters, i) ;
16536 doParameterM2 (doP, p) ;
16540 print (doP, ";") ; setNeedSpace (doP)
16544 outText (doP, ")") ;
16545 IF n^.procedureF.returnType#NIL
16547 setNeedSpace (doP) ;
16548 outText (doP, ":") ;
16549 doTypeM2 (doP, n^.procedureF.returnType) ; setNeedSpace (doP)
16551 outText (doP, ";\n")
16552 END doPrototypeM2 ;
16556 outputPartialM2 - just writes out record, array, and proctypes.
16557 No need for forward declarations in Modula-2
16558 but we need to keep topological sort happy.
16559 So when asked to output partial we emit the
16560 full type for these types and then do nothing
16561 when trying to complete partial to full.
16564 PROCEDURE outputPartialM2 (n: node) ;
16575 ELSIF isProcType (q)
16579 END outputPartialM2 ;
16586 PROCEDURE outDeclsDefM2 (p: pretty; s: scopeT) ;
16588 simplifyTypes (s) ;
16589 includeConstType (s) ;
16593 topologicallyOut (doConstM2, doTypesM2, doVarsM2,
16595 doNothing, doNothing, doNothing) ;
16597 includeVarProcedure (s) ;
16599 topologicallyOut (doConstM2, doTypesM2, doVarsM2,
16601 doNothing, doNothing, doNothing) ;
16603 ForeachIndiceInIndexDo (s.procedures, doPrototypeM2)
16604 END outDeclsDefM2 ;
16611 PROCEDURE outDefM2 (p: pretty; n: node) ;
16615 s := InitStringCharStar (keyToCharStar (getSource (n))) ;
16616 print (p, "(* automatically created by mc from ") ; prints (p, s) ; print (p, ". *)\n\n") ;
16617 s := KillString (s) ;
16618 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
16619 print (p, "DEFINITION MODULE ") ; prints (p, s) ; print (p, " ;\n\n") ;
16622 ForeachIndiceInIndexDo (n^.defF.importedModules, doIncludeM2) ;
16626 outDeclsDefM2 (p, n^.defF.decls) ;
16629 print (p, "END ") ;
16632 s := KillString (s)
16640 PROCEDURE outDeclsImpM2 (p: pretty; s: scopeT) ;
16642 simplifyTypes (s) ;
16643 includeConstType (s) ;
16647 topologicallyOut (doConstM2, doTypesM2, doVarM2,
16649 doNothing, doNothing, doNothing) ;
16651 includeVarProcedure (s) ;
16653 topologicallyOut (doConstM2, doTypesM2, doVarsM2,
16655 doNothing, doNothing, doNothing) ;
16657 outText (p, "\n") ;
16658 ForeachIndiceInIndexDo (s.procedures, doPrototypeC)
16659 END outDeclsImpM2 ;
16666 PROCEDURE outImpM2 (p: pretty; n: node) ;
16670 s := InitStringCharStar (keyToCharStar (getSource (n))) ;
16671 print (p, "(* automatically created by mc from ") ; prints (p, s) ; print (p, ". *)\n\n") ;
16672 print (p, "IMPLEMENTATION MODULE ") ; prints (p, s) ; print (p, " ;\n\n") ;
16675 ForeachIndiceInIndexDo (n^.impF.importedModules, doIncludeM2) ;
16678 includeDefConstType (n) ;
16679 outDeclsImpM2 (p, n^.impF.decls) ;
16682 print (p, "END ") ;
16686 s := KillString (s)
16694 PROCEDURE outModuleM2 (p: pretty; n: node) ;
16704 PROCEDURE outM2 (p: pretty; n: node) ;
16722 out - walks the tree of node declarations for the main module
16723 and writes the output to the outputFile specified in
16724 mcOptions. It outputs the declarations in the language
16733 p := initPretty (write, writeln) ;
16736 ansiC : outC (p, getMainModule ()) |
16737 ansiCP: outC (p, getMainModule ()) |
16738 pim4 : outM2 (p, getMainModule ())
16749 PROCEDURE setLangC ;
16759 PROCEDURE setLangCP ;
16770 PROCEDURE setLangM2 ;
16777 addDone - adds node, n, to the doneQ.
16780 PROCEDURE addDone (n: node) ;
16784 alists.includeItemIntoList (globalGroup^.doneQ, n) ;
16785 IF isVar (n) OR isParameter (n)
16787 initNodeOpaqueState (n)
16794 addDoneDef - adds node, n, to the doneQ providing
16795 it is not an opaque of the main module we are compiling.
16798 PROCEDURE addDoneDef (n: node) ;
16805 IF FALSE AND (lookupImp (getSymName (getScope (n))) = getMainModule ())
16807 metaError1 ('cyclic dependancy found between another module using
{%1ad
} from the definition module of the implementation main being compiled
, use the
--extended
-opaque option to compile
', n) ;
16809 errorAbort0 ('terminating compilation
')
16810 ELSIF isType (n) AND isDeclInImp (n)
16812 (* Ignore an opaque type which is declared in this implementation module as it
16813 will be fully declared in C/C++ with the __opaque postfix. Whereas the
16814 void * non prefixed typedef will be declared in the .h file. *)
16825 PROCEDURE dbgAdd (l: alist; n: node) : node ;
16829 alists.includeItemIntoList (l, n)
16839 PROCEDURE dbgType (l: alist; n: node) ;
16843 t := dbgAdd (l, getType (n)) ;
16844 out1 ("<%s type", n) ;
16847 out0 (", type = NIL\n")
16849 out1 (", type = %s>\n", t)
16858 PROCEDURE dbgPointer (l: alist; n: node) ;
16862 t := dbgAdd (l, getType (n)) ;
16863 out1 ("<%s pointer", n) ;
16864 out1 (" to %s>\n", t)
16872 PROCEDURE dbgRecord (l: alist; n: node) ;
16877 out1 ("<%s record:\n", n) ;
16878 i := LowIndice (n^.recordF.listOfSons) ;
16879 t := HighIndice (n^.recordF.listOfSons) ;
16881 q := GetIndice (n^.recordF.listOfSons, i) ;
16882 IF isRecordField (q)
16884 out1 (" <recordfield %s", q)
16885 ELSIF isVarientField (q)
16887 out1 (" <varientfield %s", q)
16888 ELSIF isVarient (q)
16890 out1 (" <varient %s", q)
16894 q := dbgAdd (l, getType (q)) ;
16895 out1 (": %s>\n", q) ;
16898 outText (doP, ">\n")
16906 PROCEDURE dbgVarient (l: alist; n: node) ;
16911 out1 ("<%s varient: ", n) ;
16912 out1 ("tag %s", n^.varientF.tag) ;
16913 q := getType (n^.varientF.tag) ;
16916 outText (doP, "\n")
16918 out1 (": %s\n", q) ;
16921 i := LowIndice (n^.varientF.listOfSons) ;
16922 t := HighIndice (n^.varientF.listOfSons) ;
16924 q := GetIndice (n^.varientF.listOfSons, i) ;
16925 IF isRecordField (q)
16927 out1 (" <recordfield %s", q)
16928 ELSIF isVarientField (q)
16930 out1 (" <varientfield %s", q)
16931 ELSIF isVarient (q)
16933 out1 (" <varient %s", q)
16937 q := dbgAdd (l, getType (q)) ;
16938 out1 (": %s>\n", q) ;
16941 outText (doP, ">\n")
16949 PROCEDURE dbgEnumeration (l: alist; n: node) ;
16954 outText (doP, "< enumeration ") ;
16955 i := LowIndice (n^.enumerationF.listOfSons) ;
16956 h := HighIndice (n^.enumerationF.listOfSons) ;
16958 e := GetIndice (n^.enumerationF.listOfSons, i) ;
16962 outText (doP, ">\n")
16963 END dbgEnumeration ;
16970 PROCEDURE dbgVar (l: alist; n: node) ;
16974 t := dbgAdd (l, getType (n)) ;
16975 out1 ("<%s var", n) ;
16976 out1 (", type = %s>\n", t)
16984 PROCEDURE dbgSubrange (l: alist; n: node) ;
16986 IF n^.subrangeF.low = NIL
16988 out1 ('%s
', n^.subrangeF.type)
16990 out1 ('[%s
', n^.subrangeF.low) ;
16991 out1 ('..
%s
]', n^.subrangeF.high)
17000 PROCEDURE dbgArray (l: alist; n: node) ;
17004 t := dbgAdd (l, getType (n)) ;
17005 out1 ("<%s array ", n) ;
17006 IF n^.arrayF.subr # NIL
17008 dbgSubrange (l, n^.arrayF.subr)
17010 out1 (" of %s>\n", t)
17018 PROCEDURE doDbg (l: alist; n: node) ;
17023 ELSIF isSubrange (n)
17032 ELSIF isVarient (n)
17035 ELSIF isEnumeration (n)
17037 dbgEnumeration (l, n)
17038 ELSIF isPointer (n)
17055 PROCEDURE dbg (listName, symName: ARRAY OF CHAR; n: node) ;
17065 outputFile := StdOut ;
17066 doP := initPretty (write, writeln) ;
17068 l := alists.initList () ;
17069 alists.includeItemIntoList (l, n) ;
17072 n := alists.getItemFromList (l, i) ;
17075 s := getFQstring (n) ;
17076 IF EqualArray (s, symName)
17083 s := KillString (s)
17086 UNTIL i>alists.noOfItemsInList (l) ;
17093 makeStatementSequence - create and return a statement sequence node.
17096 PROCEDURE makeStatementSequence () : node ;
17100 n := newNode (stmtseq) ;
17101 n^.stmtF.statements := InitIndex (1) ;
17103 END makeStatementSequence ;
17107 addStatement - adds node, n, as a statement to statememt sequence, s.
17110 PROCEDURE addStatement (s: node; n: node) ;
17114 assert (isStatementSequence (s)) ;
17115 PutIndice (s^.stmtF.statements, HighIndice (s^.stmtF.statements) + 1, n) ;
17116 IF isIntrinsic (n) AND (n^.intrinsicF.postUnreachable)
17118 n^.intrinsicF.postUnreachable := FALSE ;
17119 addStatement (s, makeIntrinsicProc (unreachable, 0, NIL))
17126 isStatementSequence - returns TRUE if node, n, is a statement sequence.
17129 PROCEDURE isStatementSequence (n: node) : BOOLEAN ;
17131 RETURN n^.kind = stmtseq
17132 END isStatementSequence ;
17136 addGenericBody - adds comment node to funccall, return, assignment
17140 PROCEDURE addGenericBody (n, c: node);
17152 excl : n^.intrinsicF.intrinsicComment.body := c |
17153 funccall : n^.funccallF.funccallComment.body := c |
17154 return : n^.returnF.returnComment.body := c |
17155 assignment: n^.assignmentF.assignComment.body := c |
17156 module : n^.moduleF.com.body := c |
17157 def : n^.defF.com.body := c |
17158 imp : n^.impF.com.body := c
17162 END addGenericBody;
17166 addGenericAfter - adds comment node to funccall, return, assignment
17170 PROCEDURE addGenericAfter (n, c: node);
17182 excl : n^.intrinsicF.intrinsicComment.after := c |
17183 funccall : n^.funccallF.funccallComment.after := c |
17184 return : n^.returnF.returnComment.after := c |
17185 assignment: n^.assignmentF.assignComment.after := c |
17186 module : n^.moduleF.com.after := c |
17187 def : n^.defF.com.after := c |
17188 imp : n^.impF.com.after := c
17192 END addGenericAfter ;
17196 addCommentBody - adds a body comment to a statement sequence node.
17199 PROCEDURE addCommentBody (n: node) ;
17205 b := getBodyComment () ;
17208 addGenericBody (n, makeCommentS (b))
17211 END addCommentBody ;
17215 addCommentAfter - adds an after comment to a statement sequence node.
17218 PROCEDURE addCommentAfter (n: node) ;
17224 a := getAfterComment () ;
17227 addGenericAfter (n, makeCommentS (a))
17230 END addCommentAfter ;
17234 addIfComments - adds the, body, and, after, comments to if node, n.
17237 PROCEDURE addIfComments (n: node; body, after: node) ;
17239 assert (isIf (n)) ;
17240 n^.ifF.ifComment.after := after ;
17241 n^.ifF.ifComment.body := body
17242 END addIfComments ;
17246 addElseComments - adds the, body, and, after, comments to an, if, or an elsif, node, n.
17249 PROCEDURE addElseComments (n: node; body, after: node) ;
17251 assert (isIf (n) OR isElsif (n)) ;
17254 n^.ifF.elseComment.after := after ;
17255 n^.ifF.elseComment.body := body
17257 n^.elsifF.elseComment.after := after ;
17258 n^.elsifF.elseComment.body := body
17260 END addElseComments ;
17264 addIfEndComments - adds the, body, and, after, comments to an, if, node, n.
17267 PROCEDURE addIfEndComments (n: node; body, after: node) ;
17269 assert (isIf (n)) ;
17270 n^.ifF.endComment.after := after ;
17271 n^.ifF.endComment.body := body
17272 END addIfEndComments ;
17276 makeReturn - creates and returns a return node.
17279 PROCEDURE makeReturn () : node ;
17284 n := newNode (return) ;
17285 n^.returnF.exp := NIL ;
17286 IF isProcedure (getDeclScope ())
17288 n^.returnF.scope := getDeclScope ()
17290 n^.returnF.scope := NIL
17292 initPair (n^.returnF.returnComment) ;
17298 isReturn - returns TRUE if node, n, is a return.
17301 PROCEDURE isReturn (n: node) : BOOLEAN ;
17304 RETURN n^.kind = return
17309 putReturn - assigns node, e, as the expression on the return node.
17312 PROCEDURE putReturn (n: node; e: node) ;
17314 assert (isReturn (n)) ;
17315 n^.returnF.exp := e
17320 makeWhile - creates and returns a while node.
17323 PROCEDURE makeWhile () : node ;
17327 n := newNode (while) ;
17328 n^.whileF.expr := NIL ;
17329 n^.whileF.statements := NIL ;
17330 initPair (n^.whileF.doComment) ;
17331 initPair (n^.whileF.endComment) ;
17337 putWhile - places an expression, e, and statement sequence, s, into the while
17341 PROCEDURE putWhile (n: node; e, s: node) ;
17343 assert (isWhile (n)) ;
17344 n^.whileF.expr := e ;
17345 n^.whileF.statements := s
17350 isWhile - returns TRUE if node, n, is a while.
17353 PROCEDURE isWhile (n: node) : BOOLEAN ;
17355 RETURN n^.kind = while
17360 addWhileDoComment - adds body and after comments to while node, w.
17363 PROCEDURE addWhileDoComment (w: node; body, after: node) ;
17365 assert (isWhile (w)) ;
17366 w^.whileF.doComment.after := after ;
17367 w^.whileF.doComment.body := body
17368 END addWhileDoComment ;
17372 addWhileEndComment - adds body and after comments to the end of a while node, w.
17375 PROCEDURE addWhileEndComment (w: node; body, after: node) ;
17377 assert (isWhile (w)) ;
17378 w^.whileF.endComment.after := after ;
17379 w^.whileF.endComment.body := body
17380 END addWhileEndComment ;
17384 makeAssignment - creates and returns an assignment node.
17385 The designator is, d, and expression, e.
17388 PROCEDURE makeAssignment (d, e: node) : node ;
17392 n := newNode (assignment) ;
17393 n^.assignmentF.des := d ;
17394 n^.assignmentF.expr := e ;
17395 initPair (n^.assignmentF.assignComment) ;
17397 END makeAssignment ;
17404 PROCEDURE isAssignment (n: node) : BOOLEAN ;
17406 RETURN n^.kind = assignment
17411 putBegin - assigns statements, s, to be the normal part in
17412 block, b. The block may be a procedure or module,
17413 or implementation node.
17416 PROCEDURE putBegin (b: node; s: node) ;
17418 assert (isImp (b) OR isProcedure (b) OR isModule (b)) ;
17421 imp : b^.impF.beginStatements := s |
17422 module : b^.moduleF.beginStatements := s |
17423 procedure: b^.procedureF.beginStatements := s
17430 putFinally - assigns statements, s, to be the final part in
17431 block, b. The block may be a module
17432 or implementation node.
17435 PROCEDURE putFinally (b: node; s: node) ;
17437 assert (isImp (b) OR isProcedure (b) OR isModule (b)) ;
17440 imp : b^.impF.finallyStatements := s |
17441 module : b^.moduleF.finallyStatements := s
17448 makeExit - creates and returns an exit node.
17451 PROCEDURE makeExit (l: node; n: CARDINAL) : node ;
17455 assert (isLoop (l)) ;
17456 e := newNode (exit) ;
17457 e^.exitF.loop := l ;
17458 l^.loopF.labelno := n ;
17464 isExit - returns TRUE if node, n, is an exit.
17467 PROCEDURE isExit (n: node) : BOOLEAN ;
17470 RETURN n^.kind = exit
17475 makeLoop - creates and returns a loop node.
17478 PROCEDURE makeLoop () : node ;
17482 l := newNode (loop) ;
17483 l^.loopF.statements := NIL ;
17484 l^.loopF.labelno := 0 ;
17490 putLoop - places statement sequence, s, into loop, l.
17493 PROCEDURE putLoop (l, s: node) ;
17495 assert (isLoop (l)) ;
17496 l^.loopF.statements := s
17501 isLoop - returns TRUE if, n, is a loop node.
17504 PROCEDURE isLoop (n: node) : BOOLEAN ;
17507 RETURN n^.kind = loop
17512 makeComment - creates and returns a comment node.
17515 PROCEDURE makeComment (a: ARRAY OF CHAR) : node ;
17520 c := initComment (TRUE) ;
17521 s := InitString (a) ;
17522 addText (c, DynamicStrings.string (s)) ;
17523 s := KillString (s) ;
17524 RETURN makeCommentS (c)
17529 makeCommentS - creates and returns a comment node.
17532 PROCEDURE makeCommentS (c: commentDesc) : node ;
17540 n := newNode (comment) ;
17541 n^.commentF.content := c ;
17548 isComment - returns TRUE if node, n, is a comment.
17551 PROCEDURE isComment (n: node) : BOOLEAN ;
17554 RETURN n^.kind = comment
17559 initPair - initialise the commentPair, c.
17562 PROCEDURE initPair (VAR c: commentPair) ;
17570 makeIf - creates and returns an if node. The if node
17571 will have expression, e, and statement sequence, s,
17572 as the then component.
17575 PROCEDURE makeIf (e, s: node) : node ;
17579 n := newNode (if) ;
17582 n^.ifF.else := NIL ;
17583 n^.ifF.elsif := NIL ;
17584 initPair (n^.ifF.ifComment) ;
17585 initPair (n^.ifF.elseComment) ;
17586 initPair (n^.ifF.endComment) ;
17592 isIf - returns TRUE if, n, is an if node.
17595 PROCEDURE isIf (n: node) : BOOLEAN ;
17597 RETURN n^.kind = if
17602 makeElsif - creates and returns an elsif node.
17603 This node has an expression, e, and statement
17607 PROCEDURE makeElsif (i, e, s: node) : node ;
17611 n := newNode (elsif) ;
17612 n^.elsifF.expr := e ;
17613 n^.elsifF.then := s ;
17614 n^.elsifF.elsif := NIL ;
17615 n^.elsifF.else := NIL ;
17616 initPair (n^.elsifF.elseComment) ;
17617 assert (isIf (i) OR isElsif (i)) ;
17620 i^.ifF.elsif := n ;
17621 assert (i^.ifF.else = NIL)
17623 i^.elsifF.elsif := n ;
17624 assert (i^.elsifF.else = NIL)
17631 isElsif - returns TRUE if node, n, is an elsif node.
17634 PROCEDURE isElsif (n: node) : BOOLEAN ;
17636 RETURN n^.kind = elsif
17641 putElse - the else is grafted onto the if/elsif node, i,
17642 and the statement sequence will be, s.
17645 PROCEDURE putElse (i, s: node) ;
17647 assert (isIf (i) OR isElsif (i)) ;
17650 assert (i^.ifF.elsif = NIL) ;
17651 assert (i^.ifF.else = NIL) ;
17654 assert (i^.elsifF.elsif = NIL) ;
17655 assert (i^.elsifF.else = NIL) ;
17656 i^.elsifF.else := s
17662 makeFor - creates and returns a for node.
17665 PROCEDURE makeFor () : node ;
17669 n := newNode (for) ;
17670 n^.forF.des := NIL ;
17671 n^.forF.start := NIL ;
17672 n^.forF.end := NIL ;
17673 n^.forF.increment := NIL ;
17674 n^.forF.statements := NIL ;
17680 isFor - returns TRUE if node, n, is a for node.
17683 PROCEDURE isFor (n: node) : BOOLEAN ;
17686 RETURN n^.kind = for
17691 putFor - assigns the fields of the for node with
17699 PROCEDURE putFor (f, i, s, e, b, sq: node) ;
17701 assert (isFor (f)) ;
17703 f^.forF.start := s ;
17705 f^.forF.increment := b ;
17706 f^.forF.statements := sq
17711 makeRepeat - creates and returns a repeat node.
17714 PROCEDURE makeRepeat () : node ;
17718 n := newNode (repeat) ;
17719 n^.repeatF.expr := NIL ;
17720 n^.repeatF.statements := NIL ;
17721 initPair (n^.repeatF.repeatComment) ;
17722 initPair (n^.repeatF.untilComment) ;
17728 isRepeat - returns TRUE if node, n, is a repeat node.
17731 PROCEDURE isRepeat (n: node) : BOOLEAN ;
17734 RETURN n^.kind = repeat
17739 putRepeat - places statements, s, and expression, e, into
17740 repeat statement, n.
17743 PROCEDURE putRepeat (n, s, e: node) ;
17745 n^.repeatF.expr := e ;
17746 n^.repeatF.statements := s
17751 addRepeatComment - adds body and after comments to repeat node, r.
17754 PROCEDURE addRepeatComment (r: node; body, after: node) ;
17756 assert (isRepeat (r)) ;
17757 r^.repeatF.repeatComment.after := after ;
17758 r^.repeatF.repeatComment.body := body
17759 END addRepeatComment ;
17763 addUntilComment - adds body and after comments to the until section of a repeat node, r.
17766 PROCEDURE addUntilComment (r: node; body, after: node) ;
17768 assert (isRepeat (r)) ;
17769 r^.repeatF.untilComment.after := after ;
17770 r^.repeatF.untilComment.body := body
17771 END addUntilComment ;
17775 makeCase - builds and returns a case statement node.
17778 PROCEDURE makeCase () : node ;
17782 n := newNode (case) ;
17783 n^.caseF.expression := NIL ;
17784 n^.caseF.caseLabelList := InitIndex (1) ;
17785 n^.caseF.else := NIL ;
17791 isCase - returns TRUE if node, n, is a case statement.
17794 PROCEDURE isCase (n: node) : BOOLEAN ;
17797 RETURN n^.kind = case
17802 putCaseExpression - places expression, e, into case statement, n.
17806 PROCEDURE putCaseExpression (n: node; e: node) : node ;
17808 assert (isCase (n)) ;
17809 n^.caseF.expression := e ;
17811 END putCaseExpression ;
17815 putCaseElse - places else statement, e, into case statement, n.
17819 PROCEDURE putCaseElse (n: node; e: node) : node ;
17821 assert (isCase (n)) ;
17822 n^.caseF.else := e ;
17828 putCaseStatement - places a caselist, l, and associated
17829 statement sequence, s, into case statement, n.
17833 PROCEDURE putCaseStatement (n: node; l: node; s: node) : node ;
17835 assert (isCase (n)) ;
17836 assert (isCaseList (l)) ;
17837 IncludeIndiceIntoIndex (n^.caseF.caseLabelList, makeCaseLabelList (l, s)) ;
17839 END putCaseStatement ;
17843 makeCaseLabelList - creates and returns a caselabellist node.
17846 PROCEDURE makeCaseLabelList (l, s: node) : node ;
17850 n := newNode (caselabellist) ;
17851 n^.caselabellistF.caseList := l ;
17852 n^.caselabellistF.statements := s ;
17854 END makeCaseLabelList ;
17858 isCaseLabelList - returns TRUE if, n, is a caselabellist.
17861 PROCEDURE isCaseLabelList (n: node) : BOOLEAN ;
17864 RETURN n^.kind = caselabellist
17865 END isCaseLabelList ;
17869 makeCaseList - creates and returns a case statement node.
17872 PROCEDURE makeCaseList () : node ;
17876 n := newNode (caselist) ;
17877 n^.caselistF.rangePairs := InitIndex (1) ;
17883 isCaseList - returns TRUE if, n, is a case list.
17886 PROCEDURE isCaseList (n: node) : BOOLEAN ;
17889 RETURN n^.kind = caselist
17894 putCaseRange - places the case range lo..hi into caselist, n.
17897 PROCEDURE putCaseRange (n: node; lo, hi: node) : node ;
17899 assert (isCaseList (n)) ;
17900 IncludeIndiceIntoIndex (n^.caselistF.rangePairs, makeRange (lo, hi)) ;
17906 makeRange - creates and returns a case range.
17909 PROCEDURE makeRange (lo, hi: node) : node ;
17913 n := newNode (range) ;
17914 n^.rangeF.lo := lo ;
17915 n^.rangeF.hi := hi ;
17921 isRange - returns TRUE if node, n, is a range.
17924 PROCEDURE isRange (n: node) : BOOLEAN ;
17927 RETURN n^.kind = range
17935 PROCEDURE dupExplist (n: node) : node ;
17940 assert (isExpList (n)) ;
17941 m := makeExpList () ;
17942 i := LowIndice (n^.explistF.exp) ;
17943 WHILE i <= HighIndice (n^.explistF.exp) DO
17944 putExpList (m, dupExpr (GetIndice (n^.explistF.exp, i))) ;
17955 PROCEDURE dupArrayref (n: node) : node ;
17957 assert (isArrayRef (n)) ;
17958 RETURN makeArrayRef (dupExpr (n^.arrayrefF.array), dupExpr (n^.arrayrefF.index))
17966 PROCEDURE dupPointerref (n: node) : node ;
17968 assert (isPointerRef (n)) ;
17969 RETURN makePointerRef (dupExpr (n^.pointerrefF.ptr), dupExpr (n^.pointerrefF.field))
17970 END dupPointerref ;
17977 PROCEDURE dupComponentref (n: node) : node ;
17979 assert (isComponentRef (n)) ;
17980 RETURN doMakeComponentRef (dupExpr (n^.componentrefF.rec), dupExpr (n^.componentrefF.field))
17981 END dupComponentref ;
17988 PROCEDURE dupBinary (n: node) : node ;
17990 (* assert (isBinary (n)) ; *)
17991 RETURN makeBinary (n^.kind,
17992 dupExpr (n^.binaryF.left), dupExpr (n^.binaryF.right),
17993 n^.binaryF.resultType)
18001 PROCEDURE dupUnary (n: node) : node ;
18003 (* assert (isUnary (n)) ; *)
18004 RETURN makeUnary (n^.kind, dupExpr (n^.unaryF.arg), n^.unaryF.resultType)
18012 PROCEDURE dupFunccall (n: node) : node ;
18016 assert (isFuncCall (n)) ;
18017 m := makeFuncCall (dupExpr (n^.funccallF.function), dupExpr (n^.funccallF.args)) ;
18018 m^.funccallF.type := n^.funccallF.type ;
18019 assignNodeOpaqueCastState (m, n) ;
18028 PROCEDURE dupSetValue (n: node) : node ;
18033 m := newNode (setvalue) ;
18034 m^.setvalueF.type := n^.setvalueF.type ;
18035 i := LowIndice (n^.setvalueF.values) ;
18036 WHILE i <= HighIndice (n^.setvalueF.values) DO
18037 m := putSetValue (m, dupExpr (GetIndice (n^.setvalueF.values, i))) ;
18045 dupExpr - duplicate the expression nodes, it does not duplicate
18046 variables, literals, constants but only the expression
18047 operators (including function calls and parameter lists).
18050 PROCEDURE dupExpr (n: node) : node ;
18056 RETURN doDupExpr (n)
18065 PROCEDURE doDupExpr (n: node) : node ;
18070 explist : RETURN dupExplist (n) |
18074 comment : HALT | (* should not be duplicating code. *)
18075 length : HALT | (* length should have been converted into unary. *)
18076 (* base constants. *)
18080 (* system types. *)
18105 shortcomplex : RETURN n |
18106 (* language features and compound type attributes. *)
18127 proctype : RETURN n |
18132 module : RETURN n |
18144 assignment : RETURN n |
18146 arrayref : RETURN dupArrayref (n) |
18147 pointerref : RETURN dupPointerref (n) |
18148 componentref : RETURN dupComponentref (n) |
18166 in : RETURN dupBinary (n) |
18184 max : RETURN dupUnary (n) |
18185 identlist : RETURN n |
18186 vardecl : RETURN n |
18187 funccall : RETURN dupFunccall (n) |
18188 setvalue : RETURN dupSetValue (n)
18195 setNoReturn - sets noreturn field inside procedure.
18198 PROCEDURE setNoReturn (n: node; value: BOOLEAN) ;
18201 assert (isProcedure (n)) ;
18202 IF n^.procedureF.noreturnused AND (n^.procedureF.noreturn # value)
18204 metaError1 ('{%1DMad
} definition module and implementation module have different
<* noreturn
*> attributes
', n) ;
18206 n^.procedureF.noreturn := value ;
18207 n^.procedureF.noreturnused := TRUE
18215 PROCEDURE makeSystem ;
18217 systemN := lookupDef (makeKey ('SYSTEM
')) ;
18219 addressN := makeBase (address) ;
18220 locN := makeBase (loc) ;
18221 byteN := makeBase (byte) ;
18222 wordN := makeBase (word) ;
18223 csizetN := makeBase (csizet) ;
18224 cssizetN := makeBase (cssizet) ;
18226 adrN := makeBase (adr) ;
18227 tsizeN := makeBase (tsize) ;
18228 throwN := makeBase (throw) ;
18230 enterScope (systemN) ;
18231 addressN := addToScope (addressN) ;
18232 locN := addToScope (locN) ;
18233 byteN := addToScope (byteN) ;
18234 wordN := addToScope (wordN) ;
18235 csizetN := addToScope (csizetN) ;
18236 cssizetN := addToScope (cssizetN) ;
18237 adrN := addToScope (adrN) ;
18238 tsizeN := addToScope (tsizeN) ;
18239 throwN := addToScope (throwN) ;
18241 assert (sizeN#NIL) ; (* assumed to be built already. *)
18242 sizeN := addToScope (sizeN) ; (* also export size from system. *)
18245 addDone (addressN) ;
18249 addDone (csizetN) ;
18258 PROCEDURE makeM2rts ;
18260 m2rtsN := lookupDef (makeKey ('M2RTS
'))
18268 PROCEDURE makeBitnum () : node ;
18272 b := newNode (subrange) ;
18273 b^.subrangeF.type := NIL ;
18274 b^.subrangeF.scope := NIL ;
18275 b^.subrangeF.low := lookupConst (b, makeKey ('0')) ;
18276 b^.subrangeF.high := lookupConst (b, makeKey ('31')) ;
18285 PROCEDURE makeBaseSymbols ;
18287 baseSymbols := initTree () ;
18289 booleanN := makeBase (boolean) ;
18290 charN := makeBase (char) ;
18291 procN := makeBase (proc) ;
18292 cardinalN := makeBase (cardinal) ;
18293 longcardN := makeBase (longcard) ;
18294 shortcardN := makeBase (shortcard) ;
18295 integerN := makeBase (integer) ;
18296 longintN := makeBase (longint) ;
18297 shortintN := makeBase (shortint) ;
18298 bitsetN := makeBase (bitset) ;
18299 bitnumN := makeBitnum () ;
18300 ztypeN := makeBase (ztype) ;
18301 rtypeN := makeBase (rtype) ;
18302 complexN := makeBase (complex) ;
18303 longcomplexN := makeBase (longcomplex) ;
18304 shortcomplexN := makeBase (shortcomplex) ;
18305 realN := makeBase (real) ;
18306 longrealN := makeBase (longreal) ;
18307 shortrealN := makeBase (shortreal) ;
18309 nilN := makeBase (nil) ;
18310 trueN := makeBase (true) ;
18311 falseN := makeBase (false) ;
18313 sizeN := makeBase (size) ;
18314 minN := makeBase (min) ;
18315 maxN := makeBase (max) ;
18316 floatN := makeBase (float) ;
18317 truncN := makeBase (trunc) ;
18318 ordN := makeBase (ord) ;
18319 valN := makeBase (val) ;
18320 chrN := makeBase (chr) ;
18321 capN := makeBase (cap) ;
18322 absN := makeBase (abs) ;
18323 newN := makeBase (new) ;
18324 disposeN := makeBase (dispose) ;
18325 lengthN := makeBase (length) ;
18326 incN := makeBase (inc) ;
18327 decN := makeBase (dec) ;
18328 inclN := makeBase (incl) ;
18329 exclN := makeBase (excl) ;
18330 highN := makeBase (high) ;
18331 imN := makeBase (im) ;
18332 reN := makeBase (re) ;
18333 cmplxN := makeBase (cmplx) ;
18335 putSymKey (baseSymbols, makeKey ('BOOLEAN'), booleanN) ;
18336 putSymKey (baseSymbols, makeKey ('PROC'), procN) ;
18337 putSymKey (baseSymbols, makeKey ('CHAR'), charN) ;
18338 putSymKey (baseSymbols, makeKey ('CARDINAL'), cardinalN) ;
18339 putSymKey (baseSymbols, makeKey ('SHORTCARD
'), shortcardN) ;
18340 putSymKey (baseSymbols, makeKey ('LONGCARD'), longcardN) ;
18341 putSymKey (baseSymbols, makeKey ('INTEGER'), integerN) ;
18342 putSymKey (baseSymbols, makeKey ('LONGINT'), longintN) ;
18343 putSymKey (baseSymbols, makeKey ('SHORTINT
'), shortintN) ;
18344 putSymKey (baseSymbols, makeKey ('BITSET'), bitsetN) ;
18345 putSymKey (baseSymbols, makeKey ('REAL'), realN) ;
18346 putSymKey (baseSymbols, makeKey ('SHORTREAL
'), shortrealN) ;
18347 putSymKey (baseSymbols, makeKey ('LONGREAL'), longrealN) ;
18348 putSymKey (baseSymbols, makeKey ('COMPLEX
'), complexN) ;
18349 putSymKey (baseSymbols, makeKey ('LONGCOMPLEX
'), longcomplexN) ;
18350 putSymKey (baseSymbols, makeKey ('SHORTCOMPLEX
'), shortcomplexN) ;
18352 putSymKey (baseSymbols, makeKey ('NIL'), nilN) ;
18353 putSymKey (baseSymbols, makeKey ('TRUE'), trueN) ;
18354 putSymKey (baseSymbols, makeKey ('FALSE'), falseN) ;
18355 putSymKey (baseSymbols, makeKey ('SIZE'), sizeN) ;
18356 putSymKey (baseSymbols, makeKey ('MIN'), minN) ;
18357 putSymKey (baseSymbols, makeKey ('MAX'), maxN) ;
18358 putSymKey (baseSymbols, makeKey ('FLOAT'), floatN) ;
18359 putSymKey (baseSymbols, makeKey ('TRUNC'), truncN) ;
18360 putSymKey (baseSymbols, makeKey ('ORD'), ordN) ;
18361 putSymKey (baseSymbols, makeKey ('VAL'), valN) ;
18362 putSymKey (baseSymbols, makeKey ('CHR'), chrN) ;
18363 putSymKey (baseSymbols, makeKey ('CAP'), capN) ;
18364 putSymKey (baseSymbols, makeKey ('ABS'), absN) ;
18365 putSymKey (baseSymbols, makeKey ('NEW'), newN) ;
18366 putSymKey (baseSymbols, makeKey ('DISPOSE'), disposeN) ;
18367 putSymKey (baseSymbols, makeKey ('LENGTH
'), lengthN) ;
18368 putSymKey (baseSymbols, makeKey ('INC'), incN) ;
18369 putSymKey (baseSymbols, makeKey ('DEC'), decN) ;
18370 putSymKey (baseSymbols, makeKey ('INCL'), inclN) ;
18371 putSymKey (baseSymbols, makeKey ('EXCL'), exclN) ;
18372 putSymKey (baseSymbols, makeKey ('HIGH'), highN) ;
18373 putSymKey (baseSymbols, makeKey ('CMPLX
'), cmplxN) ;
18374 putSymKey (baseSymbols, makeKey ('RE
'), reN) ;
18375 putSymKey (baseSymbols, makeKey ('IM
'), imN) ;
18377 addDone (booleanN) ;
18379 addDone (cardinalN) ;
18380 addDone (longcardN) ;
18381 addDone (shortcardN) ;
18382 addDone (integerN) ;
18383 addDone (longintN) ;
18384 addDone (shortintN) ;
18385 addDone (bitsetN) ;
18386 addDone (bitnumN) ;
18390 addDone (longrealN) ;
18391 addDone (shortrealN) ;
18392 addDone (complexN) ;
18393 addDone (longcomplexN) ;
18394 addDone (shortcomplexN) ;
18400 END makeBaseSymbols ;
18407 PROCEDURE makeBuiltins ;
18409 bitsperunitN := makeLiteralInt (makeKey ('8')) ;
18410 bitsperwordN := makeLiteralInt (makeKey ('32')) ;
18411 bitspercharN := makeLiteralInt (makeKey ('8')) ;
18412 unitsperwordN := makeLiteralInt (makeKey ('4')) ;
18414 addDone (bitsperunitN) ;
18415 addDone (bitsperwordN) ;
18416 addDone (bitspercharN) ;
18417 addDone (unitsperwordN)
18422 makeCDataTypes - assign the charStarN and constCharStarN to NIL.
18425 PROCEDURE makeCDataTypes ;
18427 CdatatypesN: node ;
18429 CdatatypesN := lookupDef (makeKey ('CDataTypes
')) ;
18430 enterScope (CdatatypesN) ;
18431 charStarN := makePointer (charN) ;
18432 constCharStarN := makePointer (charN) ;
18434 END makeCDataTypes ;
18444 outputFile := StdOut ;
18445 doP := initPretty (write, writeln) ;
18447 globalGroup := initGroup () ;
18448 modUniverse := initTree () ;
18449 defUniverse := initTree () ;
18450 modUniverseI := InitIndex (1) ;
18451 defUniverseI := InitIndex (1) ;
18452 scopeStack := InitIndex (1) ;
18457 outputState := punct ;
18459 mustVisitScope := FALSE ;