[m-rev.] for review: context macro thingies

Peter Wang novalazy at gmail.com
Thu Apr 3 11:23:18 AEDT 2008


On 2008-04-02, Julien Fischer <juliensf at csse.unimelb.edu.au> wrote:
>
> On Tue, 1 Apr 2008, Peter Wang wrote:
>
>> XXX think of a better name
>
> Implementation-defined literals.

Ok.

>> XXX are further changes to prog_rep.cons_id_rep required?
>
> Shouldn't they all be expanded out in the debugger?

Yes, they would have been expanded out.

>> Estimated hours taken: 15
>> Branches: main
>>
>> Add support for "compiler-defined literals" $file, $line, $module, $pred,
>> $grade which are replaced constants by the compiler.
>>
>> library/lexer.m:
>> 	Add a new type of token.
>>
>> 	Read "$foo" as a `compiler_defined' token instead of two name tokens.
>>
>> library/term.m:
>> library/term_io.m:
>> 	Add a new type of constant, `compiler_defined'.
>>
>> library/parser.m:
>> 	Handle `compiler_defined' tokens from the lexer.
>>
>> compiler/check_hlds.m:
>> compiler/compiler_defined_literals.m:
>> compiler/mercury_compile.m:
>> 	Add a new pass to replace compiler-defined literals in program clauses.
>>
>> 	Call the new pass.
>
> You also need to update the compiler-design document in compiler/notes.
> (Also, a NEWS file entry is needed.)

Done.

>> +A compiler-defined literal is one of the following, which can only appear
>> +within program clauses. Compiler-defined literals will be replaced by
>> +constants reflecting the context in which they appear.
>
> I suggest:
>
> Compiler-defined literals are symbolic names whose value represents
> a property of the compilation environment that cannot be determined
> until compile-time.

I don't like "cannot be determined until compile-time".

> The implementation replaces these symbolic names with actual constants
> during compilation.
> A compiler-defined literal can only appear within a rule body.

That would discount head positions, so I stuck with clause.

> The following compiler-defined literals must be supported by all Mercury
> implementations:
>
>> +
>> + at table @asis
>> + at item @samp{$file}
>> +a string that gives the name of the file that contains the module currently
>
> Delete "currently".

Done.

>> +being compiled. If the name of the file cannot be determined then it is
>> +replaced by an arbitrary string.
>> +
>> + at item @samp{$line}
>> +the line number (integer) of the goal in which the literal appears
>> +or -1 if it cannot be determined.
>> +
>> + at item @samp{$module}
>> +a string representation of the name of the module.
>
> Is the module name fully, partially, not qualified?

Fully.

>> + at item @samp{$pred}
>> +a string containing the fully-qualified predicate or function name and arity.
>> +
>> + at end table
>
>
> Move the mmc-specific ones to here.  (see below).

Done.

> I suggest you also include a test that checks the interaction with #line
> directives.

Added.

Partial interdiff follows. I've left out the parts that simply do renaming.
There was a bug in the previous patch to lexer.m which prevented it from
reading `$'-plus-one-or-more-graphic-chars as a single name token.

Peter

diff -u doc/reference_manual.texi doc/reference_manual.texi
--- doc/reference_manual.texi	1 Apr 2008 02:37:37 -0000
+++ doc/reference_manual.texi	2 Apr 2008 06:17:16 -0000
@@ -294,9 +294,9 @@
 and then another sequence of decimal digits (the exponent).
 The fraction part or the exponent (but not both) may be omitted.
 
- at item compiler_defined_literal
-A compiler-defined literal consists of a dollar sign (@code{$}) followed
-by an unquoted name.
+ at item implementation_defined_literal
+An implementation-defined literal consists of a dollar sign (@code{$})
+followed by an unquoted name.
 
 @item open_ct
 A left parenthesis, @samp{(}, that is not preceded by whitespace.
@@ -1326,7 +1326,7 @@
 @subsection Data-functors
 
 A data-functor is an integer, a float, a string, a character literal
-(any single-character name), a name, a compiler-defined literal,
+(any single-character name), a name, an implementation-defined literal,
 or a compound data-term.
 A compound data-term is a compound term which does not match
 the form of a special data-term (@pxref{Data-terms}),
@@ -1335,13 +1335,16 @@
 must name a function, predicate, or data constructor declared
 in the program or in the interface of an imported module.
 
-A compiler-defined literal is one of the following, which can only appear
-within program clauses. Compiler-defined literals will be replaced by
-constants reflecting the context in which they appear.
+Implementation-defined literals are symbolic names whose value represents
+a property of the compilation environment or the context in which it
+appears. The implementation replaces these symbolic names with actual
+constants during compilation.  Implementation-defined literals can only
+appear within clauses. The following literals must be supported by all
+Mercury implementations:
 
 @table @asis
 @item @samp{$file}
-a string that gives the name of the file that contains the module currently
+a string that gives the name of the file that contains the module
 being compiled. If the name of the file cannot be determined then it is
 replaced by an arbitrary string.
 
@@ -1350,13 +1353,22 @@
 or -1 if it cannot be determined.
 
 @item @samp{$module}
-a string representation of the name of the module.
+a string representation of the fully-qualified module name.
 
 @item @samp{$pred}
 a string containing the fully-qualified predicate or function name and arity.
 
 @end table
 
+The Mercury Melbourne implementation additionally supports the following
+extension:
+
+ at table @asis
+ at item @samp{$grade}
+the grade (string) in which the module is compiled.
+
+ at end table
+
 @node Record syntax
 @subsection Record syntax
 
@@ -9675,7 +9687,6 @@
                                 the implementation are supported at compile
                                 time.
 * Trailing::                    Undoing side-effects on backtracking.
-* Compiler-defined literals::   More literals expanded by the compiler.
 
 @end menu
 @c XXX The `reserved tag' pragma is not documented because it is intended to
@@ -10716,18 +10727,6 @@
 @c but it might be needed if you're doing certain low-level things
 @c such as implementing your own exception handling.
 
- at node Compiler-defined literals
- at section Compiler-defined literals
-
-The Melbourne Mercury compiler additionally implements the following
-compiler-defined literal:
-
- at table @asis
- at item @samp{$grade}
-the grade (string) in which the module is compiled.
-
- at end table
-
 @node Bibliography
 @chapter Bibliography
 
diff -u library/lexer.m library/lexer.m
--- library/lexer.m	1 Apr 2008 02:37:37 -0000
+++ library/lexer.m	2 Apr 2008 06:17:16 -0000
@@ -32,7 +32,7 @@
     ;       integer(int)
     ;       float(float)
     ;       string(string)      % "...."
-    ;       compiler_defined(string) % $name
+    ;       implementation_defined(string) % $name
     ;       open                % '('
     ;       open_ct             % '(' without any preceding whitespace
     ;       close               % ')'
@@ -165,8 +165,8 @@
     string.append_list(["float `", FloatString, "'"], String).
 token_to_string(string(Token), String) :-
     string.append_list(["string """, Token, """"], String).
-token_to_string(compiler_defined(Name), String) :-
-    string.append_list(["compiled-defined `", Name, "'"], String).
+token_to_string(implementation_defined(Name), String) :-
+    string.append_list(["implementation-defined `$", Name, "'"], String).
 token_to_string(open, "token ` ('").
 token_to_string(open_ct, "token `('").
 token_to_string(close, "token `)'").
@@ -332,9 +332,6 @@
         ; char.is_lower(Char) ->
             get_context(Context, !IO),
             get_name([Char], Token, !IO)
-        ; Char = '$' ->
-            get_context(Context, !IO),
-            get_compiler_defined_literal_rest(Token, !IO)
         ; Char = '0' ->
             get_context(Context, !IO),
             get_zero(Token, !IO)
@@ -363,6 +360,9 @@
         ; Char = ('`') ->
             get_context(Context, !IO),
             Token = name("`")
+        ; Char = '$' ->
+            get_context(Context, !IO),
+            get_implementation_defined_literal_rest(Token, !IO)
         ; graphic_token_char(Char) ->
             get_context(Context, !IO),
             get_graphic([Char], Token, !IO)
@@ -384,9 +384,6 @@
             string_get_variable(String, Len, Posn0, Token, Context, !Posn)
         ; char.is_lower(Char) ->
             string_get_name(String, Len, Posn0, Token, Context, !Posn)
-        ; Char = '$' ->
-            string_get_compiler_defined_literal_rest(String, Len, !.Posn,
-                Token, Context, !Posn)
         ; Char = '0' ->
             string_get_zero(String, Len, Posn0, Token, Context, !Posn)
         ; char.is_digit(Char) ->
@@ -413,6 +410,9 @@
         ; Char = ('`') ->
             string_get_context(Posn0, Context, !Posn),
             Token = name("`")
+        ; Char = '$' ->
+            string_get_implementation_defined_literal_rest(String, Len, Posn0,
+                Token, Context, !Posn)
         ; graphic_token_char(Char) ->
             string_get_graphic(String, Len, Posn0, Token, Context, !Posn)
         ;
@@ -452,9 +452,6 @@
         ; char.is_lower(Char) ->
             get_context(Context, !IO),
             get_name([Char], Token, !IO)
-        ; Char = '$' ->
-            get_context(Context, !IO),
-            get_compiler_defined_literal_rest(Token, !IO)
         ; Char = '0' ->
             get_context(Context, !IO),
             get_zero(Token, !IO)
@@ -479,6 +476,9 @@
         ; Char = ('`') ->
             get_context(Context, !IO),
             Token = name("`")
+        ; Char = '$' ->
+            get_context(Context, !IO),
+            get_implementation_defined_literal_rest(Token, !IO)
         ; graphic_token_char(Char) ->
             get_context(Context, !IO),
             get_graphic([Char], Token, !IO)
@@ -500,9 +500,6 @@
             string_get_variable(String, Len, Posn0, Token, Context, !Posn)
         ; char.is_lower(Char) ->
             string_get_name(String, Len, Posn0, Token, Context, !Posn)
-        ; Char = '$' ->
-            string_get_compiler_defined_literal_rest(String, Len, !.Posn,
-                Token, Context, !Posn)
         ; Char = '0' ->
             string_get_zero(String, Len, Posn0, Token, Context, !Posn)
         ; char.is_digit(Char) ->
@@ -525,6 +522,9 @@
         ; Char = ('`') ->
             string_get_context(Posn0, Context, !Posn),
             Token = name("`")
+        ; Char = '$' ->
+            string_get_implementation_defined_literal_rest(String, Len, Posn0,
+                Token, Context, !Posn)
         ; graphic_token_char(Char) ->
             string_get_graphic(String, Len, Posn0, Token, Context, !Posn)
         ;
@@ -1496,9 +1496,10 @@
         string_get_context(Posn0, Context, !Posn)
     ).
 
-:- pred get_compiler_defined_literal_rest(token::out, io::di, io::uo) is det.
+:- pred get_implementation_defined_literal_rest(token::out, io::di, io::uo)
+    is det.
 
-get_compiler_defined_literal_rest(Token, !IO) :-
+get_implementation_defined_literal_rest(Token, !IO) :-
     io.read_char(Result, !IO),
     (
         Result = error(Error),
@@ -1511,30 +1512,35 @@
         ( char.is_lower(Char) ->
             get_name([Char], Token0, !IO),
             ( Token0 = name(S) ->
-                Token = compiler_defined(S)
+                Token = implementation_defined(S)
             ;
                 Token = Token0
             )
+        ; graphic_token_char(Char) ->
+            get_graphic([Char, '$'], Token, !IO)
         ;
             io.putback_char(Char, !IO),
             Token = name("$")
         )
     ).
 
-:- pred string_get_compiler_defined_literal_rest(string::in, int::in,
+:- pred string_get_implementation_defined_literal_rest(string::in, int::in,
     posn::in, token::out, string_token_context::out, posn::in, posn::out)
     is det.
 
-string_get_compiler_defined_literal_rest(String, Len, Posn0, Token, Context,
-        !Posn) :-
+string_get_implementation_defined_literal_rest(String, Len, Posn0,
+        Token, Context, !Posn) :-
+    Posn1 = !.Posn,
     ( string_read_char(String, Len, Char, !Posn) ->
         ( char.is_lower(Char) ->
-            string_get_name(String, Len, Posn0, Token0, Context, !Posn),
+            string_get_name(String, Len, Posn1, Token0, Context, !Posn),
             ( Token0 = name(S) ->
-                Token = compiler_defined(S)
+                Token = implementation_defined(S)
             ;
                 Token = Token0
             )
+        ; graphic_token_char(Char) ->
+            string_get_graphic(String, Len, Posn0, Token, Context, !Posn)
         ;
             string_ungetchar(String, !Posn),
             Token = name("$"),

--- NEWS	15 Feb 2008 02:26:48 -0000	1.487
+++ NEWS	2 Apr 2008 06:17:15 -0000
@@ -22,6 +22,8 @@
 * We now support !X ^ field_list := Term as a synonym for
   !:X = !.X ^ field_list := Term.
 * We now support higher-order `any' insts.
+* We now support "implementation-defined literals", such as `$file', `$line',
+  `$pred', which are useful for producing better run-time error messages.
 
 Changes to the Mercury standard library:
 
--- compiler/notes/compiler_design.html	27 Feb 2008 07:23:55 -0000	1.133
+++ compiler/notes/compiler_design.html	2 Apr 2008 06:17:16 -0000
@@ -686,6 +686,14 @@
 	into `generic_call(unsafe_cast, ...)' goals here.
 	<p>
 
+<dt> implementation-defined literals
+
+	<dd>
+	implementation_defined_literals.m replaces unifications
+	of the form <CODE>Var = $name</CODE> by unifications to string
+	or integer constants.
+	<p>
+
 <dt> polymorphism transformation
 
 	<dd>


--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list