From: Jose E. Marchesi Date: Sat, 24 Jan 2026 19:10:10 +0000 (+0100) Subject: a68: support FFI with C via formal holes X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e41a344ccfab6fe2ac23f958eed8d69b6171890f;p=thirdparty%2Fgcc.git a68: support FFI with C via formal holes 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 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. --- diff --git a/gcc/algol68/a68-low-units.cc b/gcc/algol68/a68-low-units.cc index caaa5bb27ac..4584ff10933 100644 --- a/gcc/algol68/a68-low-units.cc +++ b/gcc/algol68/a68-low-units.cc @@ -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; diff --git a/gcc/algol68/a68-low.cc b/gcc/algol68/a68-low.cc index d13e28a0fc8..dee1a6d26c5 100644 --- a/gcc/algol68/a68-low.cc +++ b/gcc/algol68/a68-low.cc @@ -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; diff --git a/gcc/algol68/a68-moids-misc.cc b/gcc/algol68/a68-moids-misc.cc index cafb04a16ad..a8817926b88 100644 --- a/gcc/algol68/a68-moids-misc.cc +++ b/gcc/algol68/a68-moids-misc.cc @@ -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 diff --git a/gcc/algol68/a68-parser-attrs.def b/gcc/algol68/a68-parser-attrs.def index 31fc0d91f7d..e9cadd30cab 100644 --- a/gcc/algol68/a68-parser-attrs.def +++ b/gcc/algol68/a68-parser-attrs.def @@ -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") diff --git a/gcc/algol68/a68-parser-bottom-up.cc b/gcc/algol68/a68-parser-bottom-up.cc index 4adf0315492..14f914aeb27 100644 --- a/gcc/algol68/a68-parser-bottom-up.cc +++ b/gcc/algol68/a68-parser-bottom-up.cc @@ -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); } } diff --git a/gcc/algol68/a68-parser-extract.cc b/gcc/algol68/a68-parser-extract.cc index 70c0dd74cac..4779d3915f4 100644 --- a/gcc/algol68/a68-parser-extract.cc +++ b/gcc/algol68/a68-parser-extract.cc @@ -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; + } } } } diff --git a/gcc/algol68/a68-parser-moids-check.cc b/gcc/algol68/a68-parser-moids-check.cc index a7b02cb1957..f95f95890f6 100644 --- a/gcc/algol68/a68-parser-moids-check.cc +++ b/gcc/algol68/a68-parser-moids-check.cc @@ -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); } diff --git a/gcc/algol68/a68.h b/gcc/algol68/a68.h index 34090d12c05..2df79474ea1 100644 --- a/gcc/algol68/a68.h +++ b/gcc/algol68/a68.h @@ -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 */ diff --git a/gcc/algol68/ga68.texi b/gcc/algol68/ga68.texi index 7ee12ffb050..6798b3a3761 100644 --- a/gcc/algol68/ga68.texi +++ b/gcc/algol68/ga68.texi @@ -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 diff --git a/gcc/algol68/ga68.vw b/gcc/algol68/ga68.vw index 54511c927fb..77acf0f95d6 100644 --- a/gcc/algol68/ga68.vw +++ b/gcc/algol68/ga68.vw @@ -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 index 00000000000..4bb32dba66c --- /dev/null +++ b/gcc/testsuite/algol68/compile/error-nest-1.a68 @@ -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 index 00000000000..30e2d1d3022 --- /dev/null +++ b/gcc/testsuite/algol68/compile/error-nest-2.a68 @@ -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 index 00000000000..72118806807 --- /dev/null +++ b/gcc/testsuite/algol68/compile/error-nest-3.a68 @@ -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 index 00000000000..ef40c385766 --- /dev/null +++ b/gcc/testsuite/algol68/compile/error-nest-4.a68 @@ -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 index 00000000000..e5214f6be47 --- /dev/null +++ b/gcc/testsuite/algol68/compile/error-nest-5.a68 @@ -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 index 00000000000..4a0216d7be1 --- /dev/null +++ b/gcc/testsuite/algol68/compile/nest-c-1.a68 @@ -0,0 +1,4 @@ +begin proc real myrandom = nest C "_libga68_random"; + real r = myrandom; + assert (r >= 0.0 AND r <= 1.0) +end