summaryrefslogtreecommitdiffhomepage
path: root/neat.html.markdown
diff options
context:
space:
mode:
authorAdam Bard <github@adambard.com>2013-09-08 21:43:56 -0700
committerAdam Bard <github@adambard.com>2013-09-08 21:43:56 -0700
commitf32e9670d3b05b65c2a419b6c192ddf1a72e2131 (patch)
tree25366356e4eca7b31c902e726fe7ed65768c52dc /neat.html.markdown
parent3e0ec767cd2bd5f022bcf4eaeb86803c354c8237 (diff)
parentf5f3f2b3e5a6e3579d8f2217c96b5cd0d96298ee (diff)
Merge pull request #329 from FeepingCreature/master
[neat/en] Document Neat language
Diffstat (limited to 'neat.html.markdown')
-rw-r--r--neat.html.markdown299
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