INTERFACE M3AST_AS; (***************************************************************************) (* Copyright (C) Olivetti 1989 *) (* All Rights reserved *) (* *) (* Use and copy of this software and preparation of derivative works based *) (* upon this software are permitted to any person, provided this same *) (* copyright notice and the following Olivetti warranty disclaimer are *) (* included in any copy of the software or any modification thereof or *) (* derivative work therefrom made by any person. *) (* *) (* This software is made available AS IS and Olivetti disclaims all *) (* warranties with respect to this software, whether expressed or implied *) (* under any law, including all implied warranties of merchantibility and *) (* fitness for any purpose. In no event shall Olivetti be liable for any *) (* damages whatsoever resulting from loss of use, data or profits or *) (* otherwise arising out of or in connection with the use or performance *) (* of this software. *) (***************************************************************************) (* Copyright (C) 1991, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (*-------------------------------------------------------------------------- This interface defines an abstract syntax for the Modula-3 programming language, expressed as a tree of nodes represented using OBJECT types. There is a close correspondence between the grammar defined in the language definition and the abstract syntax; however some of the non-terminals have no analog in the abstract syntax, e.g. those which specify operator priority in expressions - this is directly encoded in the AST. Where appropriate the correspondence between the concrete syntax and the abstract syntax will be noted in the specification. The structure of the specification follows the conventions given in the "AST" interface. This interface, "M3AST_AS", provides an abstract specification of the nodes as OBJECT types, leaving the details on how the attributes of each node (children and lexical information) are represented to a companion interface (e.g. as object fields in "M3AST_AS_F"). In the definitions below, the name and type of node attributes are indicated in a following comment of the form (* attribute_name: Attribute_type *). Attribute types fall into two groups. First, lexical types denoting, for example, the characters of an identifier or the characters of a TEXT literal. These types are declared in the interface M3AST_LX, are opaque, and are given concrete definitions by a particular compiler implementation. Second, the children of a node, which are always other node types, i.e. subtypes of AST.NODE. In general, each non-terminal on the right hand of a rule of the concrete grammar is represented by a child node of the corresponding type. An optional term X (denoted by [X] in the concrete syntax), is represented by a child of type of X_NULL, denoting that NIL represents a missing item. A corollary of this is that a value of NIL is not legal for any attribute in a well-formed syntax tree, unless it has type X_NULL. Sequences of X's (denoted by {X} in the concrete syntax) are represented as instances of the abstract sequence type "SeqM3AST_AS_X.T". This interface is specified in the generic interface "SeqElem". Finally, non-terminals that are defined by more than one rule, e.g "Stmt", are defined by object types referred to as classes (e.g. denoting the "class" of statements), with each choice appearing as a separate subtype. There are no instances of such class types in a tree, only of the subtypes, which are called "leaf" types. However, most child nodes are declared as class types. To distinguish class types from leaf types, class types are named using all upper case leters. The standard pragmas EXTERNAL and INLINE are defined to be part of the abstract syntax. There are a number of places where it would be convenient to declare a node as a subtype of more than one parent, i.e. multiple inheritance. Since this is not possible in Modula-3, a number of mechanisms are used as workarounds. Sometimes the number of affected nodes is small enough that it suffices to merely repeat the mutiple inherited attribute in each node. The general solution is as follows: Suppose we wish to declare a new node "A" which inherits from "X" and "Y". Then choose one, say "X", to be the ancestor, and include an attribute named "vY" of type "Y". The "init" method takes care of constructing this structure. --------------------------------------------------------------------------*) IMPORT M3AST; (* All AST nodes are defined to be subtypes of the type "M3AST.NODE", which is a class that captures any behaviour common to all nodes in the Modula-3 AST. "M3AST.NODE" is itself a subtype of "AST.NODE" and thus inherits the standard set of methods provided by that class. *) TYPE (* To support a form of multiple inheritance it is possible to ask if any "NODE" belongs to the "ID", or "USED_ID" classes, see below (and "Exp_used_id". *) (* NODE => METHODS IsA_USED_ID(VAR (*out*) used_id): BOOLEAN; IsA_ID(VAR (*out*) id): BOOLEAN; *) (* Most nodes are annotated with an attribute that denotes the "position" in the (textual) representation of the AST. This is achieved by the class "SRC_NODE", of which all nodes containing this attribute are declared as subtypes. To denote the "end" of compound constructs, e.g. "IF" statements, the class "END_SRC_NODE" is defined, which is "multiply inherited" by those nodes. *) SRC_NODE <: M3AST.NODE; (* lx_srcpos: M3AST_LX.SrcPos *) END_SRC_NODE <: M3AST.NODE; (* lx_end_srcpos: M3AST_LX.SrcPos *) (* Identifiers are represented by many different node types, all of which are subtypes of the "ID" class. This class carries the lexical attribute that denotes the name of the identifier. The subtypes are partitioned into two disjoint sets, those which correspond to identifers that are definitions ("DEF_ID") and those which are correspond to uses ("USED_ID"). Unlike the concrete syntax, which does not distinguish identifier definitions, each construct that can introduce a new identifier definition has an aassociated, unique, subtype, e.g. "Proc_id" for identifiers associated with "PROCEDURE" declarations. *) ID <: SRC_NODE; (* lx_symrep: M3AST_LX.Symbol_rep *) DEF_ID <: ID; DEF_ID_NULL = DEF_ID; UNIT_ID <: DEF_ID; (* Interface or Module identifier *) Module_id <: UNIT_ID; (* MODULE m *) Interface_id <: UNIT_ID; (* INTERFACE i *) Interface_AS_id <: DEF_ID; (* the J in IMPORT I AS J *) F_Interface_id <: DEF_ID; (* generic formal parameter *) (* The class "TYPED_ID" is introduced as a placeholder for semantic information, to mitigate the lack of multiple inheritance. All the identifiers below are subtypes of "TYPED_ID". *) TYPED_ID <: DEF_ID; FORMAL_ID <: TYPED_ID; (* procedure formals *) F_Value_id <: FORMAL_ID; (* VALUE v *) F_Var_id <: FORMAL_ID; (* VAR v *) F_Readonly_id <: FORMAL_ID; (* READONLY v *) Type_id <: TYPED_ID; (* TYPE T *) Const_id <: TYPED_ID; (* CONST C *) Var_id <: TYPED_ID; (* VAR v (in blocks) *) Proc_id <: TYPED_ID; (* PROCEDURE P *) Enum_id <: TYPED_ID; (* {Red,Green,Blue} *) METHOD_OVERRIDE_ID <: TYPED_ID; Method_id <: METHOD_OVERRIDE_ID; (* METHODS m *) Override_id <: METHOD_OVERRIDE_ID; (* OVERRIDES m *) Field_id <: TYPED_ID; (* in RECORDs and OBJECTs *) For_id <: TYPED_ID; (* FOR i *) Handler_id <: TYPED_ID; (* EXCEPT E(v) *) Handler_id_NULL = Handler_id; Tcase_id <: TYPED_ID; (* TYPECASE ... T(v) *) Tcase_id_NULL = Tcase_id; With_id <: TYPED_ID; (* WITH b *) Exc_id <: TYPED_ID; (* EXCEPTION E(T) *) (* Identifier uses are separated into three distinct subtypes. Firstly, there are several cases where the binding of the use is required by the language definition to be to an "Interface_id", e.g. "IMPORT I". To improve readability, such uses are denoted by the subtype "Used_interface_id". Secondly, there are occurrences such as the identifier "N" in a "FROM I IMPORT N". These are denoted by the subtype "Used_def_id". Finally, there are identifiers that can occur in expressions. Here we have a problem, since such identifiers also need to be a subtype of the class that denotes expressions ("EXP"). The solution, of which more later, is to make these a subtype of "EXP", and call them "Exp_used_id". *) USED_ID <: ID; Used_interface_id <: USED_ID; Used_interface_id_NULL = Used_interface_id; Used_def_id <: USED_ID; (* Qualified identifiers, e.g. "I.B", can also appear in both expression and non-expression contexts. In the former case, it is not known after syntax analysis, whether a construct of the form "a.b" denotes a qualified identifier or not, until the binding for "a" is resolved. In the non-expression case, e.g. in "REVEAL I.T = ...", a qualified identifier is denoted by a separate node containing two children of class "USED_ID". Note that the "interface" component of such a node can be empty, denoted by NIL. *) Qual_used_id <: SRC_NODE; Qual_used_id_NULL = Qual_used_id; (* as_intf_id: M3AST_AS.Used_interface_id_NULL; as_id: M3AST_AS.Used_def_id; *) (* In order to provide a node in which to place to miscellaneous attributes, e.g. compilation status, the AST is rooted in a node called "Compilation_Unit", which has no couterpart in the concrete syntax. *) Compilation_Unit <: M3AST.NODE; (* as_root: M3AST_AS.UNIT; lx_comments: M3AST_LX.CommentStore; lx_pragmas: M3AST_LX.PragmaStore; *) (* The class that corresponds to the non-terminal named "Compilation" in the concrete grammar is called "UNIT", and it has subtypes to denote generic definitions, generic instantiations and "normal" interfaces and modules. Multiple inheritance would simplify the structure here also, but in this case, it is simplest to simply repeat (multiply inherited) attributes in subtypes. The "UNIT" class carries the attribute denoting the identifier that is common to all forms of "UNIT". *) UNIT <: SRC_NODE; (* as_id: M3AST_AS.UNIT_ID *) (* Generic definitions and "normal" units both have "bodies", i.e. imports and declarations, and these are associated with the class "UNIT_WITH_BODY". *) UNIT_WITH_BODY <: UNIT; (* as_import_s: SeqM3AST_AS_IMPORTED.T; as_block: M3AST_AS.Block *) (* Generic definitions contain a list of formal parameters, and this is captured by the "UNIT_GEN_DEF" class. *) UNIT_GEN_DEF <: UNIT_WITH_BODY; (* as_id_s: SeqM3AST_AS_F_Interface_id.T; *) (* Generic interfaces can be EXTERNAL *) Interface_gen_def <: UNIT_GEN_DEF; (* vEXTERNAL_DECL: M3AST_PG.EXTERNAL_DECL *) Module_gen_def <: UNIT_GEN_DEF; (* Generic module definition *) (* Normal interfaces and modules can be UNSAFE. (as can generic instantiations, but this example of multiple inheritance is not captured in the type hierarchy. *) UNIT_NORMAL <: UNIT_WITH_BODY; (* as_unsafe: M3AST_AS.Unsafe_NULL *) (* Interfaces can be EXTERNAL *) Interface <: UNIT_NORMAL; (* vEXTERNAL_DECL: M3AST_PG.EXTERNAL_DECL *) (* Modules can have an EXPORT list (as can generically instantiated modules, but this example of multiple inheritance is not captured in the type hierarchy). *) Module <: UNIT_NORMAL; (* as_export_s: SeqM3AST_AS_Used_interface_id.T *) (* Generic instantiations can be UNSAFE, contain an identifier that refers to the generic definition and a list of actual parameters. These identifier occurrences must all bind to "Interface_id"s. *) UNIT_GEN_INS <: UNIT; (* as_unsafe: M3AST_AS.Unsafe_NULL; as_gen_id: M3AST_AS.Used_interface_id; as_id_s: SeqM3AST_AS_Used_interface_id.T *) Interface_gen_ins <: UNIT_GEN_INS; Module_gen_ins <: UNIT_GEN_INS; (* as_export_s: SeqM3AST_AS_Used_interface_id.T *) (* UNSAFE is represented as node with no children *) Unsafe <: SRC_NODE; Unsafe_NULL = Unsafe; (* Imports fall into two classes, denoted by "AsImport" and "FromImport" in the concrete syntax. The class "IMPORTED" is used in the AST to denote the choice, with subtypes "Simple_import" and "From_import". *) IMPORTED <: SRC_NODE; Simple_import <: IMPORTED; (* as_import_item_s: SeqM3AST_AS_Import_item.T *) (* An "Import_item" node corresponds directly to "ImportItem" in the concrete syntax *) Import_item <: SRC_NODE; (* as_intf_id: M3AST_AS.Used_interface_id; as_id: M3AST_AS.Interface_AS_id; *) From_import <: IMPORTED; (* as_id_s: SeqM3AST_AS_Used_def_id.T; as_intf_id: M3AST_AS.Used_interface_id *) (* The concrete syntax groups revelations under the "Decl" rules. In the AST we introduce a class "DECL_REVL" to handle either and separate subtypes "DECL and "Revelation_s" *) DECL_REVL <: SRC_NODE; (* The abstract syntax permits any "DECL" to be EXTERNAL, although the static semantics are more restrictive. Declarations are somewhat tedious to represent, since each occurrence of, say, CONST, can introduce several actual declarations. Accordingly, we introduce nodes of the form "X_s", which carry a sequence attribute. *) DECL <: DECL_REVL; (* vEXTERNAL_DECL: M3AST_PG.EXTERNAL_DECL *) Const_decl_s <: DECL; (* CONST ... *) (* as_const_decl_s: SeqM3AST_AS_Const_decl.T *) Type_decl_s <: DECL; (* TYPE ... *) (* as_type_decl_s: SeqM3AST_AS_TYPE_DECL.T *) Var_decl_s <: DECL; (* VAR ... *) (* as_var_decl_s: SeqM3AST_AS_Var_decl.T *) Exc_decl_s <: DECL; (* EXCEPTION ... *) (* as_exc_decl_s: SeqM3AST_AS_Exc_decl.T *) (* Proc_decl is the exception to the rule. The "as_body" attribute will be NIL in an interface AST. *) Proc_decl <: DECL; (* as_id: M3AST_AS.Proc_id; pg_inline: M3AST_PG.Inline_NULL; as_type: M3AST_AS.Procedure_type; as_body: M3AST_AS.Block_NULL; *) (* Now the declarations proper. Note that the identifer in each node is of the appropriate type, e.g. Const_id for a Const_decl. *) Const_decl <: SRC_NODE; (* as_id: M3AST_AS.Const_id; as_type: M3AST_AS.M3TYPE_NULL; as_exp: M3AST_AS.EXP; *) (* Type declarations are either opaque (subtype) or concrete. The class "TYPE_DECL" captures this. *) TYPE_DECL <: SRC_NODE; (* as_id: M3AST_AS.Type_id; as_type: M3AST_AS.M3TYPE; *) (* The "as_type" attribute for a "Subtype_decl" is always an "Opaque_type" node (see below). The value of "U" is encoded as an attribuet of the "Opaque_type" node. *) Subtype_decl <: TYPE_DECL; (* TYPE T <: U *) Concrete_decl <: TYPE_DECL; (* TYPE T = U *) (* Variable declarations are unusual in that several identifiers can be introduced in the same declaration. Note that either the "as_type" attribute or the "as_default" attribute may be NIL, but not both. The latter constraint is not expressed in the AST. *) Var_decl <: SRC_NODE; (* as_id_s: SeqM3AST_AS_Var_id.T; as_type: M3AST_AS.M3TYPE_NULL; as_default: M3AST_AS.EXP_NULL; *) Exc_decl <: SRC_NODE; (* as_id: M3AST_AS.Exc_id; as_type: M3AST_AS.M3TYPE_NULL; *) Revelation_s <: DECL_REVL; (* as_reveal_s: SeqM3AST_AS_REVELATION.T *) (* Like type declarations, revelations can be opaque (subtype) or concrete. *) REVELATION <: SRC_NODE; (* as_qual_id: M3AST_AS.Qual_used_id; as_type: M3AST_AS.M3TYPE; *) Subtype_reveal <: REVELATION; (* REVEAL T <: U *) Concrete_reveal <: REVELATION; (* REVEAL T = U *) (* Type Productions *) (* There are situations where an attribute can be either a type or an expression, so we define the class "EXP_TYPE" to denote that choice. *) EXP_TYPE <: SRC_NODE; (* expression or type *) (* Types can appear in the AST as type constructions or as qualified identifiers (which must ultimately bind to a name declared as a "Type_id". The class "M3TYPE" is used to denote this choice. *) M3TYPE <: EXP_TYPE; M3TYPE_NULL = M3TYPE; Named_type <: M3TYPE; (* as_qual_id: M3AST_AS.Qual_used_id *) (* Type constructions (specifications) are grouped under the class "TYPE_SPEC" *) TYPE_SPEC <: M3TYPE; (* The following built-in types are primitive. Others, such as "BOOLEAN", are expressed as instances of the apropriate "TYPE_SPEC" subtype. *) (* For convenience all the floating types are grouped under "FLOAT_TYPE" *) FLOAT_TYPE <: TYPE_SPEC; Real_type <: FLOAT_TYPE; (* REAL *) LongReal_type <: FLOAT_TYPE; (* LONGREAL *) Extended_type <: FLOAT_TYPE; (* EXTENDED *) Integer_type <: TYPE_SPEC; (* INTEGER *) Null_type <: TYPE_SPEC; (* NULL *) RefAny_type <: TYPE_SPEC; (* REFANY *) Address_type <: TYPE_SPEC; (* ADDRESS *) Root_type <: TYPE_SPEC; (* ROOT/UNTRACED ROOT *) (* as_trace_mode: M3AST_AS.Untraced_NULL *) (* "UNTRACED ..." is denoted by a node of type "Untraced" *) Untraced <: SRC_NODE; Untraced_NULL = Untraced; Packed_type <: TYPE_SPEC; (* as_exp: M3AST_AS.EXP; as_type: M3AST_AS.M3TYPE *) (* No attempt is made in the AST to normalise multi-dimensional array types *) Array_type <: TYPE_SPEC; (* as_indextype_s: SeqM3AST_AS_M3TYPE.T; as_elementtype: M3AST_AS.M3TYPE; *) Enumeration_type <: TYPE_SPEC; (* as_id_s: SeqM3AST_AS_Enum_id.T *) Set_type <: TYPE_SPEC; (* as_type: M3AST_AS.M3TYPE *) Subrange_type <: TYPE_SPEC; (* as_range: M3AST_AS.Range *) (* Several attributes need to encode a range of expressions, and in some cases a single value is a legal choice . To avoid duplication, the class "RANGE_EXP" is introduced to denote this choice. *) RANGE_EXP <: SRC_NODE; (* A single value is denoted by a "Range_EXP" (sic). *) Range_EXP <: RANGE_EXP; (* as_exp: M3AST_AS.EXP *) Range <: RANGE_EXP; (* as_exp1, as_exp2: M3AST_AS.EXP *) (* RECORD types simple contain a sequence of "Fields". Since the concrete syntax contains an "END", the "END_SRC_NODE" clas is "multiply inherited" *) Record_type <: TYPE_SPEC; (* as_fields_s := SeqM3AST_AS_Fields.Null; vEND_SRC_NODE: M3AST_AS.END_SRC_NODE *) (* Like VAR declarations, Each "field" can introduce several identifiers of the same type and initial value. The remarks about "as_type" and "as_default" in the "Var_decl" node apply to fields also. *) Fields <: SRC_NODE; (* as_id_s: SeqM3AST_AS_Field_id.T; as_type: M3AST_AS.M3TYPE_NULL; as_default: M3AST_AS.EXP_NULL; *) (* OBJECT types and REF types can be BRANDED, and this is denoted by the "BRANDED_TYPE" class. *) BRANDED_TYPE <: TYPE_SPEC; (* as_brand: M3AST_AS.Brand_NULL *) (* A user supplied brand is optional. *) Brand <: SRC_NODE; (* as_exp: M3AST_AS.EXP_NULL *) Brand_NULL = Brand; Ref_type <: BRANDED_TYPE; (* as_trace_mode: M3AST_AS.Untraced_NULL := NIL; as_type: M3AST_AS.M3TYPE *) (* The object supertype (ancestor) is encoded as an attribute of type "M3TYPE". In fact only a "Named_type", "Object_type" or "Root_Type" is legal. *) Object_type <: BRANDED_TYPE; (* as_ancestor: M3AST_AS.M3TYPE_NULL := NIL; as_fields_s: SeqM3AST_AS_Fields.T; as_method_s: SeqM3AST_AS_Method.T; as_override_s: SeqM3AST_AS_Override.T; vEND_SRC_NODE: M3AST_AS.END_SRC_NODE *) (* Methods and Overrides have a similar syntactic structure, which is encoded by the class "METHOD_OVERRIDE" An "Override" has the additional constraint that "as_default # NIL". *) METHOD_OVERRIDE <: SRC_NODE; (* as_id: M3AST_AS.METHOD_OVERRIDE_ID; as_default: M3AST_AS.EXP_NULL *) Method <: METHOD_OVERRIDE; (* as_type: M3AST_AS.Procedure_type *) Override <: METHOD_OVERRIDE; Procedure_type <: TYPE_SPEC; (* as_formal_param_s: SeqM3AST_AS_Formal_param.T; as_result_type: M3AST_AS.M3TYPE_NULL; as_raises: M3AST_AS.RAISEES_NULL *) (* As with "Var_decl"s, only one of "as_formal_type" and "as_default" may be NIL. *) Formal_param <: SRC_NODE; (* as_id_s: SeqM3AST_AS_FORMAL_ID.T; as_formal_type: M3AST_AS.M3TYPE_NULL; as_default: M3AST_AS.EXP_NULL *) RAISEES <: SRC_NODE; RAISEES_NULL = RAISEES; Raisees_some <: RAISEES; (* as_raisees_s := SeqM3AST_AS_Qual_used_id.T *) Raisees_any <: RAISEES; (* RAISES ANY *) (* Opaque types have no direct correspondence in the abstract syntax. In effect they encode the "<:" in a Subtype_decl, and provide a unique node for each declaration, which is important for subsequent semantic analysis. The "as_type" attribute enocdes the "M3TYPE" that actually appeared to the right of the "<:". *) Opaque_type <: TYPE_SPEC; (* as_type: M3AST_AS.M3TYPE *) (* Expression productions *) (* There is no analogue of "ConstExpr" in the abstract syntax. *) EXP <: EXP_TYPE; EXP_NULL = EXP; (* All numeric literals are members of the class "NUMERIC_LITERAL", which carries the lexical information. *) NUMERIC_LITERAL <: EXP; (* lx_numrep: M3AST_LX.Number_rep *) Integer_literal <: NUMERIC_LITERAL; Real_literal <: NUMERIC_LITERAL; LongReal_literal <: NUMERIC_LITERAL; Extended_literal <: NUMERIC_LITERAL; Char_literal <: EXP; (* lx_charrep: M3AST_LX.Text_rep *) Text_literal <: EXP; (* lx_textrep: M3AST_LX.Text_rep *) (* NIL is represented by a node of type "Nil_literal" *) Nil_literal <: EXP; (* Single identifiers occurring in expressions are really subtypes of "EXP" and "USED_ID". They are declared as subtypes of "EXP", with the "USED_ID" attributes "multiply inherited" *) Exp_used_id <: EXP; (* vUSED_ID: M3AST_AS.USED_ID *) (* A "Call" node is used to denote all the built-in functions and procedures. *) Call <: EXP; (* as_callexp: M3AST_AS.EXP; as_param_s: SeqM3AST_AS_Actual.T *) (* The desugaring of "NEW(ObjectType, method := P)" is made easier if the applications of NEW are denoted by an independent subtype. *) NEWCall <: Call; (* Since it is legal for an actual parameter to some of the built-in functions to be a type, "as_exp_type" is of class "EXP_TYPE". The value of "as_id" will be NIL for the built-in functions. *) Actual <: SRC_NODE; (* as_id: M3AST_AS.EXP_NULL := NIL; as_exp_type: M3AST_AS.EXP_TYPE *) Index <: EXP; (* a[x,y,z,...] *) (* as_array: M3AST_AS.EXP; as_exp_s: SeqM3AST_AS_EXP.T *) (* ARRAY, RECORD and SET constructors are not distinguished in the AST, since they are not, in general, distinguished by syntax alone. The different kinds of elements are denoted by the class "CONS_ELEM". Array element propagation is denoted a node of type "Propagate". *) Constructor <: EXP; (* as_type: M3AST_AS.M3TYPE := NIL; as_element_s: SeqM3AST_AS_CONS_ELEM.T; as_propagate: M3AST_AS.Propagate_NULL *) Propagate <: SRC_NODE; Propagate_NULL = Propagate; (* There are three different kinds of constructor elements, simple expressions, ranges and keyword actuals. We use the already declared types "RANGE_EXP" and "Actual" as the corresponding attribute types. *) CONS_ELEM <: SRC_NODE; RANGE_EXP_elem <: CONS_ELEM; (* as_range_exp: M3AST_AS.RANGE_EXP *) Actual_elem <: CONS_ELEM; (* as_actual: M3AST_AS.Actual *) (* In this version of the specification, binary and unary operators are denoted by attributes of the "Binary" and "Unary" nodes. Selection (".") is denoted by a subtypee of "Binary" called "Select". This will change in a future version. The operators will be encoded directly as subtypes of "BINARY" and "UNARY" classes, and "Select" will be a direct subtype of "EXP", like "Index". *) Binary <: EXP; (* as_binary_op: M3AST_AS.BINARY_OP; as_exp1: M3AST_AS.EXP; as_exp2: M3AST_AS.EXP *) BINARY_OP <: SRC_NODE; Plus <: BINARY_OP; (* + *) Minus <: BINARY_OP; (* - *) Times <: BINARY_OP; (* * *) Rdiv <: BINARY_OP; (* / *) Textcat <: BINARY_OP; (* & *) Div <: BINARY_OP; (* DIV *) Mod <: BINARY_OP; (* MOD *) Eq <: BINARY_OP; (* = *) Ne <: BINARY_OP; (* # *) Gt <: BINARY_OP; (* > *) Lt <: BINARY_OP; (* < *) Ge <: BINARY_OP; (* >= *) Le <: BINARY_OP; (* <= *) And <: BINARY_OP; (* AND *) Or <: BINARY_OP; (* OR *) In <: BINARY_OP; (* IN *) Select <: BINARY_OP; (* . *) Unary <: EXP; (* as_unary_op: M3AST_AS.UNARY_OP; as_exp: M3AST_AS.EXP *) UNARY_OP <: SRC_NODE; Not <: UNARY_OP; (* NOT *) Unaryplus <: UNARY_OP; (* + *) Unaryminus <: UNARY_OP; (* - *) Deref <: UNARY_OP; (* ^ *) (* Statement productions *) (* The "STM" class captures all possible statement productions. *) STM <: SRC_NODE; (* Statements partition into two groups, those with "a sequence of statements" as an attribute, e.g. "WHILE", and those which do not, e.g. "RAISE". The class "STM_WSS" contains the former group. Some statements contain a component that, although it cannot appear where a "STM" can, also contains "a sequence of statements", e.g. the "ELSE" clause in a "CASE" statement. These nodes are grouped into the class "SUBSTM_WSS". *) STM_WSS <: STM; (* as_stm_s: SeqM3AST_AS_STM.T *) SUBSTM_WSS <: SRC_NODE; (* as_stm_s: SeqM3AST_AS_STM.T *) (*---------------------Subtypes of STM------------------------------------*) Assign_st <: STM; (* as_lhs_exp: M3AST_AS.EXP; as_rhs_exp: M3AST_AS.EXP *) Call_st <: STM; (* as_call: M3AST_AS.Call *) Case_st <: STM; (* as_exp: M3AST_AS.EXP; as_case_s: SeqM3AST_AS_Case.T; as_else: M3AST_AS.Else_stm_NULL; vEND_SRC_NODE: M3AST_AS.END_SRC_NODE *) Case <: SUBSTM_WSS; (* as_case_label_s: SeqM3AST_AS_RANGE_EXP.T *) Else_stm <: SUBSTM_WSS; Else_stm_NULL = Else_stm; Eval_st <: STM; (* as_exp: M3AST_AS.EXP *) Exit_st <: STM; Raise_st <: STM; (* as_qual_id: M3AST_AS.Qual_used_id; as_exp_void: M3AST_AS.EXP_NULL *) Typecase_st <: STM; (* as_exp: M3AST_AS.EXP; as_tcase_s: SeqM3AST_AS_Tcase.T; as_else: M3AST_AS.Else_stm_NULL; vEND_SRC_NODE: M3AST_AS.END_SRC_NODE; *) Tcase <: SUBSTM_WSS; (* as_type_s: SeqM3AST_AS_M3TYPE.T; as_id: M3AST_AS.Tcase_id_NULL *) Handler <: SUBSTM_WSS; (* as_qual_id_s: SeqM3AST_AS_Qual_used_id.T; as_id: M3AST_AS.Handler_id_NULL *) Return_st <: STM; (* as_exp: M3AST_AS.EXP_NULL *) (*-----------------------Subtypes of STM_WSS------------------------------*) For_st <: STM_WSS; (* as_id: M3AST_AS.For_id; as_from: M3AST_AS.EXP; as_to: M3AST_AS.EXP; as_by: M3AST_AS.By_NULL; vEND_SRC_NODE: M3AST_AS.END_SRC_NODE *) By <: SRC_NODE; (* as_exp: M3AST_AS.EXP *) By_NULL = By; If_st <: STM_WSS; (* as_exp: M3AST_AS.EXP; as_elsif_s: SeqM3AST_AS_Elsif.T; as_else: M3AST_AS.Else_stm_NULL; vEND_SRC_NODE: M3AST_AS.END_SRC_NODE *) Elsif <: SUBSTM_WSS; (* as_exp: M3AST_AS.EXP *) Lock_st <: STM_WSS; (* as_exp: M3AST_AS.EXP; vEND_SRC_NODE: M3AST_AS.END_SRC_NODE *) Loop_st <: STM_WSS; (* vEND_SRC_NODE: M3AST_AS.END_SRC_NODE *) Repeat_st <: STM_WSS; (* as_exp: M3AST_AS.EXP; vEND_SRC_NODE: M3AST_AS.END_SRC_NODE *) Try_st <: STM_WSS; (* as_try_tail: M3AST_AS.TRY_TAIL; vEND_SRC_NODE: M3AST_AS.END_SRC_NODE *) TRY_TAIL <: SUBSTM_WSS; Try_except <: TRY_TAIL; (* as_handler_s: SeqM3AST_AS_Handler.T; as_else: M3AST_AS.Else_stm_NULL *) Try_finally <: TRY_TAIL; While_st <: STM_WSS; (* as_exp: M3AST_AS.EXP := NIL; vEND_SRC_NODE: M3AST_AS.END_SRC_NODE *) With_st <: STM_WSS; (* as_binding_s: SeqM3AST_AS_Binding.T; vEND_SRC_NODE: M3AST_AS.END_SRC_NODE *) Binding <: SRC_NODE; (* as_id: M3AST_AS.With_id; as_exp: M3AST_AS.EXP *) Block <: STM_WSS; (* as_decl_s: SeqM3AST_AS_DECL_REVL.T; vEND_SRC_NODE: M3AST_AS.END_SRC_NODE *) Block_NULL = Block; (* Syntax errors are handled in part by new subtypes of a class named "Bad_Class". I.e. a syntactically incorrect AST may contain an instance of "Bad_Class", wherever an attribute of type "Class" could appear. *) Bad_EXP <: EXP; Bad_M3TYPE <: M3TYPE; Bad_STM <: STM; (*-------------------------------------------------------------------------- Classes which, because they involve multiple inheritance, cannot be expressed using Modula-3 object types. So instead of using ISTYPE(n, C) you must use one of these functions instead. Fortunately there are not many in the syntactic backbone. If the result of the call is TRUE, the 'out' parameter is set to the multiply inherited part of the (composite) node. --------------------------------------------------------------------------*) PROCEDURE IsA_USED_ID(n: M3AST.NODE; VAR(*out*) used_id: USED_ID): BOOLEAN RAISES {}; (* == n.IsA_USED_ID(used_id) *) PROCEDURE IsA_ID(n: M3AST.NODE; VAR(*out*) id: ID): BOOLEAN RAISES {}; (* == n.IsA_ID(id) *) PROCEDURE IsA_END_SRC_NODE(n: M3AST.NODE; VAR(*out*) end_src_node: END_SRC_NODE): BOOLEAN RAISES {}; (* all constructs ending in END, e.g. RECORD, IF (also REPEAT) *) (*-------------------------------------------------------------------------- Node creation procedures These take the form: PROCEDURE NewNode(): Node RAISES {}; Since the language change which permits NEW(Opaque_type), a call to NewT() is defined to be equivalent to NEW(T).init(). --------------------------------------------------------------------------*) PROCEDURE NewModule_id(): Module_id RAISES {}; PROCEDURE NewInterface_id(): Interface_id RAISES {}; PROCEDURE NewInterface_AS_id(): Interface_AS_id RAISES {}; PROCEDURE NewF_Interface_id(): F_Interface_id RAISES {}; PROCEDURE NewF_Value_id(): F_Value_id RAISES {}; PROCEDURE NewF_Var_id(): F_Var_id RAISES {}; PROCEDURE NewF_Readonly_id(): F_Readonly_id RAISES {}; PROCEDURE NewType_id(): Type_id RAISES {}; PROCEDURE NewConst_id(): Const_id RAISES {}; PROCEDURE NewVar_id(): Var_id RAISES {}; PROCEDURE NewProc_id(): Proc_id RAISES {}; PROCEDURE NewEnum_id(): Enum_id RAISES {}; PROCEDURE NewMethod_id(): Method_id RAISES {}; PROCEDURE NewOverride_id(): Override_id RAISES {}; PROCEDURE NewField_id(): Field_id RAISES {}; PROCEDURE NewFor_id(): For_id RAISES {}; PROCEDURE NewHandler_id(): Handler_id RAISES {}; PROCEDURE NewTcase_id(): Tcase_id RAISES {}; PROCEDURE NewWith_id(): With_id RAISES {}; PROCEDURE NewExc_id(): Exc_id RAISES {}; PROCEDURE NewUsed_interface_id(): Used_interface_id RAISES {}; PROCEDURE NewUsed_def_id(): Used_def_id RAISES {}; PROCEDURE NewQual_used_id(): Qual_used_id RAISES {}; PROCEDURE NewCompilation_Unit(): Compilation_Unit RAISES {}; PROCEDURE NewInterface_gen_def(): Interface_gen_def RAISES {}; PROCEDURE NewModule_gen_def(): Module_gen_def RAISES {}; PROCEDURE NewInterface_gen_ins(): Interface_gen_ins RAISES {}; PROCEDURE NewModule_gen_ins(): Module_gen_ins RAISES {}; PROCEDURE NewInterface(): Interface RAISES {}; PROCEDURE NewModule(): Module RAISES {}; PROCEDURE NewUnsafe(): Unsafe RAISES {}; PROCEDURE NewImport_item(): Import_item RAISES {}; PROCEDURE NewSimple_import(): Simple_import RAISES {}; PROCEDURE NewFrom_import(): From_import RAISES {}; PROCEDURE NewRevelation_s(): Revelation_s RAISES {}; PROCEDURE NewConst_decl_s(): Const_decl_s RAISES {}; PROCEDURE NewType_decl_s(): Type_decl_s RAISES {}; PROCEDURE NewVar_decl_s(): Var_decl_s RAISES {}; PROCEDURE NewExc_decl_s(): Exc_decl_s RAISES {}; PROCEDURE NewProc_decl(): Proc_decl RAISES {}; PROCEDURE NewConst_decl(): Const_decl RAISES {}; PROCEDURE NewVar_decl(): Var_decl RAISES {}; PROCEDURE NewExc_decl(): Exc_decl RAISES {}; PROCEDURE NewSubtype_decl(): Subtype_decl RAISES {}; PROCEDURE NewConcrete_decl(): Concrete_decl RAISES {}; PROCEDURE NewSubtype_reveal(): Subtype_reveal RAISES {}; PROCEDURE NewConcrete_reveal(): Concrete_reveal RAISES {}; PROCEDURE NewNamed_type(): Named_type RAISES {}; PROCEDURE NewInteger_type(): Integer_type RAISES {}; PROCEDURE NewReal_type(): Real_type RAISES {}; PROCEDURE NewLongReal_type(): LongReal_type RAISES {}; PROCEDURE NewExtended_type(): Extended_type RAISES {}; PROCEDURE NewNull_type(): Null_type RAISES {}; PROCEDURE NewRefAny_type(): RefAny_type RAISES {}; PROCEDURE NewAddress_type(): Address_type RAISES {}; PROCEDURE NewRoot_type(): Root_type RAISES {}; PROCEDURE NewEnumeration_type(): Enumeration_type RAISES {}; PROCEDURE NewSubrange_type(): Subrange_type RAISES {}; PROCEDURE NewArray_type(): Array_type RAISES {}; PROCEDURE NewRecord_type(): Record_type RAISES {}; PROCEDURE NewObject_type(): Object_type RAISES {}; PROCEDURE NewSet_type(): Set_type RAISES {}; PROCEDURE NewProcedure_type(): Procedure_type RAISES {}; PROCEDURE NewRef_type(): Ref_type RAISES {}; PROCEDURE NewPacked_type(): Packed_type RAISES {}; PROCEDURE NewOpaque_type(): Opaque_type RAISES {}; PROCEDURE NewBrand(): Brand RAISES {}; PROCEDURE NewUntraced(): Untraced RAISES {}; PROCEDURE NewFields(): Fields RAISES {}; PROCEDURE NewMethod(): Method RAISES {}; PROCEDURE NewOverride(): Override RAISES {}; PROCEDURE NewFormal_param(): Formal_param RAISES {}; PROCEDURE NewRaisees_some(): Raisees_some RAISES {}; PROCEDURE NewRaisees_any(): Raisees_any RAISES {}; PROCEDURE NewRange(): Range RAISES {}; PROCEDURE NewRange_EXP(): Range_EXP RAISES {}; PROCEDURE NewInteger_literal(): Integer_literal RAISES {}; PROCEDURE NewReal_literal(): Real_literal RAISES {}; PROCEDURE NewLongReal_literal(): LongReal_literal RAISES {}; PROCEDURE NewExtended_literal(): Extended_literal RAISES {}; PROCEDURE NewText_literal(): Text_literal RAISES {}; PROCEDURE NewChar_literal(): Char_literal RAISES {}; PROCEDURE NewNil_literal(): Nil_literal RAISES {}; PROCEDURE NewExp_used_id(): Exp_used_id RAISES {}; PROCEDURE NewConstructor(): Constructor RAISES {}; PROCEDURE NewRANGE_EXP_elem(): RANGE_EXP_elem RAISES {}; PROCEDURE NewActual_elem(): Actual_elem RAISES {}; PROCEDURE NewPropagate(): Propagate RAISES {}; PROCEDURE NewBinary(): Binary RAISES {}; PROCEDURE NewPlus(): Plus RAISES {}; PROCEDURE NewMinus(): Minus RAISES {}; PROCEDURE NewTimes(): Times RAISES {}; PROCEDURE NewRdiv(): Rdiv RAISES {}; PROCEDURE NewTextcat(): Textcat RAISES {}; PROCEDURE NewDiv(): Div RAISES {}; PROCEDURE NewMod(): Mod RAISES {}; PROCEDURE NewEq(): Eq RAISES {}; PROCEDURE NewNe(): Ne RAISES {}; PROCEDURE NewGt(): Gt RAISES {}; PROCEDURE NewLt(): Lt RAISES {}; PROCEDURE NewGe(): Ge RAISES {}; PROCEDURE NewLe(): Le RAISES {}; PROCEDURE NewAnd(): And RAISES {}; PROCEDURE NewOr(): Or RAISES {}; PROCEDURE NewIn(): In RAISES {}; PROCEDURE NewSelect(): Select RAISES {}; PROCEDURE NewUnary(): Unary RAISES {}; PROCEDURE NewNot(): Not RAISES {}; PROCEDURE NewUnaryplus(): Unaryplus RAISES {}; PROCEDURE NewUnaryminus(): Unaryminus RAISES {}; PROCEDURE NewDeref(): Deref RAISES {}; PROCEDURE NewCall(): Call RAISES {}; PROCEDURE NewNEWCall(): NEWCall RAISES {}; PROCEDURE NewIndex(): Index RAISES {}; PROCEDURE NewActual(): Actual RAISES {}; PROCEDURE NewAssign_st(): Assign_st RAISES {}; PROCEDURE NewCall_st(): Call_st RAISES {}; PROCEDURE NewCase_st(): Case_st RAISES {}; PROCEDURE NewEval_st(): Eval_st RAISES {}; PROCEDURE NewExit_st(): Exit_st RAISES {}; PROCEDURE NewFor_st(): For_st RAISES {}; PROCEDURE NewIf_st(): If_st RAISES {}; PROCEDURE NewLock_st(): Lock_st RAISES {}; PROCEDURE NewLoop_st(): Loop_st RAISES {}; PROCEDURE NewRaise_st(): Raise_st RAISES {}; PROCEDURE NewRepeat_st(): Repeat_st RAISES {}; PROCEDURE NewReturn_st(): Return_st RAISES {}; PROCEDURE NewTry_st(): Try_st RAISES {}; PROCEDURE NewTypecase_st(): Typecase_st RAISES {}; PROCEDURE NewWhile_st(): While_st RAISES {}; PROCEDURE NewWith_st(): With_st RAISES {}; PROCEDURE NewBlock(): Block RAISES {}; PROCEDURE NewCase(): Case RAISES {}; PROCEDURE NewElse_stm(): Else_stm RAISES {}; PROCEDURE NewBy(): By RAISES {}; PROCEDURE NewElsif(): Elsif RAISES {}; PROCEDURE NewTry_except(): Try_except RAISES {}; PROCEDURE NewTry_finally(): Try_finally RAISES {}; PROCEDURE NewTcase(): Tcase RAISES {}; PROCEDURE NewHandler(): Handler RAISES {}; PROCEDURE NewBinding(): Binding RAISES {}; PROCEDURE NewBad_EXP(): Bad_EXP RAISES {}; PROCEDURE NewBad_M3TYPE(): Bad_M3TYPE RAISES {}; PROCEDURE NewBad_STM(): Bad_STM RAISES {}; (* to support multiple inheritance need ways to create some class nodes. *) PROCEDURE NewUSED_ID(): USED_ID RAISES {}; PROCEDURE NewEND_SRC_NODE(): END_SRC_NODE RAISES {}; END M3AST_AS.