Aardvark Language: Project Web Hosting - Open Source Software

The Aardvark Language

Developers

Discuss project

Project blog

Please send a message with your thoughts about this language, or if you would be interested in joining this project. The task of developing a type-checker, a code-generator and a SDK, would be too much for one person (especially if it was uncertain if there was any interest in the language). The idea for a language is also so far only based on one person’s ideas and programming experience, so input from others would be highly valued.

Sincerely, Morten Telling Nielsen

Join this project:

To join this project, please contact the project administrators of this project, as shown on the project summary page.

About this project:

This is the Aardvark Language project ("aardvarklanguage")

This project was registered on SourceForge.net on Jun 19, 2014.

Not what you're looking for?

SourceForge.net hosts over 100,000 Open Source projects. You may find what you're looking for by searching our site or using our Software Map.

About SourceForge.net:

SourceForge.net is the world's largest provider of hosting for Open Source software development projects. SourceForge.net provides a variety of services to projects, including a download mirror network, collaborative development tools (like CVS and Subversion), and tools to support discussion and support. These services are provided to projects and their end-users free-of-charge.

About Open Source:

Of benefit to users, Open Source software is licensed so you can download and use the software free-of-charge. The source code for this software is made available free-of-charge, you (or a programmer you hire) can make changes to this software to better meet your needs, and you can release your changed code back to the community passing the benefit on to other users.

General Principles

Aardvark is intended to be a 'programmer’s language' with as few experiments as possible and a very traditional Java-like syntax. Innovations are only in response to the actual problems and annoyances faced regularly by programmers.

A key feature of Aardvark is the robustness of the compiled code. Another feature is the attempt to heighten the level of abstraction while programming, to avoid the programmer being bogged down in nitty-gritty details. This higher level of abstraction is achieved in part by a meta-programming extension to the language; all of this while keeping everything simple and intuitive.

Robustness

Computers are often used in situations where failure could result in human injury or even death. Many high end applications also often become unresponsive or fail in other ways. During software development, it is also a major task to weed out problems that make applications fail in this way. It would be highly desirable to have a programming language that would assist the software developer in producing more robust software. Non-null languages have been developed, but null-pointer exceptions are only part of the problem – software fails due to other unhandled exceptions than null-pointer exceptions, and it fails in other ways than by unhandled exceptions.

Robustness in a programming language is here defined as follows:

Robustness in a programming language is the ability of the resulting compiled code to follow the algorithm laid down by the programmer in the source code.

First of all, robustness requires a language to be strongly typed, since a crashed application is obviously not robust in any sense of the word, nor would it follow the algorithm laid down by the programmer.

This formal definition coincides with the three ways programs that are developed in strongly typed languages fail: thread termination following uncaught exceptions, deadlock, and infinitely-loops. Checked exception-handling can be said to be part of the algorithm laid down by the programmer, since it is clearly proclaimed in the source code or documentation – whereas unchecked exception-handling is not! It could be said that it is part of the algorithm laid down by the programmer, that the computation will proceed past a given point. It could also be said that it was part of the algorithm laid down by the programmer that a method with a return type (even if it was void) should return at some point. So again the definition of a robust programming language coincides with the ways in which programs fail.

Exception-handling

If unchecked exception-handling is disallowed it raises the question of what to do when the executing program encounters a problem that cannot be handled by checked exception-handling (like division by zero, integer over/under-flow, or index out of bounds). The source code obviously cannot be filed with code to catch an exception for every arithmetic operation, data structure access, or other operations that could throw an exception. In these cases the language must provide structures to let the program resume computation with usable data (a bit like exception-handling in the IEEE 754 standard), by returning max- or min-values in the cases of division by zero and integer over/under-flow, or by returning the first or last element of the data structure in the case of index out of bounds.

There are of course problems that the language can never handle, particularly out of memory problems. In these cases the thread must simply log the event and terminate.

A language without unchecked exception-handling must consequently also be statically typed, since there are no practical ways to react when a type is subjected to methods or operations that do not apply to that type, such as in dynamically typed languages.

Deadlock

A program can be made deadlock-free by analyzing the call-graph, and finding circles where a call from a critical section can call the same section, only through non-critical sections or through other critical and non-critical sections. To enter the section a thread must then hold a semaphore for all critical sections involved in that circle (and side loops to that circle). There must also be a check to see if a thread wanting to enter such a section already holds a semaphore for that circle.

Infinitely-loops

Mechanisms to prevent unintended infinitely-loops would be desirable. Finding all infinitely-loops in a deadlock-free environment would provide a solution to the halting problem, so a best-effort solution would suffice. In all cases, finding infinitely-loops is difficult, and distinguishing intentional loops from unintentional loops is also difficult, so this aspect of robustness would probably have to be put on the wish list for future enhancements of Aardvark.

Intuitiveness

This term is hard to define specifically, but one can start by looking at what programmers have been doing in the past, and what consensus has been reached about how things should be done. We can then assume that this consensus is the intuitive correct one.

Constant fields (in Java final static) identifiers are traditionally in uppercase letters only. In class names, only the first letter traditionally is in uppercase, whereas module names are in in lowercase only. Fields and variables are traditionally in lowercase, and so are method identifiers. The rule seems to be: lookups that can produce variable output are in lowercase, whereas lookups that produce a constant output are in uppercase (with the exception of modules). In this language all constants must have the first letter in uppercase and the constants are: modules, classes, singletons, and constant fields.

In classes, the consensus about the order of class members seems to be: first fields, then constructors, and then methods. In this language the compulsive order is: constant fields, properties, constructors, and then methods. Constant fields are placed first because they exist in a context outside that of an instance, and are created before any instances. For consistency the order is also maintained in modules and singletons. A consensus has also developed among programmers about indentation and other formatting of code, so auto-formatting should be used (also discussed later in Automation).

Higher level of abstraction

An aim of the language is to let the programming take place at a higher level of abstraction. First of all a higher level of abstraction, which means that everything that can be automated should be automated, is used so that the programmer is not burdened with minor tasks. Second this also means that there should be a meta-programming extension to the language.

Automation

The NetBeans and Eclipse IDE's both have automated operations to: format the source code, organize/fix imports, and encapsulate fields. This means that the language or editor should have: an auto-formatter, a better way to import, and an automated encapsulation of fields. To begin with the formatter of NetBeans or Eclipse would be adequate, and a better way to import will be discussed in Modules, Classes, and Scope (to appear later).

Automation of encapsulation would mean that getters and setters for a field should be implicit, but with an option to make both explicit. This would effectively make a module, singleton, or class variable deceleration a property deceleration (property, as in Javabean-properties) – from here on such module, singleton, or class members will be referred to as properties.

To heighten the level of abstraction the access to properties should also be automated, so that the getter or setter is automatically used when a property is accessed. Accessors are also used internally in classes, singletons, or modules.

The principle of a higher level of abstraction is also mentioned in Types and Inheritance.

Meta-programming extension

The Meta-programming idea is best illustrated by the Immutable and ReadOnly examples. Immutable and ReadOnly inherit from the language provided Modifier. The rule is that when a modifier is applied to a class, whatever the modifier says applies to all class members (also inherited). If the modifier does not make sense for that class member, it is ignored. Modifiers have the ability to add, remove, and modify all class members, and software developers can write their own modifiers, extending the Modifier.

This example illustrates the use of the Immutable modifier:

immutableList <- (Immutable ArrayList).new(list)

For ArrayList the Immutable modifier means that: The setters of all properties are made private (they would actually be private already). It means nothing to constructors, so for them the modifier is ignored. All mutable methods and all methods that call them are removed.

The modifier may also define if it is to be applied to the type of the properties themselves. In an actor model, one would want to use immutable shared data exclusively, so in this situation the immutable would have to be a deep immutable (deep as in a deep clone versus a shallow clone). So in such immutable shared data, the modifier would have to be applied downward to the types of properties, and so forth downward until natural immutables are reached.

If ArrayList was like the Java ArrayList, Immutable ArrayList would be the subtype of Immutable AbstractList, Immutable List etc. Although Immutable ArrayList has all public methods, getters, and setters of ArrayList, it is not an ad-hoc supertype of ArrayList. If Immutable ArrayList was an ad-hoc supertype of ArrayList, instances of ArrayList could be assigned to variables of type Immutable ArrayList, and the type Immutable ArrayList would not be guaranteed to be an Immutable.

The ReadOnly modifier on the other hand creates an ad-hoc supertype when applied, so instances of ArrayList can be assigned to ReadOnly ArrayList types – this is actually the only difference between Immutable and ReadOnly. The important difference, between a ReadOnly supertype and an ordinary supertype, is that typecasts are not allowed for ReadOnly supertypes; otherwise another module handed a ReadOnly instance could typecast it to its original type, and make changes to it.

Modifiers can be used late on a variable as demonstrated in the Immutable example above, or they can be used at the development-time of a class. Modifiers typically used at the development-time of a class are scope decelerations, such as public, private, and protected. Obviously a scope can be overridden; in a public class (the default) all members are public, except if overridden by a private or protected modifier. The principle of downward applying modifiers also applies to the accessors on properties; so in a property declared private, the getter and setter are both private.

Aardvark supports multiple-inheritance (see more in Types and Inheritance). Multiple-inheritance can also be used late on variables. This lets the programmer create ad-hoc types, and instances of such, without significantly raising the complexity of the language– the construct exists already for modifiers. In fact there is no reason why there should be any distinction between classes and modifiers, except that modifiers inherit from the language provided Modifier. So these constants can be modifier-classes, modifier-singletons, or modifiers (also scopes), classes, or singletons on their own.

Besides being used on variables or classes, modifiers can be applied to most or all of an application (see how in Modules, Classes, and Scope). When used this way, the modifier model already described implements some parts of the aspect-oriented programming paradigm: with the ability to add code to getters and setters etc. With some extra syntax, the language combined with modifiers can be made to implement most of the aspect-oriented paradigm (not dealt with here).

A modifier can be a singleton at the same time as it is a scope. An example is the compile modifier and singleton. Modules, classes, and class members can be declared compile scope. The same time properties and methods on the compile singleton can be accessed with the lookup operator ('.' the dot operator). Obviously a compile scope can only be accessed from another compile scope or the compile singleton. Most of the logic used to implement the behavior of the Immutable and ReadOnly modifiers described above, would be such compile scope logic. Another use of the compile singleton would be to raise or suppress compile-time warnings or errors.

Persistent is another modifier that is also a singleton. The modifier would obviously be used to declare classes persistent, so to make their properties persistent. Somewhere in the software, the persistent singleton would have to be set to how the persistence should work for that application.

Other Material:

Aardvark Language Manifesto.pdf

Name and Icon PDF

To appear later:

Battle-plan for project development

Project Web Hosted by SourceForge.net

©Copyright 1999-2009 - Geeknet, Inc., All Rights Reserved

About - Legal - Help