\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename ga68-internals.info @include gcc-common.texi @synindex tp cp @settitle GNU Algol 68 Compiler Internals @c %**end of header @c %** start of document @copying Copyright @copyright{} 2025 Jose E. Marchesi. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. @end copying @ifinfo @dircategory Software development @direntry * ga68-internals: (ga68-internals). The GNU Algol 68 Compiler Internals. @end direntry This file documents the internals of the GNU Algol 68 compiler, (@command{ga68}). @insertcopying @end ifinfo @c Macro for bold-tags. In TeX and HTML they expand to proper bold words, @c in other formats it resorts to upper stropping. @iftex @macro B{tag} @strong{\tag\} @end macro @end iftex @ifhtml @macro B{tag} @strong{\tag\} @end macro @end ifhtml @ifnottex @ifnothtml @macro B{tag} @sc{\tag\} @end macro @end ifnothtml @end ifnottex @setchapternewpage odd @titlepage @title GNU Algol 68 Internals @versionsubtitle @author Jose E. Marchesi @page @vskip 0pt plus 1filll @sp 1 @insertcopying @end titlepage @summarycontents @contents @page @ifnottex @node Top @top Introduction @cindex Introduction This manual documents (some of) the internals of @command{ga68}, the GNU Algol 68 compiler. @menu * Scope Checking:: Scope checking in assignation. * Storage Management:: Management of run-time storage. * Lowering Declarations:: Mapping external objects to internal objects. * Lowering Assignations:: Superceding the value referred by a name. * GNU Free Documentation License:: How you can copy and share this manual. * Index:: Index of this documentation. @end menu @end ifnottex @c --------------------------------------------------------------------- @c Scope Checking @c --------------------------------------------------------------------- @node Scope Checking @chapter Scope Checking Static scope checking: pass. Dynamic scope checking: run-time call. @c --------------------------------------------------------------------- @c Storage Management @c --------------------------------------------------------------------- @node Storage Management @chapter Storage Management This chapter discusses the run-time management of internal objects in Algol 68. First, a conceptual model is presented that describes the restrictions as mandated by the Report. The storage implied by the lowered GENERIC entities, as described in the previous chapter, shall match the storage of the conceptual model. @menu * Storage Structure of Objects:: * Copying of Objects:: * The Stack:: * The Heap:: @end menu @node Storage Structure of Objects @section Storage Structure of Objects The internal objects which are the values in an Algol 68 program may consist on a hierarchy of memory locations, which may not be contiguous. This hierarchy of memory locations is the storage structure of the object, and is not concerned by the particular bit-patterns stored. Simple values. Names. Multiple values. Structured values. Values of united modes. @node Copying of Objects @section Copying of Objects @node The Stack @section The Stack XXX @node The Heap @section The Heap @itemize @minus @item A value that has rows and gets returned by a procedure shall be allocated on the stack. @item A copy of the right hand side is made before assigning it to the left hand side. This copy is always allocated in the heap, because the scope of the left hand side may be older than the scope of the right hand side. This happens when assigning to a global variable. @item A trimmer of a name. This is because the trimmed multiple may be allocated on the heap, and the trim shall have the same scope than the trimmed multiple. @end itemize @c --------------------------------------------------------------------- @c Internal Objects @c --------------------------------------------------------------------- @node Lowering Declarations @chapter Lowering Declarations This chapter describes the mapping between external objects declared in identity and variable declarations and the internal objects that are the result of lowering the external objects in the parse tree into GENERIC entities. @menu * Identity Declarations:: @code{@B{amode} xxx = init value} * Variable Declarations:: @code{@B{amode} xxx [:= init value]} * Procedure Identity Declarations:: @code{@B{proc} xxx = routine text} * Procedure Variable Declarations:: @code{@B{proc} xxx := routine text} * Operator Brief Declarations:: @code{@B{op} @B{xxx} = routine text} * Operator Declarations:: @code{@B{op}(...)@B{amode} @B{xxx} = routine text} * Applied Identifiers:: @end menu @node Identity Declarations @section Identity Declarations An identity declaration with the form: @example @B{c} part 1 @B{c} @B{amode} defining_identifier = unit; @B{c} part 2 @B{c} @end example @noindent Introduces the identifier @code{defining_identifier} in the current range and ascribes a copy of the value yielded by @code{unit} to it. Once established, the relationship between an identifier and the value ascribed to it is constant and it cannot change during the reach of the identifier. The ascribed unit can be any unitary clause, and its elaboration can be arbitrarily complicated. In particular, it is not required to be a compile-time constant. @code{@B{amode}} determines the mode of the value yielded by the unit, and the unit is elaborated in a strong context. An identity declaration like the above, where @code{@B{amode}} is not a procedure mode (@xref{Procedure Identity Declarations}) is lowered into: @itemize @bullet @item A @code{VAR_DECL} with name @code{defining_identifier}, type @code{CTYPE (@B{amode})} and initial value @code{@B{amode}(@B{skip})} that gets chained into the declarations list of the current block. @item A @code{DECL_EXPR} that gets prepended in the current statement's list. @item A @code{MODIFY_EXPR} setting the @code{VAR_DECL} to a copy of the lowering of @code{unit}, @code{a68_low_dup (unit)}. @end itemize @noindent Schematically: @example BIND_EXPR (BLOCK (DECLS: ... -> VAR_DECL (defining_identifier, INITIAL=SKIP))) STMT_LIST | +-- DECL_EXPR (defining_identifier) | | @B{c} part 1 @B{c} | +-- MODIFY_EXPR (defining_identifier, unit) | | @B{c} part 2 @B{c} | @end example The reason why the @code{VAR_DECL} is initialized to @code{@B{skip}} and then set to the initial @code{unit} specified in the source line is that the Report specifies that Algol 68 identifiers can be used before they are defined provided we are in the right range, but in that case the value ascribed to the identifier is ``undefined''. Accessing an ``undefined'' value in traditional Algol 68 implementations would lead to a run-time error (these implementations used a special value to denote undefined, such as @code{F00L}) but in GNU Algol 68 the ``undefined'' value is always @code{@B{skip}} which, if not terribly useful in most cases, is at least well defined in this implementation and doesn't lead to an error. Identity declarations are the Algol 68 way of defining constants, and one may wonder why we are not using @code{CONST_DECL} instead of @code{VAR_DECL}. The reason is that @code{CONST_DECL} is really only intended for integral values in C enums, and the @code{@B{amode}} in the identity declaration can really be any mode, from simple integers or characters to fairly complicated structured modes, which may involve also rows and united modes. Whether the @code{VAR_DECL} will lead to allocating storage on the stack depends on the nature of the mode and the way the identifier is used in the program: whether its address is taken, etc. @node Variable Declarations @section Variable Declarations A variable declaration with the form: @example [@B{loc}|@B{heap}] @B{amode} defining identifier [:= unit]; @end example @noindent Is in principle equivalent to the identity declaration: @example @B{ref} @B{amode} defining identifier = [@B{loc}|@B{heap}] @B{amode}; @end example @noindent In both cases the object ascribed to the defining identifier is of mode @code{@B{ref} @B{amode}}. The ascribed object is a name which is created by a generator implied in the actual declarer in the variable declaration case, and an explicit generator in the initialization expression in the identity declaration case. However, in this compiler these two cases are handled differently in order to reduce the amount of both indirect addressing and of storage: @itemize @bullet @item The variable declaration @code{[@B{loc}|@B{heap}] @B{amode} foo} lowers into a @code{VAR_DECL} with type @code{CTYPE (amode)} provided that the generator is @code{@B{loc}} and that the type contains no rows. Accessing the variable will then involve direct addressing, and when its address is required an @code{ADDR_EXPR} shall be used. @item The identity declaration @code{@B{ref} @B{amode} foo = @B{loc} @B{amode}} lowers into a @code{VAR_DECL} with type @code{*CTYPE (amode)}. Accessing the variable will then involve indirect addressing: it is effectively a pointer. @end itemize This optimization introduces the complication that an expression (the @code{VAR_DECL}) whose type is TYPE can appear in a place where *TYPE is expected, depending on the context and the r-value and l-value interpretation of the @code{VAR_DECL}. The function @code{a68_consolidate_ref} is used in several parts of the lowering pass to guarantee a given name is an address regardless of how it was initialized. @node Procedure Identity Declarations @section Procedure Identity Declarations XXX @node Procedure Variable Declarations @section Procedure Variable Declarations XXX @node Operator Brief Declarations @section Operator Brief Declarations XXX @node Operator Declarations @section Operator Declarations XXX @node Applied Identifiers @section Applied Identifiers XXX @c --------------------------------------------------------------------- @c Lowering Assignations @c --------------------------------------------------------------------- @node Lowering Assignations @chapter Lowering Assignations Scope checking: @itemize @bullet @item If static scope checking is relevant and OK, then just perform assignation. @item If static scope checking is relevant and not OK, a compile-time error will have already being emitted. @item If static scope checking is not relevant, perform dynamic scope checking: each time a name, a routine or a format of the data structure is assigned, its dynamic scope (scope%_si) is compared with the one of the destination (scope%_d). A run-time error message is provided in case scope%_d < scope%_si. @end itemize @c --------------------------------------------------------------------- @c GNU Free Documentation License @c --------------------------------------------------------------------- @include fdl.texi @c --------------------------------------------------------------------- @c Index @c --------------------------------------------------------------------- @node Index @unnumbered Index @printindex cp @bye