N9I Overview

Written on Sun, 17 Jan 2010 22:07:24 +0000 - Last updated on Mon, 08 Feb 2010 17:19:22 +0000Conceptual programming language intended to blur the distinction between files and variables. N9I allows local and remote file accesses through a variety of protocols, as well as a simple namespace, module, and class system. Objects may be strictly typed or typeless. Functions and methods are first-class objects.

N9I Principles and Goal

Abstraction of I/O

The foremost principle of N9I is to abstract away what needs abstraction. Current mechanisms for I/O require specialized interfaces that differ from platform to platform. Stream classes may implement a plethora of methods, depending on whether you want to write characters or bytes. In some languages you are required to wrap several objects around one another just to read a line of text. The author of N9I once ran into a situation where he was required to wrap a string around a "string reader" object - an object whose purpose is to read a string. It is then that he realized that, instead of using a mess of reader objects and input classes to provide a general I/O interface, one could devise a mechanism by which I/O is effectively hidden from both the developer and from other functions. Functions will not have to mess with "readers" or "writers" but simply with strings, numbers, arrays, and objects (in other words, what would be a "XYZ stream reader" is seen as a normal string). Consider: A good example of this already in use is Texas Instruments' TI-89/92 BASIC environment. The BASIC language on that calculator has literally no distinction between a "file" and a "variable" (everything on the TI-89/92 filesystem is referred to as a variable) although it does restrict which types of files/variables may be manipulated through BASIC (strings, numbers, lists, matrices, functions, and expressions may; text, data, and other types cannot). Older languages require you to manually manage every byte of memory you allocate, while more modern languages include some form of garbage collection. The designer of N9I believes that the next logical step is to abstract away I/O in much the same manner.

Maximum Source Code Portability

The Java programming language attempted to introduce cross-platform binary object files ("write once, run anywhere"). These require a virtual machine, which is available on many widely used platforms. Nevertheless, Java bytecode applications never seemed to be popular on the desktop. Perhaps it was because the presence of a virtual machine slowed down overall performance. Perhaps the not-quite-right look of Java's GUI toolkit puts people off. Perhaps Java isn't as cross-platform as it tries to be ("write once, debug everywhere"). For whatever reason, "write once, run anywhere" has failed. Furthermore, it may not be feasible to introduce a virtual machine on some platforms (Apple, for instance, will not allow the JVM to run on its iPhone). Regardless of that fact, the computing landscape is becoming more heterogenous in this decade. Free/open source operating systems such as Linux become ever-so-slightly more popular (especially outside the United States, where the iron grip of Microsoft is not as prevalent), and smartphone OSs such as Android and the iPhone OS introduce another factor. Companies who develop software typically focus on Windows only because they claim it would not be worth the money to make their software accessable to others. While it is possible to develop for multiple platforms using a conventional language, N9I is explictly designed to be portable at the source code level. A few design decisions were made regarding this - for example, N9I requires that all files on the local filesystem be referenced using a Unix path (even under Windows), and the compiler emits a warning if you use any platform-specific APIs. However, N9I compiles directly to a native binary instead of to a virtual machine (although it can be compiled into Java bytecode as well). Because N9I compiles to native code, it can provide cross-platform interfaces to OS facilities like environment variables, configuration, audio and video, and window management, while avoiding the pitfalls of a virtual machine. N9I is also an interpreted language, meaning you can run your program without needing to compile it. N9I aims to reduce the effort and cost needed to write fully cross-platform applications. It is not feasible to expect 100% of N9I source code to compile on all of the supported platforms (i.e. because some platforms have capabilities others do not). N9I does not promise that. However, a reasonable effort is made to ensure that code that does compile on multiple platforms will function equivalently on those platforms. N9I provides a module called "Capability" that can be used to check to see if a platform supports a certain feature, such as tray icons. You can check for a Capability and write code that uses the capability only if the capability exists, rather than writing blocks of Win32-specific or Mac-specific code using OS-dependent APIs to access the capability.

@ ("at") and ResourceAlias

The foundation of N9I is an operator called @. The @, or "at operator", identifies the resource "at" the given location (which may be a string literal or a variable). By default, the at operator returns a ResourceAlias object. A ResourceAlias is "magic" in that assigning or reading a reference to a ResourceAlias will actually redirect the read or write to the specified resource. Destroying the ResourceAlias using its "unset" method clears the variable and allows it to be reused (note that unset cannot be called directly on the at operator). A ResourceAlias may also be created of a variable. Method calls (other than unset) invoked on the ResourceAlias are also redirected to the underlying resource. A ResourceAlias can automatically "cast" itself into the needed variable type. For example, if you read from the ResourceAlias into a byte array, it will read binary data. If you read the ResourceAlias into a string or character array, it reads character data. If you write a string or character array to a ResourceAlias, N9I will write character data. If you write a byte array to a ResourceAlias, N9I will write binary data. An array of strings is represented a file in which each line corresponds to an array element. Dictionaries containing strings are represented by a key-value pair in each line, with the key and value separated by equals signs. Objects are represented as binary data, unless they are being stored to or read from an XML or JSON file (in which case it is stored as plain text). When reading or writing to a local file, N9I respects the system's preferred line ending. When accessing a remote resource or a socket, N9I uses a CR+LF as line ending. When reading a file into a string, N9I will read the entire file. To read only one line, treat the file as an array and call pop() on it. The at operator can also detect, based on the URI, what sort of resource the URI points to. For example, if the filename ends in ".zip", N9I assumes the at operator is being invoked on a zip file and provides zip methods on the resulting object; if given an XML or JSON file, it will allow you to create an Object out of it simply by casting the result to an Object. The at operator can also be invoked on remote hostnames in the form host:port. The IO.Authorize function is used to grant the program permission to access certain resources, such as FTP or HTTP locations. In some protocols, these may be placed directly in the URI passed to the at operator (for obvious reasons, this is probably not a good idea).

N9I keywords

Project files

Typically, languages define only the grammar of program source code. They do not, on the other hand, dictate the grammar of files used to configure compilation options. This results in code being difficult to move between development environments. N9I will define a "project" file type that is part of the official N9I specification. This project file will contain project-related settings. The N9I compiler will be given this file as input and is expected to be smart enough to produce a corresponding binary as output. This should result in an N9I codebase being not only operating system independent but also IDE-independent. This file will dictate options such as:

Packages, modules, classes, functions...

How this would look in a folder

Visibility modifiers

These can be applied to anything defined in a module

N9I API module structure