Java
_Java_
_java_
The libraries of the "java" collection provide utilities for manipulating Java
programs in both source and binary format.
*** CAVEAT: This library is still in its rather early stages. Expect significant
changes to the API to occur in the future.
======================================================================
_java.ss_:
======================================================================
> (current-classpath [cp]) :: (parameterof (listof path))
A parameter containing a list of paths that point to either directories where
.class files reside or .zip/.jar files containing .class files. This is used by
the standard class resolver in _semantics/standard-resolver.ss_.
> (current-sourcepath [sp]) :: (parameterof (listof path))
A parameter containing a list of paths that point to directories where .java
files reside. This is used by the standard class resolver in
_semantics/standard-resolver.ss_.
======================================================================
_syntax/class-file.ss_:
======================================================================
This module provides procedures for reading compiled Java .class files according
to the Java class file format, as specified by Chapter 4 of the Java Virtual
Machine Specification, 2nd Ed.
http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html
http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html
> (struct class-file (pool flags this super interfaces fields methods attributes))
This structure encapsulates all the information read in from a class file.
> (extract-access-flags bits) :: exact-integer [(union 'super 'synchronized)] -> (listof access-flag)
A utility for converting access flags packed in the bits of an exact integer
into a list of their corresponding symbolic names. The possible access flags
occurring in a bit field can be enumerated by taking the union of tables 4.1,
4.4, 4.5, and 4.7 of the JVM specification.
Unfortunately, there is a single overlap amongst these tables: both
ACC_SUPER and ACC_SYNCHRONIZED have the value 0x0020. The second optional
argument allows clients to specify which way to interpret the value; by default
the procedure produces the symbol 'super/synchronized.
Flag name Bit Symbolic value
--------- --- --------------
ACC_PUBLIC 0x0001 'public
ACC_PRIVATE 0x0002 'private
ACC_PROTECTED 0x0004 'protected
ACC_STATIC 0x0008 'static
ACC_FINAL 0x0010 'final
ACC_SUPER 0x0020 'super
ACC_SYNCHRONIZED 0x0020 'synchronized
ACC_VOLATILE 0x0040 'volatile
ACC_TRANSIENT 0x0080 'transient
ACC_NATIVE 0x0100 'native
ACC_INTERFACE 0x0200 'interface
ACC_ABSTRACT 0x0400 'abstract
ACC_STRICT 0x0800 'strictfp
> (utf8-info->string ui) :: utf8-info -> string
Converts a utf8-info struct into a Unicode string.
> (read-class-file [in]) :: [input-port] -> class-file
Reads a class file from an input port.
> access-flag/c :: contract
Recognizes symbols that name access flags: all of the symbols in the table
above, plus 'super/synchronized.
The _class-file.ss_ library defines a hierarchy of structures representing the
elements of a class file. The structures are organized according to the
following hierarchy:
info
|
+-- class-info
| o name-index :: natural-number
|
+-- ref-info
| o class-index :: natural-number
| o name-and-type-index :: natural-number
| |
| +-- field-ref-info
| |
| +-- method-ref-info
| |
| +-- interface-method-ref-info
|
+-- string-info
| o string-index :: natural-number
|
+-- integer-info
| o value :: integer
|
+-- float-info
| o bytes :: bytes
|
+-- long-info
| o high-bytes :: bytes
| o low-bytes :: bytes
|
+-- double-info
| o high-bytes :: bytes
| o low-bytes :: bytes
|
+-- name-and-type-info
| o name-index :: natural-number
| o descriptor-index :: natural-number
|
+-- utf8-info
| o length :: natural-number
| o bytes :: bytes
|
+-- inner-class-entry
| o inner-class-info-index :: natural-number
| o outer-class-info-index :: natural-number
| o inner-name-index :: natural-number
| o inner-class-access-flags :: integer
|
+-- element-info
| o access-flags :: integer
| o name-index :: natural-number
| o descriptor-index :: natural-number
| o attributes-count :: natural-number
| o attributes :: (listof attribute-info)
| |
| +-- field-info
| |
| +-- method-info
|
+-- attribute-info
|
+-- unsupported-attribute-info
| o length :: natural-number
| o bytes :: bytes
|
+-- constant-value-attribute-info
| o value-index :: natural-number
|
+-- code-attribute-info
|
+-- exceptions-attribute-info
| o count :: natural-number
| o exceptions :: (listof natural-number)
|
+-- inner-classes-attribute-info
|
+-- synthetic-attribute-info
|
+-- source-file-attribute-info
|
+-- line-number-table-attribute-info
|
+-- local-variable-table-attribute-info
|
+-- deprecated-attribute-info
======================================================================
_syntax/ast.ss_:
======================================================================
The _ast.ss_ module defines a hierarchy of structures representing nodes in the
abstract syntax tree of a Java program. The structures are organized according
to the following hierarchy:
ast
o src :: (optional src)
|
+-- id
| o name :: symbol
|
+-- name
| o path :: (listof id)
| o id :: id
|
+-- import
| o name :: name
| o star? :: boolean
|
+-- type-spec
| o base-type :: type-name
| o dimension :: natural-number
|
+-- modifier
| o modifier :: symbol
|
+-- initializer
| o static? :: boolean
| o body :: block-stmt
|
+-- compilation-unit
| o package :: (optional name)
| o imports :: (listof import)
| o classes :: (listof (optional type-decl))
|
+-- decl
| o modifiers :: (listof modifier)
| o name :: id
| |
| +-- type-decl
| | o interfaces :: (listof name)
| | o body :: (listof class-element)
| | |
| | +-- class-decl
| | | o super :: (optional name)
| | |
| | +-- interface-decl
| |
| +-- variable-decl
| | o type :: type-spec
| | o init :: (optional expr)
| |
| +-- behavior-decl
| o formals :: (listof variable-decl)
| o throws :: (listof name)
| o body :: block-stmt
| |
| +-- constructor-decl
| |
| +-- method-decl
| o return-type :: type-spec
|
+-- stmt
| |
| +-- expr-stmt
| | o expr :: expr
| |
| +-- labeled-stmt
| | o label :: id
| | o stmt :: (optional stmt)
| |
| +-- block-stmt
| | o body :: (listof block-element)
| |
| +-- switch-stmt
| | o expr :: expr
| | o clauses :: (listof (union case-stmt block-element))
| |
| +-- case-stmt
| | o test :: (optional expr)
| |
| +-- if-stmt
| | o test :: expr
| | o con :: (optional stmt)
| | o alt :: (optional stmt)
| |
| +-- for-stmt
| | o init :: (union (listof variable-decl) (listof expr))
| | o test :: (optional expr)
| | o update :: (listof expr)
| | o body :: (optional stmt)
| |
| +-- while-stmt
| | o test :: expr
| | o body :: (optional stmt)
| |
| +-- do-stmt
| | o body :: stmt
| | o test :: expr
| |
| +-- break-stmt
| | o label :: (optional id)
| |
| +-- continue-stmt
| | o label :: (optional id)
| |
| +-- return-stmt
| | o value :: (optional expr)
| |
| +-- throw-stmt
| | o expr :: expr
| |
| +-- synchronized-stmt
| | o expr :: expr
| | o body :: stmt
| |
| +-- try-stmt
| | o body :: block-stmt
| | o catches :: (listof catch-stmt)
| | o finally :: (optional block-stmt)
| |
| +-- catch-stmt
| | o exception :: variable-decl
| | o body :: block-stmt
| |
| +-- assert-stmt
| o predicate :: expr
| o message :: expr
|
+-- expr
|
+-- conditional-expr
| o test :: expr
| o con :: expr
| o alt :: expr
|
+-- prefix-expr
| o op-src :: src
| o operator :: symbol
| o operand :: expr
|
+-- postfix-expr
| o op-src :: src
| o operator :: symbol
| o operand :: expr
|
+-- unary-expr
| o op-src :: src
| o operator :: symbol
| o operand :: expr
|
+-- binary-expr
| o op-src :: src
| o operator :: symbol
| o left :: expr
| o right :: expr
|
+-- instanceof-expr
| o op-src :: src
| o expr :: expr
| o type :: type-spec
|
+-- literal
| o value :: any
| |
| +-- boolean-literal
| |
| +-- char-literal
| |
| +-- integer-literal
| |
| +-- long-literal
| |
| +-- float-literal
| |
| +-- double-literal
| |
| +-- string-literal
| |
| +-- null-literal
|
+-- class-expr
| o type :: type-spec
|
+-- new-object-expr
| o container :: (optional expr)
| o name :: name
| o args :: (listof expr)
| o class-body :: (optional (listof class-element))
|
+-- new-array-expr
| o type :: type-spec
| o dim-exprs :: (listof expr)
| o dim :: natural-number
| o init :: (optional array-initializer)
|
+-- array-initializer
| o contents :: (listof expr)
|
+-- call-expr
| o object :: (optional expr)
| o name :: name
| o args :: (listof expr)
|
+-- assign-expr
| o operator :: symbol
| o left :: access
| o right :: expr
|
+-- cast-expr
| o type :: type-spec
| o expr :: expr
|
+-- access
|
+-- field-access
| o object :: expr
| o name :: id
|
+-- array-access
| o array :: expr
| o index :: expr
|
+-- var-access
o var :: name
Every AST node can contain a field of type `src', which represents the source
location information of the item.
> (struct src (file line col span)) :: (optional path) * (optional natural-number) * (optional natural-number) * (optional natural-number)
> (name->access name) :: name -> access
Converts a name to a variable reference.
> (access->name acc) :: (union field-access var-access) -> name
Converts a field or local variable reference to a name.
FIXME: doesn't work with field accesses in general, since those can contain
arbitrary expressions, which can't be represented as names. (In fact, it
appears that field-accesses always have non-name expressions; all other
field refs get mapped to var-access nodes instead.)
> (increase-type-dimension ts n) :: type-spec natural-number -> type-spec
Constructs a new type-spec which is equivalent to `ts' except with type
dimension increased by `n'.
> primitive-type ::= 'void | 'boolean | 'byte | 'short | 'int | 'long | 'char | 'float | 'double
> (primitive-type? v) :: any -> boolean
Members of class and interface declarations are represented by the type
`class-element', which is define by:
> class-element ::=
decl
| (nelistof variable-decl)
| initializer
| #f
> (class-element? v) :: any -> boolean
> block-element ::=
decl
| (nelistof variable-decl)
| stmt
| #f
> (block-element? v) :: any -> boolean
> type-name ::=
primitive-type
| name
> (type-name? v) :: any -> boolean
======================================================================
_syntax/lexer.ss_:
======================================================================
The _lexer.ss_ module provides a lexer for Java.
> Operators :: empty-tokens
> Separators :: empty-tokens
> EmptyLiterals :: empty-tokens
> Keywords :: empty-tokens
> BasicTokens :: tokens
> (struct string-error (string error-token)) :: string position-token
> (java-lexer in) :: input-port -> position-token
======================================================================
_syntax/parser.ss_:
======================================================================
The _parser.ss_ module provides a parser for Java.
> (parse in path) :: [input-port (optional (union path string))] -> ast
Parses a Java compilation unit (i.e., the contents of a .java file) from an
input port, with the given file name (used for error reporting).
> (parse-string str) :: string -> ast
Parses a Java compilation unit from a string.
> (parse-file path) :: (union path string) -> ast
Parses a Java comilation unit from a file.
======================================================================
_semantics/semantic-object.ss_:
======================================================================
The _semantic-object.ss_ library defines a hierarchy of mzscheme classes and
interfaces for the representation of the (static) semantic elements of a Java
program, e.g., classes, interfaces, methods, fields, etc.
> (struct type-name (package type [dimension])) :: (listof symbol) symbol? natural-number
The `type-name' structure contains enough information to identify a type
uniquely and can be used to look up a type with a class resolver (see
_class-resolver.ss). The `package' field contains the name of the type's package
(primitive types and members of the default package use the empty list). The
`type' field contains the symbolic name of the type. The optional `dimension'
field contains the array dimension and defaults to 0, representing a ground
(i.e., non-array) type.
> (build-type-name path) :: (listof symbol) -> type-name
Given a fully qualified type name as a list of symbols, this procedure builds a
`type-name' structure representing that name.
> (dot-notation path) :: (listof symbol) -> string
Given a fully qualified type name as a list of symbols, this procedure
constructs the string representation of the fully qualified name in Java
``dot-notation''.
> (type-name->string tn) :: (optional type-name) -> string
Given a `type-name' struct (or #f, representing the ``void'' type), this
procedure constructs the string representation of the fully qualified name in
Java ``dot-notation''.
> byte, char, double, float, int, long, short, boolean :: primitive-type%
Objects of class primitive-type% representing the Java primitive types of the
same respective name.
Interfaces
----------
The mzscheme interfaces defined in this library are organized according to the
following graph:
semantic-object<%> resolvable<%>
| |
+---------+---------+
|
type<%>
++ interface semantic-object<%>
> (to-string) :: -> string
Returns a string representation of the semantic object.
++ interface resolvable<%>
> (get-related-types) :: -> (listof type-name)
Returns the list of type-names that are referenced in the definition of the
semantic object.
++ interface type<%> extends semantic-object<%>, resolvable<%>
> (get-type-name) :: -> type-name
Returns the type-name representing the type object.
Classes
-------
The mzscheme classes defined in this library are organized according to the
following hierarchy (classes without parent classes extend the standard mzscheme
object% class):
package% (semantic-object<%>, resolvable<%>)
array-type% (type<%>)
ground-type% (type<%>)
|
+-- primitive-type%
|
+-- declared-type%
|
+-- class%
|
+-- interface%
type-element% (semantic-object<%>, resolvable<%>)
|
+-- field%
|
+-- behavior%
| |
| +-- constructor%
| |
| +-- method%
|
+-- initializer%
|
+-- inner-type%
++ class package% implements semantic-object<%>
> (new package% (name _)) -> package%
name :: (listof symbol)
> (to-string) :: -> string
Returns the package name in dot-notation.
++ class array-type% implements type<%>
> (new array-type% (base-type _)) -> array-type%
base-type :: type-name
> (get-type-name) :: -> type-name
> (get-base-type) :: -> type-name
> (get-dimension) :: -> natural-number
> (get-related-types) :: -> (listof type-name)
> (to-string) :: -> string
++ class ground-type% implements semantic-object<%>, type<%>
> (new ground-type% (package _) (name _)) -> ground-type%
package :: (listof symbol)
name :: type-name
> (get-package) :: -> (listof symbol)
THIS METHOD IS DEPRECATED. Use (type-name-package (send obj get-type-name))
instead. In the next major version release, this method will be removed.
> (get-type-name) :: -> type-name
> (get-related-types) :: (listof type-name)
> (to-string) :: -> string
++ class primitive-type% extends ground-type%
> (new primitive-type% (name _)) -> primitive-type%
name :: type-name
++ class declared-type% extends ground-type%
> (new declared-type% (package-name _) (name _) (modifiers _) (interfaces _) (elements _)) -> declared-type%
package-name :: (listof symbol)
name :: type-name
modifiers :: (listof access-flags)
interfaces :: (listof type-name)
elements :: (listof type-element%)
> (get-modifiers) :: -> (listof access-flag)
> (get-interfaces) :: -> (listof type-name)
> (get-elements) :: -> (listof type-element%)
++ class class% extends declared-type%
> (new class% (package _) (name _) (modifiers _) (interfaces _) (elements _) (superclass _)) -> class%
package :: (listof symbol)
name :: type-name
modifiers :: (listof access-flag)
interfaces :: (listof type-name)
elements :: (listof type-element%)
superclass :: (optional type-name)
> (get-superclass) :: -> (optional type-name)
++ class interface% extends declared-type%
> (new interface% (package _) (name _) (modifiers _) (interfaces _) (elements _)) -> interface%
package :: (listof symbol)
name :: type-name
modifiers :: (listof access-flag)
interfaces :: (listof type-name)
elements :: (listof type-element%)
++ class type-element% implements semantic-object<%>, resolvable<%>
> (new type-element% (name _)) -> type-element%
name :: string
> (get-name) :: -> (option string)
> (get-related-types) :: (listof type-name)
> (to-string) :: -> string
++ class field% extends type-element%
> (new field% (name _) (modifiers _) (type _)) -> field%
name :: string
modifiers :: (listof access-flag)
type :: type-name
> (get-modifiers) :: -> (listof access-flag)
> (get-type) :: -> type-name
++ class initializer% extends type-element%
> (new initializer%) -> intializer%
++ class behavior% extends type-element%
> (new behavior% (name _) (formals _) (exceptions _) (modifiers _)) -> behavior%
name :: string
formals :: (listof type-name)
exceptions :: (listof type-name)
modifiers :: (listof access-flag)
> (get-formals) :: -> (listof type-name)
> (get-exceptions) :: -> (listof type-name)
> (get-modifiers) :: -> (listof access-flag)
++ class constructor% extends behavior%
> (new constructor% (name _) (formals _) (exceptions _) (modifiers _)) -> constructor%
name :: string
formals :: (listof type-name)
exceptions :: (listof type-name)
modifiers :: (listof access-flag)
++ class method% extends behavior%
> (new method% (name _) (formals _) (exceptions _) (modifiers _) (return-type _)) -> method%
name :: string
formals :: (listof type-name)
exceptions :: (listof type-name)
modifiers :: (listof access-flag)
return-type :: (optional type-name)
> (get-return-type) :: -> (optional type-name)
++ class inner-type% extends type-element%
> (new inner-type% (name _) (type _)) -> inner-type%
name :: string
type :: type-name
> (get-type) :: -> type-name
======================================================================
_semantics/class-resolver.ss_:
======================================================================
;; TODO: this should not be starting out #f
> (current-class-resolver [cr]) :: (parameterof class-resolver<%>)
> (lookup-package pkg) :: (listof symbol) -> (optional package%)
> (lookup-type tn) :: type-name -> (optional type<%>)
> (resolve-all t) :: (union type-name semantic-object<%>) -> any
Forces the resolution (via the current class resolver) of the transitive closure
of the `get-related-types' relation on either a semantic object or the type
associated with a type-name.
++ interface class-resolver<%>
> (resolve-package path) :: (listof symbol) -> (optional package%)
> (resolve-type tn) :: type-name -> (optional type<%>)
======================================================================
_semantics/standard-resolver.ss_:
======================================================================
++ class class-resolver% implements class-resolver<%>
> (new method% (name _) (formals _) (exceptions _) (modifiers _) (return-type _)) -> method%
name :: string
formals :: (listof type-name)
exceptions :: (listof type-name)
modifiers :: (listof access-flag)
return-type :: (optional type-name)
> (new class-resolver% (classpath _) (sourcepath _)) -> class-resolver%
classpath :: (listof path)
sourcepath :: (listof path)
The initialization arguments specify the paths to search during class
resolution for binary and source resolution, respectively. Both arguments
are optional. If they are not specified, this class uses the value of
the current-classpath and current-sourcepath parameters, respectively, at
the time when the class was created. Therefore, changing the value of
either of these parameters will *not* affect previously-created instances
of class-resolver%.
> (resolve-package path) :: (listof symbol) -> (optional package%)
> (resolve-type tn) :: type-name -> (option type<%>)
======================================================================
_semantics/resolve-source.ss_:
======================================================================
TODO: (resolve-source ast) :: ast -> (listof declared-type%)
======================================================================
_semantics/resolve-binary.ss_:
======================================================================
> (resolve-binary cf) :: class-file -> declared-type%