Converting LES to C#/.NET

LES is very comparable to Enhanced C#, especially its lexer (e.g. "strings", 'c'haracters, and @identifiers are practically the same between the two languages). Both languages have

And in addition, LES has superexpressions, which serve a similar function as block-call statements in EC#, and are also used to represent fn method declarations, if statements, for loops, return statements and virtually all other “special” syntax.

LeMP macros are available to “compile” LES into C# or Enhanced C#. To do this, your LES file needs to have the following first line:

import macros LeMP.Prelude.Les;

To gain access to LLLPG, add

import macros Loyc.LLPG;

Differences & similarities between LeMP/LES and C#

I don’t want to bore you with all the details, but the most striking difference between LES and C# is that LES has no keywords whatsoever. Words like if and while are not parsed in a special way because of the actual word used, but because of the how the statement is formatted.

Anyway, here’s a list:

Similarities:

The following statements mean the same thing in LeMP/LES and C#:

return;
return x;
continue;
break;
var x = value;
x = y++ * 10;
Console.Write("Hi");

Differences:

In many cases the difference is simply that you need an extra semicolon or braces.

using System.Collections.Generic;             // C#
import System.Collections.Generic;            // LES
class Foo {                                   // C#
  public Foo() : this(0) { }
  public Foo(int num) { }
}
class Foo {                                   // LES
  public cons Foo() { this(0); };
  public cons Foo(num::int) { };
};

class Foo : BaseClass, IEnumerable { }        // C#
class Foo(BaseClass, IEnumerable!object) { }; // LES
int Square(int x)       { return x*x; }       // C#
def Square(x::int)::int { return x*x; };      // LES
void Quit() { throw new QuitException(); }    // C#
fn Quit()   { throw (new QuitException()); }; // LES
int x, y; string s;                           // C#
x::int; y::int; s::string;                    // LES
int[] list1;      List list2;                 // C#
list1::array!int; list2::List!int;            // LES
bool flag = true;   int? maybe = null;        // C#
flag::bool = @true; maybe::opt!int = @null;   // LES
int more = (int)(num * 1.5);                  // C#
more::int = (num * 1.5) -> int;               // LES

while (x) Foo();                              // C#
while (x) { Foo(); };                         // LES
while x   { Foo(); };                         // LES
do x/=2; while (x>y);                         // C#
do { x/=2; } while (x>y);                     // LES
for (x = 0; x < 10; x++) Console.WriteLine(x);      // C#
for (x = 0, x < 10, x++) { Console.WriteLine(x); }; // LES
foreach (var item in list) { Process(item); } // C#
foreach (item in list)     { Process(item); };// LES
if (c) return 0;                              // C#
if (c) { return 0; };                         // LES
if c   { return 0; };                         // LES
if (i < list.Count) str.Append(list[i]);      // C#
if (i < list.Count) { str.Append(list[i]); }; // LES
unless i >= list.Count { str.Append(list[i]); }; // LES
if (inc) x++; else x--;                       // C#
if (inc) {x++;} else {x--;};                  // LES
if inc   {x++;} else {x--;};                  // LES
switch (x) { case 123: break; default: break; } // C#
switch (x) { case 123; break; default; break }; // LES
switch (x) { case 123 { break; }; default { break; }; }; // LES
try { } catch (Exception ex) { } finally { }; // C#
try { } catch ex::Exception  { } finally { }; // LES

Some error messages that don’t mention a semicolon are actually referring to a missing semicolon; LeMP gets confused because certain sequences like

if (a) { ... } if (b) { ... };

is parsed successfully as a single statement if (a, {...}, if, b, {...}), which the “if” macro does not understand because there are too many arguments.

Learn more about LES.