]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
a68: support FFI with C via formal holes
authorJose E. Marchesi <jemarch@gnu.org>
Sat, 24 Jan 2026 19:10:10 +0000 (20:10 +0100)
committerJose E. Marchesi <jemarch@gnu.org>
Thu, 29 Jan 2026 00:37:57 +0000 (01:37 +0100)
This commit adds FFI support to access C variables and call C
functions from Algol 68, using the construct specified by the Modules
and Separated compilation facilities intended to that effect: formal
holes (`nest' constructs).

Briefly put, an `int foo' C variable can be accessed from Algol 68
like:

  int foo = nest C "foo";
  if foo > 10 then ... fi;

A ref to a C variable `int counter', that allows to modify it as well
as read it:

  ref int counter = nest C "&counter";
  counter +:= 1;

The address stored in an `int *ptr' variable, as an Algol 68
reference:

  ref int ptr = nest C "ptr";
  ptr := 100; { Changes the integer pointed by the C ptr }

Calling the standard C `random' function:

  proc long int random = nest C "random";
  if random < 100 then ... fi;

Some tests and an sketchy section in the manual are also included.

Signed-off-by: Jose E. Marchesi <jemarch@gnu.org>
gcc/algol68/ChangeLog

* ga68.vw: Fix grammar for formal holes.
* ga68.texi (Particular programs): New section.
(Comments): Likewise.
* a68.h: Prototypes for a68_is_c_mode, a68_make_fomal_hole_decl,
a68_lower_formal_hole.
* a68-parser-attrs.def (FORMAL_HOLE): New attribute.
(LANGUAGE_INDICANT): Likewise.
* a68-parser-extract.cc (a68_elaborate_bold_tags): Elaborate
language indicants.
* a68-parser-moids-check.cc (mode_check_unit): Check mode in
formal holes.
* a68-low-units.cc (a68_lower_formal_hole): New function.
* a68-low.cc (a68_make_formal_hole_decl): Likewise.
* a68-moids-misc.cc (a68_is_c_mode): Likewise.
* a68-parser-bottom-up.cc (reduce_formal_holes): Likewise.

gcc/testsuite/ChangeLog

* algol68/compile/error-nest-1.a68: New test.
* algol68/compile/nest-c-1.a68: Likewise.
* algol68/compile/error-nest-5.a68: Likewise.
* algol68/compile/error-nest-4.a68: Likewise.
* algol68/compile/error-nest-3.a68: Likewise.
* algol68/compile/error-nest-2.a68: Likewise.

16 files changed:
gcc/algol68/a68-low-units.cc
gcc/algol68/a68-low.cc
gcc/algol68/a68-moids-misc.cc
gcc/algol68/a68-parser-attrs.def
gcc/algol68/a68-parser-bottom-up.cc
gcc/algol68/a68-parser-extract.cc
gcc/algol68/a68-parser-moids-check.cc
gcc/algol68/a68.h
gcc/algol68/ga68.texi
gcc/algol68/ga68.vw
gcc/testsuite/algol68/compile/error-nest-1.a68 [new file with mode: 0644]
gcc/testsuite/algol68/compile/error-nest-2.a68 [new file with mode: 0644]
gcc/testsuite/algol68/compile/error-nest-3.a68 [new file with mode: 0644]
gcc/testsuite/algol68/compile/error-nest-4.a68 [new file with mode: 0644]
gcc/testsuite/algol68/compile/error-nest-5.a68 [new file with mode: 0644]
gcc/testsuite/algol68/compile/nest-c-1.a68 [new file with mode: 0644]

index caaa5bb27acf676465e3bb4c8679b49a3dbad545..4584ff10933bcaf7a7a77ad3342c8aa00e0052c7 100644 (file)
@@ -1238,6 +1238,28 @@ a68_lower_routine_text (NODE_T *p, LOW_CTX_T ctx)
                        func_decl);
 }
 
+/* Lower a formal hole.
+
+      formal hole : formal nest symbol, tertiary ;
+                    formal nest symbol, language indicant, tertiary.
+*/
+
+tree
+a68_lower_formal_hole (NODE_T *p, LOW_CTX_T ctx ATTRIBUTE_UNUSED)
+{
+  NODE_T *str = NEXT_SUB (p);
+  if (IS (str, LANGUAGE_INDICANT))
+    FORWARD (str);
+  gcc_assert (IS (str, TERTIARY));
+  while (str != NO_NODE && !IS (str, ROW_CHAR_DENOTATION))
+    str = SUB (str);
+  gcc_assert (IS (str, ROW_CHAR_DENOTATION));
+
+  char *symbol = a68_string_process_breaks (p, NSYMBOL (str));
+  tree decl = a68_make_formal_hole_decl (p, symbol);
+  return decl;
+}
+
 /* Lower an unit.
 
       unit : assignation; identity relation;
index d13e28a0fc8c2519ea94881220173143d8389b21..dee1a6d26c53afd0fc0e7d24f1dbb376492e29ca 100644 (file)
@@ -631,6 +631,35 @@ a68_make_variable_declaration_decl (NODE_T *identifier,
   return decl;
 }
 
+/* Make an extern declaration for a formal hole.  */
+
+tree
+a68_make_formal_hole_decl (NODE_T *p, const char *extern_symbol)
+{
+  /* The CTYPE of MODE is a pointer to a function.  We need the pointed
+     function type for the FUNCTION_DECL.  */
+  tree type = (IS (MOID (p), PROC_SYMBOL)
+              ? TREE_TYPE (CTYPE (MOID (p)))
+              : CTYPE (MOID (p)));
+
+  gcc_assert (strlen (extern_symbol) > 0);
+  const char *sym = (extern_symbol[0] == '&'
+                    ? extern_symbol + 1
+                    : extern_symbol);
+
+  tree decl = build_decl (a68_get_node_location (p),
+                         VAR_DECL,
+                         get_identifier (sym),
+                         type);
+  DECL_EXTERNAL (decl) = 1;
+  TREE_PUBLIC (decl) = 1;
+  DECL_INITIAL (decl) = a68_get_skip_tree (MOID (p));
+
+  if (extern_symbol[0] == '&')
+    decl = fold_build1 (ADDR_EXPR, type, decl);
+  return decl;
+}
+
 /* Do a checked indirection.
 
    P is a tree node used for its location information.
@@ -1621,6 +1650,9 @@ a68_lower_tree (NODE_T *p, LOW_CTX_T ctx)
     case OR_FUNCTION:
       res = a68_lower_logic_function (p, ctx);
       break;
+    case FORMAL_HOLE:
+      res = a68_lower_formal_hole (p, ctx);
+      break;
     case IDENTITY_RELATION:
       res = a68_lower_identity_relation (p, ctx);
       break;
index cafb04a16ad6e7bd7ce92719be4c21b2ea0b628a..a8817926b886bfd6317282705e7dcaf8f4ac1186 100644 (file)
@@ -1059,7 +1059,7 @@ a68_is_balanced (NODE_T *n, SOID_T *y, int sort)
     {
       bool k = false;
 
-      for (; y != NO_SOID && !k; FORWARD (y)) 
+      for (; y != NO_SOID && !k; FORWARD (y))
        k = (!IS (MOID (y), STOWED_MODE));
 
       if (k == false)
@@ -1189,6 +1189,44 @@ a68_determine_unique_mode (SOID_T *z, int deflex)
     }
 }
 
+/* Whether the given mode M is a valid mode for a C formal hole.  See
+   metaproduction rule 561B in ga68.vw.  */
+
+bool
+a68_is_c_mode (MOID_T *m)
+{
+  if (m == M_VOID || m == M_BOOL || m == M_CHAR)
+    return true;
+  else if (IS_INTEGRAL (m))
+    return true;
+  else if (IS_BITS (m))
+    return true;
+  else if (IS_REAL (m))
+    return true;
+  else if (IS_REF (m))
+    return a68_is_c_mode (SUB (m));
+  else if (IS (m, PROC_SYMBOL))
+    {
+      bool yielded_mode_valid = a68_is_c_mode (SUB (m));
+      bool params_valid = true;
+
+      for (PACK_T *z = PACK (m); z != NO_PACK; FORWARD (z))
+       params_valid &= a68_is_c_mode (MOID (z));
+
+      return yielded_mode_valid && params_valid;
+    }
+  else if (IS_STRUCT (m))
+    {
+      bool fields_valid = true;
+
+      for (PACK_T *z = PACK (m); z != NO_PACK; FORWARD (z))
+       fields_valid &= a68_is_c_mode (MOID (z));
+      return fields_valid;
+    }
+
+  return false;
+}
+
 /* Insert coercion A in the tree.  */
 
 void
index 31fc0d91f7dba809c64173baf1d32893d7c6d11d..e9cadd30cab20a45d95d8412b6b6995aec6ead8c 100644 (file)
@@ -140,6 +140,7 @@ A68_ATTR(FORMAL_BOUNDS_LIST, "list of formal declarer bounds")
 A68_ATTR(FORMAL_DECLARERS, "formal declarers")
 A68_ATTR(FORMAL_DECLARERS_LIST, "list of formal declarers")
 A68_ATTR(FORMAL_DECLARER_MARK, "formal declarer mark")
+A68_ATTR(FORMAL_HOLE, "formal hole")
 A68_ATTR(FORMAL_NEST_SYMBOL, "formal-nest-symbol")
 A68_ATTR(FORMULA, "formula")
 A68_ATTR(FOR_PART, "for-part")
@@ -223,6 +224,7 @@ A68_ATTR(LABEL, "label")
 A68_ATTR(LABELED_UNIT, "labeled unit")
 A68_ATTR(LABEL_IDENTIFIER, "label identifier")
 A68_ATTR(LABEL_SEQUENCE, "label sequence")
+A68_ATTR(LANGUAGE_INDICANT, "language indicant")
 A68_ATTR(LITERAL, "literal")
 A68_ATTR(LOCAL_LABEL, "local label")
 A68_ATTR(LOC_SYMBOL, "loc-symbol")
index 4adf03154929b9a9e670e67f15d2f437c32b6db4..14f914aeb27246d164f7c3c16af115fc957c6cc3 100644 (file)
@@ -135,6 +135,7 @@ static void reduce_basic_declarations (NODE_T *p);
 static void reduce_declaration_lists (NODE_T *p);
 static void reduce_module_texts (NODE_T *p);
 static void reduce_module_text_parts (NODE_T *p);
+static void reduce_formal_holes (NODE_T *p);
 static NODE_T *reduce_dyadic (NODE_T *p, int u);
 
 /* Whether a series is serial or collateral.  */
@@ -687,6 +688,7 @@ reduce_branch (NODE_T *q, enum a68_attribute expect)
          reduce_right_to_left_constructs (p);
          /* Reduce units and declarations.  */
          reduce_basic_declarations (p);
+         reduce_formal_holes (p);
          reduce_units (p);
          reduce_erroneous_units (p);
          if (expect != UNIT)
@@ -1840,10 +1842,41 @@ reduce_tertiaries (NODE_T *p)
     }
 }
 
+/* Reduce formal holes.  */
+
+static void
+reduce_formal_holes (NODE_T *p)
+{
+  for (NODE_T *q = p; q != NO_NODE; FORWARD (q))
+    {
+      bool ahole = false;
+      reduce (q, NO_NOTE, &ahole, FORMAL_HOLE,
+             FORMAL_NEST_SYMBOL, TERTIARY, STOP);
+      reduce (q, NO_NOTE, &ahole, FORMAL_HOLE,
+             FORMAL_NEST_SYMBOL, LANGUAGE_INDICANT, TERTIARY, STOP);
+
+      if (ahole)
+       {
+         /* Check that the tertiary is a row of chars denotation.  */
+         for (NODE_T *s = SUB (q); s != NO_NODE; FORWARD (s))
+           {
+             if (IS (s, TERTIARY)
+                 && !(IS (SUB (s), SECONDARY)
+                      && IS (SUB (SUB (s)), PRIMARY)
+                      && IS (SUB (SUB (SUB (s))), DENOTATION)
+                      && IS (SUB (SUB (SUB (SUB (s)))), ROW_CHAR_DENOTATION)))
+               {
+                 a68_error (s, "expected row char denotation");
+               }
+           }
+       }
+    }
+}
+
 /* Reduce units. */
 
 static void
-reduce_units (NODE_T * p)
+reduce_units (NODE_T *p)
 {
   /* Stray ~ is a SKIP.  */
   for (NODE_T *q = p; q != NO_NODE; FORWARD (q))
@@ -1864,6 +1897,7 @@ reduce_units (NODE_T * p)
       reduce (q, NO_NOTE, NO_TICK, UNIT, SKIP, STOP);
       reduce (q, NO_NOTE, NO_TICK, UNIT, TERTIARY, STOP);
       reduce (q, NO_NOTE, NO_TICK, UNIT, ASSERTION, STOP);
+      reduce (q, NO_NOTE, NO_TICK, UNIT, FORMAL_HOLE, STOP);
     }
 }
 
index 70c0dd74cac87d00d4b36158eff512ccbf129327..4779d3915f4a87b4f7f631dc92bd75738e26b7c2 100644 (file)
@@ -135,7 +135,8 @@ find_tag_definition (TABLE_T *table, const char *name)
     return 0;
 }
 
-/* Fill in whether bold tag is operator, indicant or module indicant.  */
+/* Fill in whether bold tag is operator, indicant, module indicant or language
+   indicant.  */
 
 void
 a68_elaborate_bold_tags (NODE_T *p)
@@ -144,20 +145,31 @@ a68_elaborate_bold_tags (NODE_T *p)
     {
       if (IS (q, BOLD_TAG))
        {
-         switch (find_tag_definition (TABLE (q), NSYMBOL (q)))
+         if (PREVIOUS (q) != NO_NODE
+             && IS (PREVIOUS (q), FORMAL_NEST_SYMBOL))
            {
-           case 0:
-             a68_error (q, "tag S has not been declared properly");
-             break;
-           case INDICANT:
-             ATTRIBUTE (q) = INDICANT;
-             break;
-           case OPERATOR:
-             ATTRIBUTE (q) = OPERATOR;
-             break;
-           case MODULE_INDICANT:
-             ATTRIBUTE (q) = MODULE_INDICANT;
-             break;
+             if (strcmp (NSYMBOL (q), "C") != 0)
+               a68_error (q, "S is not a valid language indication");
+             else
+               ATTRIBUTE (q) = LANGUAGE_INDICANT;
+           }
+         else
+           {
+             switch (find_tag_definition (TABLE (q), NSYMBOL (q)))
+               {
+               case 0:
+                 a68_error (q, "tag S has not been declared properly");
+                 break;
+               case INDICANT:
+                 ATTRIBUTE (q) = INDICANT;
+                 break;
+               case OPERATOR:
+                 ATTRIBUTE (q) = OPERATOR;
+                 break;
+               case MODULE_INDICANT:
+                 ATTRIBUTE (q) = MODULE_INDICANT;
+                 break;
+               }
            }
        }
     }
index a7b02cb19576763a3af92c9268cd2b03a7db80ec..f95f95890f64c8fe9da31c3b8c1bd2a7e23a3ad0 100644 (file)
@@ -1840,6 +1840,53 @@ mode_check_unit (NODE_T *p, SOID_T *x, SOID_T *y)
       mode_check_bool_function (SUB (p), x, y);
       a68_warn_for_voiding (p, x, y, OR_FUNCTION);
     }
+  else if (IS (p, FORMAL_HOLE))
+    {
+      NODE_T *tertiary = NO_NODE;
+
+      for (NODE_T *q = SUB (p); q != NO_NODE; FORWARD (q))
+       {
+         if (IS (q, TERTIARY))
+           {
+             tertiary = q;
+             break;
+           }
+       }
+
+      NODE_T *str = tertiary;
+      while (str != NO_NODE && !IS (str, ROW_CHAR_DENOTATION))
+       str = SUB (str);
+      gcc_assert (IS (str, ROW_CHAR_DENOTATION));
+
+      if (SORT (x) != STRONG)
+       {
+         /* A formal hole should appear in a strong context, and its mode is
+            the goal mode of the context.  */
+         a68_error (p, "formal hole should be in a strong context");
+         a68_make_soid (y, STRONG, M_ERROR, 0);
+       }
+      else if (!a68_is_c_mode (MOID (x)))
+       {
+         /* Additionally, the mode of the formal hole should be amenable to be
+            somehow "translated" to C semantics. */
+         a68_error (p, "formal hole cannot be of mode M", MOID (x));
+         a68_make_soid (y, STRONG, M_ERROR, 0);
+       }
+      else if (NSYMBOL (str)[0] == '&' && !IS_REF (MOID (x)))
+       {
+         /* A C formal whole whose string starts with & requires
+            a ref mode.  */
+         a68_error (p, "formal hole should be a name (ref to a mode)");
+         a68_make_soid (y, STRONG, M_ERROR, 0);
+       }
+      else
+       {
+         SOID_T z;
+         mode_check_unit (tertiary, x, &z);
+         a68_make_soid (y, SORT (x), MOID (x), 0);
+         a68_warn_for_voiding (p, x, y, FORMAL_HOLE);
+       }
+    }
 
   MOID (p) = MOID (y);
 }
index 34090d12c053af84b4a6e8fb458a6ea5c7776ddf..2df79474ea1be54e3df79aab2555bad1d288697c 100644 (file)
@@ -476,6 +476,7 @@ void a68_make_soid (SOID_T *s, int sort, MOID_T *type, int attribute);
 void a68_make_strong (NODE_T *n, MOID_T *p, MOID_T *q);
 void a68_make_uniting_coercion (NODE_T *n, MOID_T *q);
 void a68_make_void (NODE_T *p, MOID_T *q);
+bool a68_is_c_mode (MOID_T *m);
 
 #define A68_DEPREF true
 #define A68_NO_DEPREF false
@@ -810,6 +811,7 @@ tree a68_make_variable_declaration_decl (NODE_T *identifier, const char *module_
 tree a68_make_proc_identity_declaration_decl (NODE_T *identifier, const char *module_name = NULL,
                                              bool indicant = false, bool external = false,
                                              const char *extern_symbol = NULL);
+tree a68_make_formal_hole_decl (NODE_T *p, const char *extern_symbol);
 tree a68_make_anonymous_routine_decl (MOID_T *mode);
 tree a68_get_skip_tree (MOID_T *m);
 tree a68_get_empty (void);
@@ -873,6 +875,7 @@ tree a68_lower_assignation (NODE_T *p, LOW_CTX_T ctx);
 tree a68_lower_routine_text (NODE_T *p, LOW_CTX_T ctx);
 tree a68_lower_generator (NODE_T *p, LOW_CTX_T ctx);
 tree a68_lower_call (NODE_T *p, LOW_CTX_T ctx);
+tree a68_lower_formal_hole (NODE_T *p, LOW_CTX_T ctx);
 tree a68_lower_unit (NODE_T *p, LOW_CTX_T ctx);
 
 /* a68-low-generator.c  */
index 7ee12ffb05053542e2178d8bd618e65843bcfb5c..6798b3a3761fdb27f107bb761767c4519e3c309d 100644 (file)
@@ -108,6 +108,7 @@ variable @B{C}} is a pseudo-comment.
 @menu
 * Invoking ga68::               How to run the compiler.
 * Composing programs::          Packets, modules, holes, particular programs.
+* Foreign Function Interface::  Communicating with other languages via holes.
 * Comments and pragmats::       Comments and pragmas.
 * Hardware representation::     Representation of programs.
 * Standard prelude::            Standard modes, operators, etc.
@@ -407,6 +408,7 @@ modules and separated compilation support provided by this compiler.
 @menu
 * Packets::                  Compilation units.
 * Modules::                  Facilities for bottom-up programming.
+* Holes::                    Facilities for top-down programming.
 * Particular programs::      The main program.
 * The standard environment:: Environment conforming a full program.
 @end menu
@@ -997,6 +999,22 @@ identify user-defined modes and operators, such as @code{JSON},
 
 XXX
 
+@node Holes
+@section Holes
+@cindex holes
+
+@dfn{Holes} are part of the modules system and are a mechanism used
+for two main purposes:
+
+@itemize @minus
+@item Top-down programming.
+@item Communication with other programming languages.
+@end itemize
+
+
+At the moment only the second kind of holes are supported by this
+compiler.  @xref{Foreign Function Interface}.
+
 @node Particular programs
 @section Particular programs
 @cindex particular program
@@ -1137,6 +1155,162 @@ involved then the user-prelude is empty.
 Subsequent sections in this manual include a detailed description of
 the contents of these preludes.
 
+@node Foreign Function Interface
+@chapter Foreign Function Interface
+@cindex FFI
+
+It is possible to call functions written in other programming
+languages, and also to access variables and constants, using the
+following form of @dfn{formal hole}:
+
+@example
+@B{nest} @B{language_indicant} "row char denotation"
+@end example
+
+@noindent
+Where @B{language_indicant} is a bold word indicating the programming
+language we are communicating with and the row char denotation
+specifies the entity we are accessing.  The interpretation of the
+later depends on the specific language.
+
+The formal hole construction is an @dfn{unit}, and can only appear in
+a strong context.  It's mode is the mode expected by the strong
+context.  For example, in the following declaration:
+
+@example
+int counter = nest C "_counter";
+@end example
+
+@noindent
+The mode of the formal hole is @code{@B{int}}, since it is in a strong
+context (the actual parameter of an identity declaration) in which an
+integral value is expected.  Likewise, in:
+
+@example
+proc long int func = nest C "random";
+@end example
+
+@noindent
+The expected mode is a procedure that gets no arguments and returns a
+@code{@B{long} @B{int}}.
+
+The set of modes that are accepted in the formal holes depend on the
+specific language we are communicating to.  These are usually
+restricted because the compiler may not know how to translate certain
+Algol 68 concepts into the foreign language ones.  A compile time
+error is issued if an invalid mode is required.  Specifics are
+described in the sections below.
+
+It is important to note that the language-indicants like @code{@B{C}}
+or @code{@B{Fortran}} are still available to be used as mode
+indicants, operators or module indicants: they only qualify as
+language indicants when they appear in a formal hole (@code{@B{nest}})
+construct.
+
+The following subsections document the specific supported foreign
+languages.
+
+@menu
+* Communicating with C::     Accessing C variables and functions.
+@end menu
+
+@node Communicating with C
+@section Communicating with C
+
+The language indicant @code{@B{C}} is used to access C variables and
+calling C functions:
+
+@example
+@B{nest} @B{C} "[&]symbol"
+@end example
+
+The row char denotation should contain a symbol corresponding to a C
+variable or function, optionally preceded by an ampersand @code{&}.
+It is the responsibility of the programmer to make sure the specified
+symbol actually corresponds to an entity with the right type.  In case
+a malformed symbol is specified it will very likely result in an
+assembler error.
+
+For example, this is how we can access a C variable as an Algol 68
+constant:
+
+@example
+@B{int} counter = @B{nest} @B{C} "counter";
+
+@B{if} counter = 0
+@B{then} ... @B{fi};
+@end example
+
+If we wanted to be able to change the value of the C variable
+@code{counter} then we need to add a leading ampersand to the row
+denotation, and of course change the mode on the Algol 68 side to a
+@code{@B{ref} @B{int}}:
+
+@example
+@B{ref} @B{int} counter = @B{nest} @B{C} "&counter";
+
+counter +:= 1;
+@end example
+
+If we wanted to access a C pointer variable @code{int *ptr} as an
+Algol 68 name we could do:
+
+@example
+@B{ref} @B{int} ptr = @B{nest} @B{C} "ptr";
+
+ptr := 100; @{ Changes the value pointed by the C pointer ptr,
+              not of ptr itself @}
+@end example
+
+If we wanted to call the standard POSIX functions @code{random} and
+@code{srandom} we could do:
+
+@example
+@B{proc} @B{long} @B{int} random = @B{nest} @B{C} "random";
+@B{proc}(@B{bits})@B{void} srandom = @B{nest} @B{C} "srandom";
+
+@B{if} random < 100 @B{then} ... @B{fi}
+@end example
+
+The modes accepted in a formal hole for C are:
+
+@table @asis
+@item @code{@B{void}}
+As C @code{void}.
+@item @code{@B{bool}}
+As C @code{bool}.
+@item @code{@B{char}}
+As C 32-bit integer.
+@item @code{@B{int}}
+As C @code{int}.
+@item @code{@B{short} @B{int}}
+As C @code{short}.
+@item @code{@B{short} @B{short} @B{int}}
+As C @code{char}.
+@item @code{@B{long} @B{int}}
+As C @code{long} or as C @code{int}.
+@item @code{@B{long} @B{long} @B{int}}
+As C @code{long long} or as C @code{long} or as C @code{int}.
+@item @code{@B{bits}}
+As C @code{unsigned int}.
+@item @code{@B{short} @B{bits}}
+As C @code{unsigned short}.
+@item @code{@B{short} @B{short} @B{bits}}
+As C @code{unsigned char}.
+@item @code{@B{long} @B{bits}}
+As C @code{unsigned long} or as C @code{unsigned int}.
+@item @code{@B{long} @B{long} @B{bits}}
+As C @code{unsigned long long} or as C @code{unsigned long} or as C @code{unsigned int}.
+@item @code{@B{real}}
+As C @code{float}
+@item @code{@B{long} @B{real}}
+As C @code{double}
+@item @B{proc} with accepted formal parameter modes and yielded mode
+As the corresponding C functions.
+@item Structs with fields of accepted modes
+As the corresponding C structs.
+@end table
+
 @node Comments and pragmats
 @chapter Comments and pragmats
 
index 54511c927fbe7a708400459e3df4562ff22a7dba..77acf0f95d6c8ddcec28f4267a279cf4e42c7350 100644 (file)
@@ -1217,12 +1217,14 @@ a) strong MOID NEST skip{5A} : skip{94f} token.
 
 5.6.1 Syntax
 
-A) LANGUAGE :: algol sixty eight ; fortran ; c language ; cpp language.
-B) ALGOL68 :: algol sixty eight.
-C) FORTRAM :: fortran.
-D) CLANG :: c language.
-E) CPPLANG :: cpp language.
-F) DLANG :: d language.
+A) LANGUAGE :: algol sixty eight ; c language.
+B) CODE :: CAIN ; CLAN ; reference to CAIN ;
+           procedure with PERFORMERS yieling COID ;
+           procedure yielding COID.
+C) PERFORMERS :: PERFORMER ; PERFORMERS PERFORMER.
+D) PERFORMER :: CODE parameter.
+E) COID :: CODE ; void.
+F) CAIN :: real ; long real ; integral ; BITS ; boolean ; char.
 
 a) strong MOID NEST virtual hole{5A} :
      virtual nest symbol, strong MOID NEST closed clause{31a}.
@@ -1233,15 +1235,12 @@ c) MOID NEST actual hole{A6a} :
      strong MOID NEST ENCLOSED clause{31a,33a,c,34a,35a,36a,-}.
 d) hole indication{b} :
      character denotation{814a} ; row of character denotation{83a}.
-e) MOID ALGOL68 indication{b} : EMPTY.
-f) MOID FORTRAN indication{b} : bold letter f letter o letter r letter t
-                                     letter r letter a letter n token.
-g) MOID CLANG indication{b} : bold letter c letter l letter a letter n
-                                   letter g.
-e) MOID CPPLANG indication{b} : bold letter c letter p letter p letter l
-                                     letter a letter n letter g.
-f) MOID DLANG indication{b} : bold letter d letter l letter a letter n
-                                   letter g.
+e) MOID algol sixty eight indication{b} : EMPTY.
+f) COID c language indication{b} : bold letter c token.
+
+{ COID-c-language-indication restricts the `MOID's to the set for
+  which a C equivalence can be immediately determined by the compiler
+  without any additional information.  }
 
 { Since no representation is provided for the virtual-nest-symbol, the
   user is unable to construct virtual-holes for himself, but a
diff --git a/gcc/testsuite/algol68/compile/error-nest-1.a68 b/gcc/testsuite/algol68/compile/error-nest-1.a68
new file mode 100644 (file)
index 0000000..4bb32db
--- /dev/null
@@ -0,0 +1,5 @@
+begin int foo =
+         nest XYZ { dg-error "valid language" }
+         "foo";
+      skip
+end
diff --git a/gcc/testsuite/algol68/compile/error-nest-2.a68 b/gcc/testsuite/algol68/compile/error-nest-2.a68
new file mode 100644 (file)
index 0000000..30e2d1d
--- /dev/null
@@ -0,0 +1,8 @@
+begin int foo =
+         nest C
+              200; { dg-error "denotation" }
+      int bar =
+         nest
+              3.14; { dg-error "denotation" }
+      skip
+end
diff --git a/gcc/testsuite/algol68/compile/error-nest-3.a68 b/gcc/testsuite/algol68/compile/error-nest-3.a68
new file mode 100644 (file)
index 0000000..7211880
--- /dev/null
@@ -0,0 +1,4 @@
+begin int foo = 10 + (nest C "foo"); { dg-error "strong context" }
+      int bar = 20 + (nest "bar");   { dg-error "strong context" }
+      assert (foo = 10)
+end
diff --git a/gcc/testsuite/algol68/compile/error-nest-4.a68 b/gcc/testsuite/algol68/compile/error-nest-4.a68
new file mode 100644 (file)
index 0000000..ef40c38
--- /dev/null
@@ -0,0 +1,8 @@
+begin string s =
+         nest C "lala"; { dg-error "" }
+      union(int,real) x =
+         nest C "x"; { dg-error "" }
+      proc(string)bool y =
+         nest C "y"; { dg-error "" }
+      skip
+end
diff --git a/gcc/testsuite/algol68/compile/error-nest-5.a68 b/gcc/testsuite/algol68/compile/error-nest-5.a68
new file mode 100644 (file)
index 0000000..e5214f6
--- /dev/null
@@ -0,0 +1,3 @@
+begin int lala = nest C "&lala"; { dg-error "name" }
+      skip
+end
diff --git a/gcc/testsuite/algol68/compile/nest-c-1.a68 b/gcc/testsuite/algol68/compile/nest-c-1.a68
new file mode 100644 (file)
index 0000000..4a0216d
--- /dev/null
@@ -0,0 +1,4 @@
+begin proc real myrandom = nest C "_libga68_random";
+      real r = myrandom;
+      assert (r >= 0.0 AND r <= 1.0)
+end