PROPOSAL: Compiletime information access

rssh at gradsoft.com.ua rssh at gradsoft.com.ua
Thu Mar 26 02:01:40 PDT 2009


>
> I think the implementation of this could be far cleaner if the values
> you want were represented as static final fields not methods, which
> would make them compile time constants.

I. e. Compiletime.__FILE__,  Complietime.__LINE__


import static Compiletime.__FILE__;

System.out.println("file is %s",__FILE__); as in old good days.

 ;)

// Nice. Very nice.


This wouldn't work for exec()
> and getBindings() but those are probably better done using annotation
> processing.
>

getBinding() is impossible to simulate with annotation processing, because
 generation of binding contains code, which must be executed in local
context of current scope.  Annotation Processor can't touch current
scope,
only generate new files.

in latest version of this submission:
  http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000890.html
All non-trivial parts which is possible to simulate with annotation
processing moving out.

Anyway, this is already rejected:
cite from:
http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000887.html
<cite>
>
>>  -  improving proposal about access to compile-time information about
>> local context can have some sence (?)
>>
>
>Given the existing capabilities of annotation processors, I don't think
>the proposed API is necessary or desirable.
</cite>
<IMHO>
 I does not understand, why Joseph Darcy think, that existing capabilities
of annotation processing may allows programmer use compile-time
information about local context (it's not true for now).
</IMHO>

  So, proposed changes are very funny, but creation of next version of this
proposal will be waste of time:(

But it is possible to achieve same effects by changing libraries:
Generation of such information will be available from annotation processor
if we will add location-method information to javax.annotation.Element,
than it would be possible to wrote annotation processor which will
retrieve location information near in the same way, as you wrote
@LongString in rapt, something in style:

@Compiletime(action="getSourceLocation()",id="unique");
final SourceLocation sourceLocation = Compiletime.unique;

Emulate getBindings() with annotation processing still impossible (add AST
rewriting to compiler is funny, but too avanagard for such archaic^H^H^H^H
 solid production language as Java), but need for it is quite small, so it
can be dropped.

 (and without enhanced strings getBinding() not needed at all; my plan was
to use getBinding() as mechanizm for run-time or compile-time
implementation of stirng literals in future, but this is another story).

So, practical approach will be wait for 'Small library changed' and submit
proposal about adding access to source location of annotation element to
it.


> The strategy would then be that the compiler would contain a custom
> implementation of javax.lang.model.TypeElement representing o nly this
> class. When the compile time constants were being resolved during
> compilation, this customer TypeElement with Custom VariableElements
> would be called by the compiler to get the constant value, the
> VariableElement could (with only a little magic) return the appropriate
> value for the site where the compile time constant was being copied to.
>
> The only concern would be that the compile time constants would have non
> constant values which varied depending on where they were referenced
> from. I suspect this might be a small compiler change, the question
> would then be whether the utility of such a mechanism carried enough
> benefit to counteract the rather strange behaviour of this particular
> class.
>
> It will be interesting to see what other think.
>
> Bruce
>
> rssh at gradsoft.com.ua wrote:
>> AUTHOR:  Ruslan Shevchenko
>>
>> OVERVIEW:
>>
>>  FEATURE SUMMARY:
>>
>>    Add API to access compile-time context of current compiled element
>> from
>>  programs and annotation processors.
>>
>>  MAJOR ADVANTAGE:
>>
>>    Now compile time properties are unaccessible for programmer. This
>> meaning
>>  that some functionality (such as access to location of file and line)
>> is
>>  accessible only from debug version of program with technique, which is
>> not
>>  officially supported, some (such as access to time of compilation or
>>   to binding context of current program location) is not avaible at all.
>>
>>  MAJOR DISADVANTAGE
>>
>>    Inaccurate usage of this feature can cause producing of unmaintable
>> code.
>>
>>  ALTERNATIVES:
>>
>>    External preprocessing of java sources.
>>
>> EXAMPLES
>>
>> SIMPLE EXAMPLE:
>>
>> Example 1
>>
>>   if (traceCondigion) {
>>     log.trace(Compiletime.getFileName()+":"+
>>               Compiletime.getLineNumber());
>>   }
>>
>> Example 2
>>
>>   if (system.currentTimeMillis() - Compiletime.getTimeMillis() > 86400)
>> {
>>      System.out.println("This file was compiled more than day ago");
>>   }
>>
>> Example 3
>>
>>   System.out.println("Superprogram by AAA AC, version:"+
>>                                       Compiletime.exec("svnversion"));
>>
>> ADVANCED EXAMPLE:
>>
>> Example 1
>>   // assuming that multiline strings are implemented:
>>
>>   int a=0;
>>   int b=1;
>>   Binding bindings = Compiletime.getInstance().getCurrentBindings();
>>   ScriptEngine velocity = ScriptEngineManager.get("velocity");
>>   try {
>>     String fname = Compiletime.getFileName();
>>     int    line  = Compiletime.getLineNumber();
>>     String s = velocity.eval("""
>>     #if ($a==$b)
>>         Something interesting here may be,
>>        Are you know that value of b is $b ?
>>     #else
>>        no mistics here.
>>     #end
>>     """,
>>     bindings);
>>   } catch (ScriptException ex){
>>      Sytem.err.println("error in inline velocity in "+fname+", "
>>                        "line "+line+1+ex.getLineNumber());
>>   }
>>
>>
>> Example 2
>>
>>   boolean isDemo = (Compiletime.eval(Properties.class,
>>                                    "getProperty","is.demo")!=null);
>>
>>   if (!isDemo) {
>>     String key = (String)Compiletime.eval(GenerateUniqueKey.class,
>>                                         "generate");
>>     LoadNotDemoClass();
>>   }
>>
>>
>> DETAILS:
>>
>>
>>
>>  Add to Java Library pseudo-objects java.lang.Compiletime with access to
>> compile-time properties and next signature:
>>
>> public class Compiletime
>> {
>>    /**
>>     * get filename of compiled call.
>>     * in case of generated source and avaible JSR-45 SMAP file
>>     * return file name of translated-source.
>>     **/
>>    public static String getFileName();
>>
>>    /**
>>     * get line number of compiled call.
>>     * in case of generated source and avaible JSR-45 SMAP file
>>     * return line number in translated-source.
>>     **/
>>    public static int getLineNumber();
>>
>>    /**
>>     * get class name where this call is placed.
>>     * in case of generated source and avaible JSR-45 SMAP file
>>     * return class name in translated-source.
>>     **/
>>    public static int getClassName();
>>
>>    /**
>>     * get method name where this call is placed.
>>     * in case of generated source and avaible JSR-45 SMAP file
>>     * return method name in translated-source.
>>     **/
>>    public static int getMethodName();
>>
>>
>>    /**
>>     * generate JSR223 bindings for given names in current compilation
>>     *context.
>>     *Names array must be empty or consists from string literals.
>>     **/
>>    public static Bindings getBindings(String ... names)
>>
>>
>>    /**
>>     * get time of compilation in miliseconds.
>>     **/
>>    public static long getTimeMillis();
>>
>>    /**
>>     * Execute os command in compile-time.
>>     *@command - must be a string literal or result of call of
>> Compiletime
>>     * method, otherwise compile-time error is thrown
>>     **/
>>    public static String exec(String command)
>>    /**
>>     *  call java class at compile-time.
>>     *During processing this directive, compiler will
>>     *1. determinate, if class available in user path.
>>     *2. determinate, if exists method with appropriative number and
>> types
>>     *  of parameters.
>>     *3. If such method is static - call one, otherwise
>>     *  3.1 if class have default constructor - create instance of object
>>     *      (otherwise throw compile-time error)
>>     *  3.2. Call methid with new-created instance.
>>     *  3.3. If method return some result - substitute output to result,
>>     *       on exception throw compile-time error.
>>     *@param classLiteral - must be a class literal for object to call.
>>     *@param methodName - must be a string literal with name of method to
>> call.
>>     *@param parameters - parameters of method to call. Must be a
>> literals, or
>>     *    calls of Compiletime methods.
>>     **/
>>    public static Object eval(Class<?> classLiteral, String methodName,
>> Object .. params);
>>
>> }
>>
>>
>>
>> COMPILATION:
>>
>>  During compilation calls to compile time are changed to generation of
>> appriative constant expressions.
>>
>> String x = Compiletime.getFileName();
>> changed to
>> String x = "com/mycompany/package/MyClass.java";
>>
>> int x = Compiletime.getLinNumber();
>>  changed to
>> int x = 33;
>>
>> String x = getClassName()
>>  changed to
>> String x = "com.mycompany.package.MyClass";
>>
>>
>> class X
>> {
>>   int p1;
>>   String p2;
>>
>>   ...
>>   public void doSomething(int x, int y)
>>   {
>>     int local = x+y;
>>     Bindings bindings = Compiletime.getBindings();
>>     evalSomeScript(bindings);
>>   }
>>
>> }
>>
>>
>>  will translated to
>>
>> class X
>> {
>>   int p1;
>>   String p2;
>>   ...
>>
>>   public void doSomething(int x, int y)
>>   {
>>     int local = x+y;
>>     SimpleBinding binding=(SimpleBinging uniqueName= new
>> SimpleBinding();
>>                            uniqueName.put("this",this);
>>                            uniqueName.put("p1",p1);
>>                            uniqueName.put("p2",p2);
>>                            uniqueName.put("x",x);
>>                            uniqueName.put("y",y);
>>                            uniqueName.put("local",local);
>>                            uniqueName );
>>     evalSomeScript(bindings);
>>   }
>>
>>
>> }
>>
>>  (assuming that Block Expressions for Java will be avaible. If not - it
>> will be necessory create own implementation of Bindings as part of
>> library).
>>
>> exec will be changed to Sting literal, with result of execution, i. e.
>> on Unix
>> String compiledBy = Compiletime.eval("whoami");
>> whill be translated to 'rssh'
>>
>> At last eval call is translated to
>>  - appropriative literal, if result of eval is primitive type or boxed
>>    primitivew type.
>>  - Call of code to unserialize constant byte array, which as serialized
>>    during compilation
>>  or throw compile-time error is object is not primitive type and not
>> implements Serializable.
>>
>> JLS changes: current scope of JLS is not touched.
>>
>> Btw, may be add to JLS chapter with name 'Compilation process' where
>> describe:
>>  - high level description of transforming source code to JVM classes.
>>  - process of automatic loading of annotation processors and when ones
>> are
>> used.
>>  - this API.
>>
>>
>> TESTING:
>>
>>  Special cases are:
>>   *  compability with JSR45
>>   *  testing of exec function is
>>
>> LIBRARY SUPPORT:
>>   None, or adding two classes (for Bindings implementation with filling
>> in
>> constructor and Unserializing Object utility) in depends of avaibility
>> of block expressions for Java
>>
>>  (May be exists sence add methods for retrieveing source location (i.e.
>> file
>>  name and line number retrieving) to javax.lang.model.element.Element to
>>  support better diagnostics.
>>
>> REFLECTIVE APIS: None
>>
>> OTHER CHANGES: None
>>
>> MIGRATION: None
>>
>> COMPABILITY
>>  None
>>
>> REFERENCES
>>
>>  http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4411102
>>  http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6439965
>>  http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4649007
>>
>> IMPLEMENTATION URL (optional)
>>
>>  None yet.
>>
>>
>>
>>
>>
>>
>>
>
>
>





More information about the coin-dev mailing list