Cola (programming language)

Cola is a programming language similar to Java and C# with some higher level features of Perl and Ruby including first-class regular expressions. It can be compiled for the Microsoft .NET CLR or the Parrot virtual machine.

Cola is a compiled language with static type checking, but the designer mixed in some of the features more common to scripting languages like Perl and Ruby. Cola is less of a new language "design" than a mix of several very powerful languages with the following key principles in mind:

C++, Java and C# programmers should be immediately comfortable.

Convention over Code - Things that are conventional are implicit defaults. The default scope accesses can be configured with compiler flags to remove burden from the language. (See Java/C# public keyword)

Low signal-to-noise ratio - Reduced keyword clutter and an emphasis on improved readability and less on controlling access of other programmers. In practice, the use of the word public dominates Java and C# syntax, based on source code analysis. Cola omits the public keyword, and supports C++ style of scope access sections, and provides a single character @ to make a member private.

Regular Expressions, Lists and Associative Arrays get special treatment - Most programming involves text manipulation, lists and iteration. Regular expression support dramatically increases the brevity and productivity "power" of a language, but BUILTIN syntax for regular expressions improves the readability of it. In Cola, regex and pattern matching is part of the syntax. Future plans include equal support of inline EBNF grammar syntax and parsing functions.

Scriptlets - Cola allows globals functions, or none at all for a simple script. Though the language is compiled, it has a script mode that compiles on the fly.

A Hello world program Cola style:

// C/Perl-style without classes
// Cola package/global methods are static by default, void by default
main() {
   println("Hello World");
}
// Cola OO-style
// classes, methods and constructors public by default, fields private by default
class Hello {
   string mesg;
   new() { mesg = "Hello world\n"; }
   static void main() {
     print(mesg);
   }
}


Use of most of the .NET framework is possible, including generics, interfaces, arrays, as well as the standard enum constants in the various assemblies. The "using" directive imports a namespace just like C#, to allow unqualified names to be used. In general, C# syntax for any .NET framework class or method is identical in Cola.

 // .NET System.IO.File sample
 using System.IO;
 main() {
   foreach(var line in File.ReadAllLines("flintstones.txt"))
     if(line =~ /FRED/)
       print(line);
 }
 // .NET Winforms Example
 using System.Windows.Forms;
 main() {
   // uses the .NET enum value MessageBoxButtons.YesNoCancel
   MessageBox.Show("Testing", "Testing", MessageBoxButtons.YesNoCancel);
   var form = new Form();
   form.Text = "Cola Winforms Sample";      
   Application.Run(form);
 }
 // .NET System.Xml Example
 using System.Xml;
 main()
 {
   var doc = new XmlDocument();
   doc.LoadXml(
      @"<book genre='novel' ISBN='1-861001-57-5' misc='sale item'>
        <title>The Handmaid's Tale</title>
           <price>14.95</price>
        </book>");
   var element = doc.DocumentElement;
   io.println(element.InnerXml);
 }
 // Oracle.DataAccess sample
 using Oracle.DataAccess.Client;
 main() {
   string first, last;
   var conn = new OracleConnection("Data Source=DEV;User Id=scott;Password=tiger;");
   conn.Open();
   var cmd = new OracleCommand("select first_name, last_name from doctor", conn);
   var reader = cmd.ExecuteReader();
   while(reader.Read()) {
     first = reader.GetString(0);
     last = reader.GetString(1);
     print(first + " " + last);
     conn.Close();
 }


Cola can currently compile against a significant portion of the .NET CLR standard libraries, with lack of support for pointer / unsafe types.


Cola allows you to name constructors after the class name in the tradition of C++/Java/C#, or to use "new" and "delete" for constructor and destructor names, to simplify the appearance of code and improve cut-and-paste productivity. Cola has a special constructor parameter binding that acts as an initialization mechanism.

class T {
  int x, string y;
  new(x,y) {}       // Automatically initializes x and y and establishes the types of the parameters
}

Constructor delegation is supported, using the "this" keyword from the constructor.

class T
{
  int x, string y;
  new(int x) {
    this.x = x;
  }
  new(int x, int y)
    : this(x)       // delegate to the 1-arg  constructor
  {
    this.y = y;    // init the 2nd field
  }
}

Cola 0.24 implements properties with getters and setters per the C# standard.

class T
{
  int @len;
  int Length { get { return len; } set { len = value; } }
}

Cola provides both prefix and postfix array declaration notation, and both static and dynamic arrays. This is a productivity choice by the author, to improve comfort for diverse programmer background (C/C++ vs Java/C# style), and to reduce notation (static arrays).

int[] arr = new int[12];    // prefix, dynamic
int arr[] = new int[12];    // postfix, dynamic if no size specified
int[12] arr;                // prefix, dynamic, requires a new
int arr[12];                // postfix, static auto-allocated
int arr[5] = {1,2,3,4,5};   // postfix, static auto-allocated and initialized
int arr[]  = {1,2,3,4,5};   // postfix, no size, but static allocation due to initialization

Cola supports N-dimensional arrays. Currently they are implementing as contiguous vectors on the CLR rather than sparse arrays.


An example of Cola's support for regular expression and matching is given below. First a conventional example that echoes Perl's approach.

// implicit match backreference
if(mesg =~ /(yes)(madam)/) {
   print("In string: " + $0);
   print("we matched: " + $1 + ", " + $2);
}

Cola includes a more powerful, expressive notation for matching called match aliasing. Any match expression can be captured as a named object of type match

// explicit named match example
if(str =~ /foo(bar)/ as match1) {
   // default is matchA
   print(match1.$1);
}

For the scope of the if statement, match1 is in scope. The advantage of the syntax is more evident when we have multiple, nested matches.

if(str =~ /foo(bar)/ as match1) {
   // We can use a backreference in a new match expression
   // $1 refers to match1 until a new match expression, after which
   // it refers to the new match in immediate scope. To refer back
   // we use match1 alias (match1.$1)
   if($1 =~ /b(ar)/ as match2) {
      print(match1.$1);    // match1 still in scope
      print(match2.$1);    // match2 now in scope, and the default
      print($1);           // same as match2.$1
   }
}

Cola includes some static type inference via the "var" keyword (similar to C#), as well as a shorthand "new" notation where the type is inferred from the right side.

 // equivalent
 var s = new Dog();

Also supported is a virtual constructor, to create objects from another object.

 Animal a = new Dog();
 Animal b = a.new();
 var v = a.new();  // v will be of the Animal type, but receives a Dog

Cola includes a foreach statement, supporting iteration on arrays and the builtin .NET types in System.Collections, or any class that implements "IEnumerator GetEnumerator()". Generics are now supported in 0.20. Cola foreach() is implemented similar to the C# compiler, generating array iteration code when arrays are used, and using the IEnumerable interface or GetEnumerator() convention.

  // Uses .NET System.Collections
  var list = new System.Collections.ArrayList();   // note the inferred type
  list.Add("LITTLEDOG");
  list.Add("BIGDOG");
  list.Add("LITTLECAT");
  list.Add("BIGCAT");
  foreach(string s in list) {
     // Nested named matching
     if(s =~ /(LITTLE|BIG)/ as size) {
        if(s =~ /(DOG|CAT)/ as animal)
           print("Animal is a " + size.$1 + " " + animal.$1);
     }
  }

It is also possible to iterate inline arrays.

  for(var item in {1,2,3,4,5,5,4,3,2,1})
  {
     io.println(item);
  }
  for(var s in {"this","is", "a", "inline", "array", "!"})
  {
  }


Cola 0.25 adds enum support. It is possible to define enumerated types as well as make use of the standard .NET enums.

 enum Direction {
    North = 0,
    South,
    East,
    West
 }
 Direction d = Direction.North;  

As of 0.20 Cola includes generic type support. The default(type) operator was added as well, in order to return values or initialize objects within a generic class. This follows the C# standard.

 // Sample generic class in Cola
 // Demonstrates a single parameter generic stack with a private array
 
 class Stack<T>
 {
     int   @top;
     T     @vector[100];
     // properties
     int   Length { get { return top; } set { top = value; } }
     T Top {
        get { if (top > 0) return vector[top - 1]; return default(T); }
     }
     // constructor
     new() {
        top = 0;
     }
     // methods
     void Push(T item) { 
        vector[top++] = item;
     }
     T Pop() {
        T t = Front();
        if(top > 0)
           top--;
        return t;
     }
 }
 main()
 {
     var stack = new Stack<string>(); // Stack<T> where T = string
     foreach(var word in { "This", "is", "a", "statically", "initialized", "dynamic", "array"}) {
        stack.Push(word);
     }
     io.println("Stack has " + stack.Length + " items");
     io.println("Top item is " + stack.Top);
     io.println(stack.Pop());
     io.println(stack.Pop());
     io.println("Stack has " + stack.Length + " items");
 }


The current version of the Cola compiler for .NET is available from the website [1]

References

  1. Cola Programming Language.

External links

This article is issued from Wikipedia - version of the Sunday, April 17, 2016. The text is available under the Creative Commons Attribution/Share Alike but additional terms may apply for the media files.