diff options
Diffstat (limited to 'neat.html.markdown')
| -rw-r--r-- | neat.html.markdown | 299 | 
1 files changed, 299 insertions, 0 deletions
| diff --git a/neat.html.markdown b/neat.html.markdown new file mode 100644 index 00000000..6a319a7d --- /dev/null +++ b/neat.html.markdown @@ -0,0 +1,299 @@ +--- + +language: neat +contributors: +    - ["Feep", "https://github.com/FeepingCreature"] +filename: LearnNeat.nt + +--- + +Neat is basically a smaller version of D1 with some experimental syntax and a focus on terseness without losing the basic C-like syntax. + +[Read more here.](https://github.com/FeepingCreature/fcc/wiki) + +```D +// single line comments start with // +/* +  multiline comments look like this +*/ +/+ +  or this +  /+ these can be nested too, same as D +/ ++/ + +// Module name. This has to match the filename/directory. +module LearnNeat; + +// Make names from another module visible in this one. +import std.file; +// You can import multiple things at once. +import std.math, std.util; +// You can even group up imports! +import std.(process, socket); + +// Global functions! +void foo() { } + +// Main function, same as in C. +// string[] == "array of strings". +// "string" is just an alias for char[], +void main(string[] args) { +  // Call functions with "function expression". +  writeln "Hello World"; +  // You can do it like in C too... if you really want. +  writeln ("Hello World"); +  // Declare a variable with "type identifier" +  string arg = ("Hello World"); +  writeln arg; +  // (expression, expression) forms a tuple. +  // There are no one-value tuples though. +  // So you can always use () in the mathematical sense. +  // (string) arg; <- is an error +   +  /* +    byte: 8 bit signed integer +      char: 8 bit UTF-8 byte component. +    short: 16 bit signed integer +    int: 32 bit signed integer +    long: 64 bit signed integer +     +    float: 32 bit floating point +    double: 64 bit floating point +    real: biggest native size floating point (80 bit on x86). +     +    bool: true or false +  */ +  int a = 5; +  bool b = true; +  // as in C, && and || are short-circuit evaluating. +  b = b && false; +  assert(b == false); +  // "" are "format strings". So $variable will be substituted at runtime +  // with a formatted version of the variable. +  writeln "$a"; +  // This will just print $a. +  writeln `$a`; +  // you can format expressions with $() +  writeln "$(2+2)"; +  // Note: there is no special syntax for characters. +  char c = "a"; +  // Cast values by using type: expression. +  // There are three kinds of casts: +  // casts that just specify conversions that would be happening automatically +  // (implicit casts) +  float f = float:5; +  float f2 = 5; // would also work +  // casts that require throwing away information or complicated computation - +  // those must always be done explicitly +  // (conversion casts) +  int i = int:f; +  // int i = f; // would not work! +  // and, as a last attempt, casts that just reinterpret the raw data. +  // Those only work if the types have the same size. +  string s = "Hello World"; +  // Arrays are (length, pointer) pairs. +  // This is a tuple type. Tuple types are (type, type, type). +  // The type of a tuple expression is a tuple type. (duh) +  (int, char*) array = (int, char*): s; +  // You can index arrays and tuples using the expression[index] syntax. +  writeln "pointer is $(array[1]) and length is $(array[0])"; +  // You can slice them using the expression[from .. to] syntax. +  // Slicing an array makes another array. +  writeln "$(s[0..5]) World"; +  // Alias name = expression gives the expression a name. +  // As opposed to a variable, aliases do not have an address +  // and can not be assigned to. (Unless the expression is assignable) +  alias range = 0 .. 5; +  writeln "$(s[range]) World"; +  // You can iterate over ranges. +  for int i <- range { +    write "$(s[i])"; +  } +  writeln " World"; +  // Note that if "range" had been a variable, it would be 'empty' now! +  // Range variables can only be iterated once. +  // The syntax for iteration is "expression <- iterable". +  // Lots of things are iterable. +  for char c <- "Hello" { write "$c"; } +  writeln " World"; +  // For loops are "for test statement"; +  alias test = char d <- "Hello"; +  for test write "$d"; +  writeln " World\t\x05"; // note: escapes work +  // Pointers: function the same as in C, btw. The usual. +  // Do note: the pointer star sticks with the TYPE, not the VARIABLE! +  string* p; +  assert(p == null); // default initializer +  p = &s; +  writeln "$(*p)"; +  // Math operators are (almost) standard. +  int x = 2 + 3 * 4 << 5; +  // Note: XOR is "xor". ^ is reserved for exponentiation (once I implement that). +  int y = 3 xor 5; +  int z = 5; +  assert(z++ == 5); +  assert(++z == 7); +  writeln "x $x y $y z $z"; +  // As in D, ~ concatenates. +  string hewo = "Hello " ~ "World"; +  // == tests for equality, "is" tests for identity. +  assert  (hewo == s); +  assert !(hewo is s); +  // same as +  assert  (hewo !is s); +   +  // Allocate arrays using "new array length" +  int[] integers = new int[] 10; +  assert(integers.length == 10); +  assert(integers[0] == 0); // zero is default initializer +  integers = integers ~ 5; // This allocates a new array! +  assert(integers.length == 11); +   +  // This is an appender array. +  // Instead of (length, pointer), it tracks (capacity, length, pointer). +  // When you append to it, it will use the free capacity if it can. +  // If it runs out of space, it reallocates - but it will free the old array automatically. +  // This makes it convenient for building arrays. +  int[auto~] appender; +  appender ~= 2; +  appender ~= 3; +  appender.free(); // same as {mem.free(appender.ptr); appender = null;} +   +  // Scope variables are automatically freed at the end of the current scope. +  scope int[auto~] someOtherAppender; +  // This is the same as: +  int[auto~] someOtherAppender2; +  onExit { someOtherAppender2.free; } +   +  // You can do a C for loop too +  // - but why would you want to? +  for (int i = 0; i < 5; ++i) { } +  // Otherwise, for and while are the same. +  while int i <- 0..4 { +    assert(i == 0); +    break; // continue works too +  } then assert(false); // if we hadn't break'd, this would run at the end +  // This is the height of loopdom - the produce-test-consume loop. +  do { +    int i = 5; +  } while (i == 5) { +    assert(i == 5); +    break; // otherwise we'd go back up to do { +  } +   +  // This is a nested function. +  // Nested functions can access the surrounding function. +  string returnS() { return s; } +  writeln returnS(); +   +  // Take the address of a function using & +  // The type of a global function is ReturnType function(ParameterTypeTuple). +  void function() foop = &foo; +   +  // Similarly, the type of a nested function is ReturnType delegate(ParameterTypeTuple). +  string delegate() returnSp = &returnS; +  writeln returnSp(); +  // Class member functions and struct member functions also fit into delegate variables. +  // In general, delegates are functions that carry an additional context pointer. +  // ("fat pointers" in C) +   +  // Allocate a "snapshot" with "new delegate". +  // Snapshots are not closures! I used to call them closures too, +  // but then my Haskell-using friends yelled at me so I had to stop. +  // The difference is that snapshots "capture" their surrounding context +  // when "new" is used. +  // This allows things like this +  int delegate(int) add(int a) { +    int add_a(int b) { return a + b; } +    // This does not work - the context of add_a becomes invalid +    // when add returns. +    // return &add_a; +    // Instead: +    return new &add_a; +  } +  int delegate(int) dg = add 2; +  assert (dg(3) == 5); +  // or +  assert (((add 2) 3) == 5); +  // or +  assert (add 2 3 == 5); +  // add can also be written as +  int delegate(int) add2(int a) { +    // this is an implicit, nameless nested function. +    return new λ(int b) { return a + b; } +  } +  // or even +  auto add3(int a) { return new λ(int b) -> a + b; } +  // hahahaaa +  auto add4 = λ(int a) -> new λ(int b) -> a + b; +  assert(add4 2 3 == 5); +  // If your keyboard doesn't have a λ (you poor sod) +  // you can use \ too. +  auto add5 = \(int a) -> new \(int b) -> a + b; +  // Note! +  auto nestfun = λ() { } // There is NO semicolon needed here! +  // "}" can always substitute for "};". +  // This provides syntactic consistency with built-in statements. +   +   +  // This is a class. +  // Note: almost all elements of Neat can be used on the module level +  //       or just as well inside a function. +  class C { +    int a; +    void writeA() { writeln "$a"; } +    // It's a nested class - it exists in the context of main(). +    // so if you leave main(), any instances of C become invalid. +    void writeS() { writeln "$s"; } +  } +  C cc = new C; +  // cc is a *reference* to C. Classes are always references. +  cc.a = 5; // Always used for property access. +  auto ccp = &cc; +  (*ccp).a = 6; +  // or just +  ccp.a = 7; +  cc.writeA(); +  cc.writeS(); // to prove I'm not making things up +  // Interfaces work same as in D, basically. Or Java. +  interface E { void doE(); } +  // Inheritance works same as in D, basically. Or Java. +  class D : C, E { +    override void writeA() { writeln "hahahahaha no"; } +    override void doE() { writeln "eeeee"; } +    // all classes inherit from Object. (toString is defined in Object) +    override string toString() { return "I am a D"; } +  } +  C cd = new D; +  // all methods are always virtual. +  cd.writeA(); +  E e = E:cd; // dynamic class cast! +  e.doE(); +  writeln "$e"; // all interfaces convert to Object implicitly. +   +  // Templates! +  // Templates are parameterized namespaces, taking a type as a parameter. +  template Templ(T) { +    alias hi = 5, hii = 8; +    // Templates always have to include something with the same name as the template +    // - this will become the template's _value_. +    // Static ifs are evaluated statically, at compile-time. +    // Because of this, the test has to be a constant expression, +    // or something that can be optimized to a constant. +    static if (types-equal (T, int)) { +      alias Templ = hi; +    } else { +      alias Templ = hii; +    } +  } +  assert(Templ!int == 5); +  assert(Templ!float == 8); +} +``` + +## Topics Not Covered + + * Extended iterator types and expressions + * Standard library + * Conditions (error handling) + * Macros | 
