04-07-2014, 01:11 PM
Java/MP Project Report
JavaMP Project Report.pdf (Size: 143.39 KB / Downloads: 139)
Abstract
In this report we present Java/MP, a multiparadigm language designed as an extension to Java. Java/MP is an
upward compatible superset of Java and incorporates the object oriented, functional and logical paradigms.
Java/MP programs are compatible with the standard Java virtual machine. Many of the ideas in Java/MP have
been borrowed from an earlier multiparadigm language Leda which is based on Pascal. One of the objectives
in the design of Java/MP was to add as few features as possible and make the extensions feel natural and
evolutionary. A prototype compiler was developed as part of this project. Java/MP is currently implemented
as a preprocessor that translates Java/MP code into pure Java.
This report describes the features new to Java/MP and also the translation techniques used by the prototype
compiler. We will also take a look at some sample programs written in Java/MP.
Introduction
The American Heritage Dictionary defines the word paradigm as follows:
A set of assumptions, concepts, values and practices that constitutes a way of viewing reality for the
community that shares them, especially in an intellectual discipline.
So paradigms are fundamentally characterized by the way a community uses them to view reality. Paradigms
are perhaps best illustrated in the religions. Every religion subscribes to a set of ideas and the religious
community shares them. Some religions may have common set (small or large) of ideas, in which case they
could be categorized into a common paradigm.
Programming languages can also be divided into different paradigms. These paradigms however are about
problem solving. Programming languages are used to instruct the computer and the computer is a device for
doing computation or problem solving. This basically leaves a programming language responsible for
providing effective problem solving tools. The paradigm or the school of thought to which a programming
language belongs directly influences the way in which problems are tackled using the language. That is, the
technique invented to solve a given problem in one language can be strikingly different than the technique that
would be invented in another language subscribing to a different paradigm.
Functional Paradigm
The functional paradigm is based upon a branch of mathematics called lambda calculus that has its roots in
Alonzo Church’s work on recursive functions. In this paradigm there are only constant values and functions.
There is no notion of incremental changes being made to portions of memory to reflect computation results.
Functions are similar to algebraic equations involving variables. The process of substituting the variables with
values is referred to as “applying”. Just as in mathematical equations, once the variables are assigned values,
they do not undergo change during the process of evaluating the function. Results are obtained when a
function is applied with some values and each time the same values are applied to a function the same result is
obtained1. A function is the fundamental building block of the functional paradigm. Functional languages
allow functions themselves to be treated as values. Consequently a function itself can be applied to another
function and also the result of applying a function can be a function. This property is commonly referred to as
higher order functions . Functional languages use the following two important ideas to build programs with
functions:
Multiparadigm
There is a plethora of paradigms that exist on which programming languages are based. Some other paradigms
include the visual, spreadsheet, rule based, access oriented, subject oriented, constraint etc. Languages that
subscribe to more than one paradigm are called multiparadigm languages. Smooth and seamless integration of
the paradigms then becomes an important issue for these languages. Another important issue is the degree to
which each of the paradigms is supported. The prime motivation for research in multiparadigm languages
stems from the fact that not all problems are best solved within a single paradigm. Problems that can be
solved very easily in one paradigm can prove to be a sizeable undertaking in another. For example it is widely
accepted that logic programming languages prove to be a rather useful implementation tool for expert systems
but lack good support for numeric computation which is a forte of imperative languages. Object oriented
languages on the other hand are the most natural fit for creating simulations of real world systems.
Some multiparadigm research tends to provide a greater emphasis on providing maximum support paradigm
to each individual paradigm but compromise on smooth integration between them. Others tend to provide
seamless integration among the paradigms but provide a very high degree of support to one paradigm and
heavily compromise on others. [Diomidis,1994] discusses some ideas on implementing a multiparadigm
system. They introduce an abstraction named call gate. The call gate provides a communication channel for
the interaction between the different paradigms. Every paradigm will provide call gates to allow other
paradigms to interact with it. This technique makes the multiparadigm system look like a conglomeration of
mutually independent paradigms. Even though a high degree of support can be given to any particular
paradigm, mixing paradigms seamlessly turns out to be elusive.
Multiparadigm languages differ vastly in the paradigms they support. The Oz programming language, for
instance, supports logic, object-oriented, constraint, and concurrency programming. Pizza supports functional,
generic and object oriented paradigms. Leda supports the functional, object oriented, generic, and logic
paradigms
Motivation
The object oriented paradigm has become the dominant programming paradigm today. Its has become a part
of academic programs in many universities and familiarity with its basic concepts is widespread. Java too has
grown to be a popular object oriented language in academia and industry. Its simple object model provides a
short learning curve for beginners, while its “write once, run anywhere” promise has given a tremendous
impetus for professionals seeking to create platform independent applications. The ability to create
applications in Java that run inside a web browser as a front end to a web application or as a backend in a web
Java/MP Language Overview
Java/MP is a multiparadigm programming language designed as an extension to the Java programming
language. The language has been conceived and designed by Timothy Budd. It is really a new version of the
earlier multiparadigm language Leda. Java/MP is an upward compatible superset of Java. In addition to the
object oriented style present in Java, it introduces functional and logic programming styles. One of the
interesting aspects of Java/MP is that it introduces very few syntactic additions to Java and also maintains the
original feel of the Java language. The language is compatible with the Java VM, and implemented as a
source-to-source transformation. So the output generated by the prototype compiler is pure Java code, which
is in turn fed to a Java compiler to produce byte code. This chapter provides a brief description of the
important features new to Java/MP.
Java/MP to Java Translation
This chapter describes how Java/MP features are translated into Java by the prototype compiler.
3.1 Functions as values
As noted in section 2.1, higher order functions are an important feature of the functional paradigm. A function
that takes a function as parameter or returns a function as result is called a higher order function. Let us
consider the issues involved in treating functions as values.
3.1.1 Types For Functions
In programming languages, values are always associated with types. The first step in treating functions as
values is to develop a technique for assigning types to functions. The type of a function is determined by the
formal arguments (types and arity7) and the return type of the function. Consider functions square, cube,
Functions as expressions
In a system where functions can treated as values, it is often convenient to treat functions as expressions. It
simplifies the task of creating simple functions that will only be treated as values and never be invoked
directly by name. If the function will never be referred to by name, it seems wasteful to assign a name to the
function. Such a function can very well be specified “inline” where needed. This feature is supported to
varying degrees in many object oriented languages such as Python, Smalltalk, Ruby and Eiffel.
To see how this can be useful, consider the following Java/MP code:
Operator Overloading
All operators are assigned names in Java/MP. Operator overloading in Java/MP is done by declaring a
function with the corresponding name in the global scope. This technique is used in Leda, as well as other
languages such as Python. There are a couple of restrictions. The assignment operator =, the arrow operator <-
, and the conditional assignment operator ?: cannot be overloaded. Also, the default meanings assigned by
Java for operators cannot be changed. So arithmetic operators cannot be overloaded on ints, the complement
operator ! cannot be overloaded on booleans etc. The current prototype implementation does not allow
overloading of operators on any primitive types. This is an implementation imposed restriction and not a
language defined restriction. Refer to Appendix A. for names assigned to operators. Following code shows
the binary operator plus (+) overloaded on Integer arguments
Pass by Name
The purpose of introducing pass by name in Java/MP is twofold. First, evaluation of pass by name arguments
is delayed until the point an expression is used rather than the point at which the function call is made.
Second, allow changes made by the callee to a by name parameter to reflect back in the caller. When an
argument is to be passed by name, we simply wrap the argument in a class (better known as a thunk ) and use
an instance of this thunk as the actual argument.
Logic programming
Logic programming is implemented using a combination of all the features mentioned above, a new data type
called relation and the new arrow operator. A rather simplified way of understanding a relation is to think of
it as an extension of boolean. It really represents a func tion that returns a boolean. In addition, it also takes
another relation as argument. Since we would like to pass relations as arguments and return them from other
functions, the internal representation implements this function as part of a class. The type relation is defined in
the standard library as follows:
Java/MP Example Programs and Techniques
Iteration
Many useful styles of iteration are described in chapter 5 of [Budd, 1995]. This section discuses two
additional iteration techniques. The first proves useful in enabling logical style iteration over existing objectoriented
containers. The second one is an attempt to improve upon the traditional object-oriented iteration to
fit somewhat better in the multiparadigm framework.
Implementation Notes
A prototype implementation for the Java/MP compiler was developed as part of this project to test the
language and verify the translation techniques described in [Budd, 2000]. This chapter gives a brief overview
of the implementation and also the lists the known limitations
Implementation Details
The compiler is implemented as a command line executable that processes a single Java/MP source file and
produces Java source code as output. Input and output files are specified as command line parameters. The
Java source produced as output is fed to a Java compiler to produce byte codes. The compiler is written using
flex version 2.5.4 and GNU bison 1.2.8. The source consists of about 8600 lines of code and approximately
six months were spent in developing the compiler. An existing Java 1.1 grammar [Dmitri, 1998] for flex and
bison was used as a starting point. Changes and additions to the grammar were made to suit the code
generation better and accommodate the following features
Testing
The compiler implementation has not undergone a rigorous and formalized testing process. The primary goal
in developing the compiler was to demonstrate that our ideas for Java/MP were in fact realistic rather than
implement an industrial strength compiler. However the implementation has been put through some amount of
testing as noted below to make sure its quality is acceptable for our research purposes.
The symbol table was first tested independent of the parser by using scripts that added entries into the symbol
table, performed lookups and printed all symbol table content. The aim was to verify if the symbol table
behaved as expected and to determine any memory leaks. Borland Code Guard was used to monitor runtime
memory usage for detecting memory leaks. All the editing and debugging was done in Borland C++ Builder.
After integrating the symbol table into the parser, testing was done using sample Java/MP programs to ensure
that modifications to the symbol table did not introduce new problems. The system was again subjected to
memory leak detection. The lexer and parser are known to have memory leaks that are difficult to fix due
Future Work and Conclusion
Future Work
The current prototype compiler implementation was built as a tool for evaluating and verifying many of the
ideas related to implementation we had in mind for Java/MP. Thus many simplifying assumptions have been
made as noted in section 5.3. But availability of a solid compiler is essential for every programming language.
As Nicklaus Wirth notes,
Conclusion
Adding multiparadigm features to Java is certainly a feasible idea. Java/MP combines the logic, object
oriented and functional paradigms in a manner that allows the programmers to mix and match the paradigms
seamlessly. Java/MP adds very few extensions and maintains much of the feel of Java. There is no doubt
about the usefulness of a multiparadigm language as a tool for problem solving and is demonstrated by the
Leda book [Budd, 1995]. Java/MP brings these benefits to a much wider audience by using Java as its
foundation.
It is evident from the translation techniques that Java/MP programs will typically have greater memory
requirements than pure Java solutions for the same problem. It is difficult to estimate how execution
efficiency will be affected without conducting formal tests. No testing or benchmarks have been conducted to
accurately asses the runtime efficiency and memory overhead of Java/MP programs