/********* * * WARNING: Any structural changes made here need to be reflected in the non-++ * version, and vice versa. This file was once a sym link to the ++ version, * but it's now a copy so it will check in with cvs normally. This whole "++" * business undoubtedly needs to go away at some point. * */ /* * Modula-2 and RSL parse tree data abastraction. */ #ifndef parsetreeIncluded #define parsetreeIncluded #include "val.h" /* #include "list.h" */ /* * Tree tokens are simply integers. */ typedef int TokenType; /* * These are the kind of parse tree nodes; see struct node def below. The * kind_of_node values serve as tags for the top-level union structure of tree * nodes. */ typedef enum { /* Modula-2 Node Types */ MODULE_NODE, /* 0 */ BLOCK_NODE, /* 1 */ DECL_NODE, /* 2 */ STMT_NODE, /* 3 */ EXPR_LIST_NODE, /* 4 */ EXPR_NODE, /* 5 -- DEPRECATED; use BINOP or UNOP instead */ PROC_CALL_NODE, /* 6 */ TYPE_NODE, /* 7 */ ATOM_NODE, /* 8 */ /* Spec lang Node Types */ SPEC_NODE, /* 9 */ BINOP_NODE, /* 10 */ UNOP_NODE, /* 11 */ TRINOP_NODE, /* 12 */ EXPR_TYPE_NODE /* 13 */ } KindOfNode; /* * Source location struct indicating column, line, and file. This info is set * in the lexer and then passed on to the parser, where it is put into tree * nodes. In this way, the tree itself contains the info that can trace nodes * back to their positions within the source program. */ typedef struct { int abschar; /* Absolute char pos, from beginning of file */ int abscharnnl; /* Absolute char pos, from beginning of file, * not including new lines (for iv text buffers) */ int col; /* Relative char pos, from beginning of line */ int line; /* Line in file */ char *file; /* File */ } SrcLoc; /* * This is the def for the kind of data that can be attached to a parse tree * node. It's generic for now, but may expand in future. */ typedef struct { unsigned int flags; /* Flag bits; defs are below. */ int count; /* A general count field, used when an int is needed. * E.g, for TYPE_NODEs it's the type size; for * IdentLists, its the list length. */ char *astring; /* A general string attachment. E.g, for comment * attachemnt this holds the comment string. */ struct node *n1,*n2;/* General nodep attachments, allowing threading. */ struct node *n3,*n4;/* Two more */ } AttachStruct; /* * Flag bit defs for attachments. */ #define TypeChecked 0x1 /* Set if type tree has been type checked. */ #define StopAt 0x2 /* Set if brkpt set at this node. */ #define IsListParm 0x4 /* Set if type was *'d in parm list. */ /* * Macros to set and check attachment flags. */ #define SetNodeFlag(node, bit) (node->header.attachment.flags |= bit) #define ChkNodeFlag(node, bit) (node->header.attachment.flags & bit) #define SetSubnodeFlag(flags, bit) (flags |= bit) #define ChkSubnodeFlag(flags, bit) (flags & bit) /* * The type nodep is a pointer to a parsetree node. It's used all over the * place, so the name is short and sweet, contrary the author's normal tendency * for mnemonic verbosity. */ typedef struct node *nodep; typedef struct node Node; /* For moving towards the upgrade. */ /* * This is the def of a parse tree node. It's composed of two major parts: a * fixed header and a union of components. The header contains the kind of * node, a more specific node name, a source location, and a general attachment * field. The components part varies for each different kind of node; in * general it contains pointers to the node's children. As noted above, the * header.kind field serves as the tag for the components union. There are a * number of subunions within the components. The header.name field serves as * the tag for these subunions. */ struct node { /* Fixed Header Part: */ struct { KindOfNode kind; /* General kind, such as DECL_NODE */ TokenType name; /* Specific name, such as YOBJ */ SrcLoc loc; /* Starting source location for node */ SrcLoc end_loc; /* Ending source location for node */ AttachStruct attachment; /* Various attachements */ nodep type; /* Partial type, for type inferenceing. This pointer is only used for expr type checking, but it's up in the node header as a convenience, since there's no single generalized EXPR_NODE in which to put the type inference pointer. */ } header; /* Variant Components Part: */ union { /* MODULE_NODE, for any one kind of module. * header.name = YMODULE for program module * YIMPLE for implementation module * YDEF for definition module * YOBJ for spec module */ struct { nodep name; nodep parms; /* For module parms extension */ nodep priority; nodep imports; nodep exports; nodep body; /* This is either a block or defs */ } module; /* BLOCK_NODE, for the bodies of modules and procs */ struct { nodep decls; nodep stmts; } block; /* SPEC_NODE, for bodies of spec modules. */ struct { nodep entities; } spec; /* DECL_NODE, for all types of decls */ struct { union { /* NULL -- no additional fields necessary */ /* YCONST */ struct { nodep name; nodep expr; nodep next; } consta; /* YTYPE */ struct { nodep name; nodep type; nodep next; } type; /* YVAR */ struct { nodep vars; nodep type; nodep init; nodep attrs; nodep next; } var; /* A plain (non-variant) record field (tag = ':' or 'f') */ struct { nodep vars; nodep type; bool isinherited; } field; /* A variant part (tag = YCASE) */ struct { nodep tagfield; nodep casefields; nodep elsefield; } variant; /* An indidual variant field (tag = '|') */ struct { nodep caselabels; nodep fields; } variantfield; /* A case label (tag = YDOTDOT) */ struct { nodep lower; nodep upper; } caselab; /* YPROC */ struct { nodep name; /* empty if proc type */ nodep formals; nodep type; /* empty if not a function */ nodep body; /* empty if proc header or proc type */ } proc; /* Formal parm (tag = '(') */ struct { bool isvar; /* true if this is a var parm */ bool isarray; /* true if this is an open array*/ nodep vars; /* empty if parm in a proc type */ nodep type; } parm; /* NOTE: name tag is '(' */ /* YMODULE */ nodep module; /* Just a pointer to a module node */ /* YIMPORT */ struct { /* an import decl */ nodep items; bool isall; nodep except; } import; /* YEXPORT */ struct { /* an export decl */ nodep names; bool isall; nodep except; } export_; /* YOBJ */ struct { nodep name; nodep type; unsigned int flags; /* isClass, isInstance, isDef */ nodep inheritsfrom; nodep parms; nodep parts; nodep where; nodep ops; nodep eqns; nodep attrs; struct Sym* sym; } obj; /* YOP */ struct { nodep name; unsigned int flags; /* isClass, isInstance, isDef */ nodep inheritsfrom; nodep parts; nodep ins; nodep outs; nodep precond; nodep postcond; nodep attrs; struct Sym* sym; } op; /* YPARTS */ nodep parts; /* YPARENTS */ nodep parents; /* WHERE */ nodep where; /* '=' (where item that resolves a generic type var or typeless let assmnt (but not the former anymore) */ struct { nodep left_operand; nodep right_operand; } eq; /* YOPS (op signature or list thereof) */ struct { nodep list; nodep name; nodep ins; nodep outs; } opsig; /* ':' (a name/type or name/value pair) */ struct { nodep name; char colon; /* non-null for "Name:" construct */ nodep value; nodep initvalue; } attr; /* YASSMNT (an initialized decl, parm or local; we could just use STMT_NODE for this, but it would be a bit kludgy. */ struct { bool islist; /* For list parms, ease of parsing */ bool iscoarity; /* For doing the right thing with a * list parm; see EnterOperation thence * BuildCompeType1. */ nodep decl; nodep init; } initdecl; /* YPRE (unbundled pre/post cond decl -- NOT CURRENTLY USED) */ struct { nodep sig; nodep precond; nodep postcond; } prepost; /* YPRE */ struct { nodep expr; struct Symt *symtab; } pre; /* YPOST */ struct { nodep expr; struct Symt *symtab; } post; /* YEQUATIONS (a set of equation decls with opt var decls) */ struct { nodep vars; nodep eqns; struct Symt *symtab; } eqns; /* YACTIONS (a set of action routine decls */ nodep actions; /* YFORALL or YEXISTS (a quantifier scope and expr body) 8nov01 Note: Scope currently not used. Reenabled 9nov01. */ struct { nodep vars; nodep in; nodep expr; struct Symt *symtab; } quant; /* YLET (an element in a let exprlist) */ struct { nodep names; nodep expr; nodep type; nodep in; /* ML-style body, not currently used */ } let; /* YEQEQ (bundled or unbundled equation) */ struct { nodep lhs; nodep rhs; } eqn; /* YAXIOM or YTHEOREM */ struct { nodep name; nodep expr; nodep attrs; struct Symt *symtab; } formaldef; /* YINPUTS */ nodep ins; /* YOUTPUTS */ nodep outs; /* '>' (an executable expression, amongst decls) */ nodep expr; } kind; nodep next; nodep prev; } decl; /* STMT_NODE, for an assignment stmt */ struct { union { /* NULL stmt and EXIT stmt -- no additional fields necessary */ /* YASSMNT_OP */ struct { nodep var; nodep expr; } assmnt; /* YPROCEDURE */ nodep proccallstmt; /* ptr to a PROC_CALL_NODE It's done this way so next field can be handled uniformly for all stmts. */ /* YIF */ struct { nodep expr; nodep thenpart; nodep elsifparts; /* empty if no else */ nodep elsepart; /* empty if no else */ } ifstmt; /* YELSIF */ struct { nodep expr; nodep thenpart; } elsif; /* YCASE */ struct { nodep expr; nodep cases; nodep elsepart; /* empty if no else */ struct Symt *symtab;/* hash tab of case label vals */ } casestmt; /* YOF */ /* a labeled stmtseq */ struct { nodep labellist; nodep stmtseq; } ofpart; /* YWHILE */ struct { nodep expr; nodep body; } whilestmt; /* YREPEAT */ struct { nodep body; nodep expr; } repeatstmt; /* YLOOP */ struct { nodep body; } loopstmt; /* YFOR */ struct { nodep var; nodep startexpr; nodep endexpr; nodep byexpr; nodep body; } forstmt; /* YWITH */ struct { nodep desig; nodep body; } withstmt; /* YRETURN */ nodep returnstmt; /* holds return expr, if any */ } kind; nodep next; nodep prev; } stmt; /* EXPR_LIST_NODE, for stringing together expr's without having to put * a frequently wasted next field in expr nodes themselves. Also * stores the expr list scope symtab, and the type tree for expr lists * that represent tuple value construction. Both of the latter fields * are used by the interpreter. */ struct { nodep expr; nodep next; struct Symt *symtab; nodep type; } exprlist; /* EXPR_TYPE_NODE */ struct { nodep type; nodep next; } exprtype; /* UNOP_NODE, unary operator */ struct { nodep operand; } unop; /* BINOP_NODE, binary operator */ struct { nodep left_operand; nodep right_operand; } binop; /* EXPR_NODE, for both binary and unary operators; DEPRECATED; use BINOP or UNOP instead */ struct { nodep left_operand; nodep right_operand; /* NULL if unary op */ } expr; /* TRINOP_NODE, trinary operator (e.g., if-then-else expr) */ struct { nodep left_operand; nodep middle_operand; nodep right_operand; } trinop; /* PROC_CALL_NODE, for a proc call expr; the returns field is used in validation invocations. */ struct { nodep desig; nodep actuals; nodep returns; } proccall; /* TYPE_NODE, for a type structure */ struct { union { /* ';' (an opaque type) */ /* NULL -- a forward ref to a not-yet resolved type. */ nodep resolved; /* Yident */ struct { nodep name; /* atom node */ nodep type; /* type node */ } ident; /* '(' */ struct { nodep idents; /* an enumeration type */ int size; } enumtype; /* '[' */ struct { /* a subrange type */ nodep basetype; /* the basetype */ nodep lower; nodep upper; int lowerval; int upperval; } subrange; /* YARRAY */ struct { /* an array type */ nodep bound; /* the single checkable bound */ nodep bounds; /* the declared list of bounds */ int lowerboundval; /* the int value of lower bound */ int normalizedubval;/* the n in [0..n] bounds */ nodep basetype; /* the base type */ bool anon_base; /* true if bastype is anonyous union */ } arraytype; /* YRECORD or YOR */ struct { /* a record type */ int numfields; struct Symt *fieldstab; nodep fields; } record; /* YSET */ struct { nodep basetype; } settype; /* YPOINTER */ struct { nodep basetype; } pointer; /* YPROCEDURE */ struct { /* a procedure type */ nodep formals; struct Sym *formalchain; nodep type; } proc; /* YOP */ struct { struct Sym* entry; nodep ins; nodep outs; } op; /* ')' */ struct { /* a declared procedure's type; */ struct Sym *formalchain; /* see chkIdent and parmCompat */ nodep type; /* for use of this type */ } dproc; /* YMODULE */ struct Sym *module; /* YPARTS */ struct { /* subcomponents */ nodep expr; struct Symt *parts; int references; int dimensions; } parts; /* '\'' a literal type */ struct { /* A literal type, i.e., "the T X" */ nodep type; /* for ident type T */ nodep value; /* and literal value X */ } lit; /* '\'' -- DEPRECATED as sym lit type, replaced with lit type */ char* symlit; /* The symlit string name */ } kind; struct Symt *symtab; ValTag tag; char* resolvedname; /* The "lowest" ident name in a resolved type; * necessary for fmsl-to-java codegen, even * though it might seem not, given the mnemonic * and commentary for ResolveToBaseIdentType; * whatever. */ bool isDerivedIdentType; bool isTopLevelNameTypePair; nodep name; /* Name of name/type pair for parenthszed type * value. */ nodep origname; /* For resolved ident types, and resolved * instances, etc, this is the original * i.e., pre-resolution, ident type name. */ nodep whereparent; /* For instantiated types, this is the * original generic parent, so that subtype * compat can see that an instantiated type is * subtype compat with the same types with * which its generic parent is subtype compat. */ int size; /* Size measured in number of components, * non-transitive. */ int totalsize; /* Total size measured in transitive number of components. */ /* Not currently used; it's an alternative to the above lit type rep; will be removed if it remains unused. Value* litval; // Non-null if this is an atomic or constructed // literal type, i.e., one of int, real, bool, // str, nil, or recursively, [literal, ...] or // {literal, ...}. */ } type; /* ATOM_NODE, for one or more atoms, where atom includes qident, ident, and atomic literal values. Note that header.name is the tag for these. */ struct { union { int integer; float real; char *text; char character; char *string; char *symlit; char nilval; } val; nodep next; nodep next2; /* When two kinds of listing is needed, as in qualidents in a name list. */ nodep prev; nodep tail; /* Quick access to last elem in list. */ nodep parms; /* For parameterized type instantiations */ } atom; } components; }; /* end of struct node */ /** * Construction functions, called primarily for parser.y action routines. */ Node* NewNode(KindOfNode kind, TokenType name, SrcLoc loc); void SetSpecUnitBody(Node* heading, Node* entityspec); /** * Access functions, called extensively from the type checker, and elsewhere. */ SrcLoc GetNodeSrcLoc(Node* t); Node* GetModuleName(Node* t); Node* GetDeclNext(Node* t); Node* GetArrayBaseType(Node* t); int GetRecordTypeNumFields(Node* t); Node* GetFieldDeclVars(Node* t); Node* GetFieldDeclType(Node* t); struct Symt* GetRecordTypeFieldsTab(Node* t); Node* GetRecordTypeFields(Node* t); Node* GetWhereLHS(Node* t); Node* GetWhereRHS(Node* t); Node* GetIdentTypeName(Node* t); char* GetAtomTextVal(Node* t); /** * Set functions. */ void SetIdentTypeType(Node* t, Node* type); void SetArrayBaseType(Node* t, Node* type); void SetRecordType(Node* t, int numfields, struct Symt* fieldstab, Node* fields); /** * Specialized traversal functions. */ Node* ThreadIdentAtoms(Node* t, char* name); /* * Thread all of the ident atoms in the given tree of the given name. If * name is null, thread all ident atoms. */ bool EqualIdentAtoms(Node* t1, Node* t2); /* * Return true if the text parts of the given two ident atoms are streq. */ /** * Copy functions. */ /* * Shallow copy. */ Node* ShallowCopyNode(Node* t); #endif