doc/manual: put back the manual in the main repository
authorJean Privat <jean@pryen.org>
Wed, 10 Jul 2019 14:58:57 +0000 (10:58 -0400)
committerJean Privat <jean@pryen.org>
Fri, 12 Jul 2019 17:53:31 +0000 (13:53 -0400)
Currently it bit rot in the wiki :(

Signed-off-by: Jean Privat <jean@pryen.org>

16 files changed:
doc/manual/.gitignore [new file with mode: 0644]
doc/manual/Makefile [new file with mode: 0644]
doc/manual/attribute.md [new file with mode: 0644]
doc/manual/basic_type.md [new file with mode: 0644]
doc/manual/class.md [new file with mode: 0644]
doc/manual/constructor.md [new file with mode: 0644]
doc/manual/genericity.md [new file with mode: 0644]
doc/manual/makedoc.sh [new file with mode: 0755]
doc/manual/method.md [new file with mode: 0644]
doc/manual/module.md [new file with mode: 0644]
doc/manual/nitlanguage.sty [new file with mode: 0644]
doc/manual/nitreference.tex [new file with mode: 0644]
doc/manual/structure.md [new file with mode: 0644]
doc/manual/syntax.md [new file with mode: 0644]
doc/manual/variable.md [new file with mode: 0644]
doc/manual/virtual_type.md [new file with mode: 0644]

diff --git a/doc/manual/.gitignore b/doc/manual/.gitignore
new file mode 100644 (file)
index 0000000..07784df
--- /dev/null
@@ -0,0 +1,7 @@
+blank
+nitreference.aux
+nitreference.epub
+nitreference.log
+nitreference-main.md
+nitreference-main.tex
+nitreference.pdf
diff --git a/doc/manual/Makefile b/doc/manual/Makefile
new file mode 100644 (file)
index 0000000..8e54885
--- /dev/null
@@ -0,0 +1,2 @@
+nitreference.pdf: *.md
+       ./makedoc.sh
diff --git a/doc/manual/attribute.md b/doc/manual/attribute.md
new file mode 100644 (file)
index 0000000..e9741e9
--- /dev/null
@@ -0,0 +1,59 @@
+# Attributes
+
+`var`, used inside concrete and abstract classes, declares attributes. Attributes require a static type and can possibly have an initial value (it may be any kind of expression, even including
+`self`)
+
+~~~
+class Foo
+    var i: Int = 5
+    fun dec(x: Int)
+    do
+        var k = self.i
+        if k > x then self.i = k - x else self.i = 0
+    end
+end
+~~~
+
+Note that from an API point of view, there is no way to distinguish the read access of an attribute with a normal method neither to distinguish a write access of an attribute with a setter. Therefore, the read access of an attribute is called a getter while the write access is called a setter.
+
+~~~
+var x = foo.bar # Is bar an attribute or a method?
+foo.bar = y # Is bar an attribute or a setter?
+# In fact, we do not need to know.
+~~~
+
+## Visibility of Attributes
+
+By default, a getter is public and a setter is private. The visibility of getters can be precised with the `private` or `protected` keywords. The visibility of setters can be specified with an
+additional `writable` keyword.
+
+~~~
+class Foo
+    var pub_pri: X
+    protected var pro_pri: X
+    var pub_pub: X is writable
+    private var pri_pro: X is protected writable
+    var pub_pri2: X is private writable # the default
+end
+~~~
+
+## Redefinition of Attributes
+
+Getters and setters of attributes behave like genuine methods that can be inherited and redefined. Getters and setters can also redefine inherited methods. `redef var` declares that the getter is
+a redefinition while `redef writable` declares that the setter is a redefinition.
+
+~~~
+interface Foo
+    fun derp: Int is abstract
+    fun derp=(o: Int) is abstract
+end
+class Bar
+    super Foo
+    redef var derp: Int redef writable
+end
+class Baz
+    super Bar
+    redef fun derp do ...
+    redef fun derp=(o) do ...
+end
+~~~
diff --git a/doc/manual/basic_type.md b/doc/manual/basic_type.md
new file mode 100644 (file)
index 0000000..a94912f
--- /dev/null
@@ -0,0 +1,153 @@
+# Basic Types
+
+## Object
+
+Nit is a full object language. Every value is an instance of a
+class. Even the basic types described in this section.
+
+`Object` is the root of the class hierarchy. All other classes,
+including the basic ones, are a specialization of `Object`.
+
+Classes, methods and operators presented in this section are defined in
+the standard Nit library that is implicitly imported by every module.
+Many other classes and methods are also defined in the standard library.
+Please look at the specific standard library documentation for all
+details.
+
+## Int and Float
+
+`1`, `-1` are `Int` literals, and `1.0`, `-0.1` are `Float`
+literals. Standard arithmetic operators are available with a common
+precedence rules: `*`, `/`, and `%` (modulo) ; then `+` and `-`. Some
+operators can be composed with the assignment (`=`).
+
+~~~
+var i = 5
+i += 2
+print i # outputs 7
+~~~
+
+Conversion from `Int` to `Float` and `Float` to `Int` must be done with
+the `to_f` and `to_i` methods.
+
+## String
+
+Literal strings are enclosed within quotes (`"`).
+To insert a value
+inside a literal string, include the values inside braces (`{}`).
+Braces has to be escaped.
+`+` is the concatenation operator but is less efficient than the brace form.
+
+~~~
+var j = 5
+print "j={j}; j+1={j+1}" # outputs "j=5; j+1=6"
+~~~
+
+Common escaping sequences are available (`\"`, `\n`, `\t`, etc.) plus the escaped brace `\{`.
+
+~~~
+print "hel\"lo\nwo\{rld"
+# outputs `hel"lo` on a first line
+# and `wo{rld` on a second line
+~~~
+
+Multi-line strings are enclosed with triple quotes (`"""`).
+Values are inserted with a triple braces (`{{{value}}}`).
+The multi-line form thus allows verbatim new-lines, quotes and braces
+
+~~~
+print """some text
+with line breaks
+and characters like " and {
+but {{{ 1+2 }}} is rendered as 3
+"""
+~~~
+
+All objects have a `to_s` method that converts the object to a String.
+`print` is a top-level method that takes any number of arguments and
+prints to the standard output. `print` always add a newline, another
+top-level method, `printn`, does not add the newline.
+
+~~~
+var x: String
+x = 5.to_s # -> the String "5"
+print x # outputs "5"
+~~~
+
+## Bool
+
+`true` and `false` are the only two `Bool` values. Standard
+Boolean operators are available with the standard precedence rule:
+`not`; then `and`; then `or`.
+
+Common comparison operators are available: `==` and `!=` on all objects;
+`<`, `>`, `<=`, `>=` and `<=>` on `Comparable` objects (which include
+`Int`, `String` and others).
+
+- `==`, `<`, `>`, `<=`, `>=` and `<=>` are standard Nit operators (so they are redefinable).
+
+- `and`, `or` and `not` are not standard Nit operators: they are not
+  redefinable, also they are lazy and have adaptive typing flow
+  effects.
+
+- `==` is not for reference equality but for value equality (like
+  `equals` in Java). There is a special reference equality operator,
+  `is`, but it cannot be redefined and its usage is not recommended.
+  Note also that while `==` is redefinable, it has a special adaptive
+  typing flow effect when used with `null`.
+
+- `!=` is not a standard Nit operator. In fact `x != y` is
+  syntactically equivalent to `not x == y`.
+
+## Array
+
+`Array` is a generic class, thus `Array[Int]` denotes an array
+of integers and `Array[Array[Bool]]` denotes an array of array of
+Booleans. Literal arrays can be declared with the bracket notation
+(`[]`). Empty arrays can also be instantiated with the `new` keyword and
+elements added with the `add` method. Elements can be retrieved or
+stored with the bracket operator.
+
+~~~
+var a = [1, 2, 3, 4] # A literal array of integers
+print a.join(":") # outputs "1:2:3:4"
+var b = new Array[Int] # A new empty array of integers
+b.add(10)
+b.add_all(a)
+b.add(20)
+print b[0] # outputs "10"
+print b.length # outputs "6"
+b[1] = 30
+print b.join(", ") # outputs "10, 30, 2, 3, 4, 20"
+~~~
+
+Note that the type of literal arrays is deduced using the static type
+combination rule.
+
+## Range
+
+`Range` is also a generic class but accepts only `Discrete`
+types (`Int` is discrete). There are two kinds of literal ranges, the
+open one `[1..5[` that excludes the last element, and the closed one
+`[1..5]` that includes it.
+
+~~~
+print([1..5[.join(":")) # outputs "1:2:3:4"
+print([1..5].join(":")) # outputs "1:2:3:4:5"
+~~~
+
+Ranges are mainly used in `for` loops.
+
+## HashMap
+
+`HashMap` is a generic class that associates keys with values.
+There is no literal hashmap, therefore the `new` keyword is used to
+create an empty `HashMap` and the bracket operators are used to store
+and retrieve values.
+
+~~~
+var h = new HashMap[String, Int]
+# h associates strings to integers
+h["six"] = 6
+print h["six"] + 1 # outputs "7"
+~~~
diff --git a/doc/manual/class.md b/doc/manual/class.md
new file mode 100644 (file)
index 0000000..b778c43
--- /dev/null
@@ -0,0 +1,49 @@
+# Classes
+
+`interface`, `abstract class`, `class` and `enum` are the four kinds of classes. All these classes can be in multiple inheritance, can define new methods and redefine inherited method (yes, even interfaces).
+
+Here are the differences:
+
+-   interfaces can only specialize other interfaces, cannot have     attributes, cannot have constructors, cannot be instantiated.
+
+-   abstract classes cannot specialize enums, can have attributes, must have constructors, cannot be instantiated.
+
+-   concrete classes (i.e. `class`) cannot specialize enums, can have attributes, must have constructors, can be instantiated.
+
+-   enums (e.g. `Int` or `Bool`) can only specialize interfaces, cannot have attributes, cannot have constructors, have proper instances but they are not instantiated by the programmer—it means no `new Int`. Note that at this point there is no user-defined enums.
+
+All kinds of classes must have a name, can have some superclasses and can have some definitions of properties. Properties are methods, attributes, constructors and virtual types. All kinds of classes can also be generic. When we talk about “classes” in general, it means all these four kinds. We say “concrete classes” to designate only the classes declared with the `class` keyword alone.
+
+## Class Specialization
+
+`super` declares superclasses. Classes inherit methods, attributes and virtual-types defined in their superclasses. Currently, constructors are inherited in a specific manner.
+
+`Object` is the root of the class hierarchy. It is an interface and all other kinds of classes are implicitly a subclass of `Object`.
+
+There is no repeated inheritance nor private inheritance. The specialization between classes is transitive, therefore `super` declarations are superfluous (thus ignored).
+
+## Class Refinement
+
+`redef` allows modules to refine imported classes (even basic ones). Refining a class means:
+
+-   adding new properties: methods, attributes, constructors, virtual types;
+
+-   redefining existing properties: methods and constructors;
+
+-   adding new superclasses.
+
+Note that the kind or the visibility of a class cannot be changed by a refinement. Therefore, it is allowed to just write `redef class X` whatever is the kind or the visibility of `X`.
+
+In programs, the real instantiated classes are always the combination of all their refinements.
+
+~~~
+redef class Int
+    fun fib: Int
+    do
+        if self < 2 then return self
+        return (self-1).fib + (self-2).fib
+    end
+end
+# Now all integers have the fib method
+print 15.fib # outputs 610
+~~~
diff --git a/doc/manual/constructor.md b/doc/manual/constructor.md
new file mode 100644 (file)
index 0000000..39bfe53
--- /dev/null
@@ -0,0 +1,196 @@
+# Constructors
+
+Constructors in Nit behave differently.
+
+Their objective is double :
+
+* be compatible with full multiple-inheritance
+* be simple enough to be KISS and compatible with the principle of least surprise.
+
+
+## `new` construction and simple classes
+
+Classes in OO models are often a simple aggregates of attributes and methods.
+
+By default, the `new` construction require a value for each attribute defined in a class without a default value.
+
+~~~
+class Product
+       var id: String
+       var description: String
+       var price: Float
+end
+var p = new Product("ABC", "Bla bla", 15.95)
+assert p.id == "ABC"
+~~~
+
+In subclasses, additional attributes are automatically collected.
+
+~~~
+class Book
+       super Product
+       var author: String
+end
+
+var book = new Book("ABC", "Bla bla", 15.95, "John Doe")
+~~~
+
+
+## special `init` method
+
+The special init method is automatically invoked after the end of a `new` construction.
+It is used to perform additional systematic tasks.
+
+Because the `init` is run at the end of the initialization sequence, initialized attributes are usable in the body.
+
+~~~
+class OverpricedProduct
+       super Product
+       init
+       do
+               price = price * 10.0
+       end
+end
+var op = new OverpricedProduct("ABC", "Bla bla", 15.95)
+assert op.price == 159.50
+~~~
+
+
+## Uncollected attributes
+
+There is three cases for an attributes to not be collected in the `new`.
+
+* Attributes with a default value
+* Attributes with the annotation `noinit`
+* Attributes introduced in refinement of classes
+
+~~~
+class TaxedProduct
+       super Product
+       var tax_rate = 9.90
+       var total_price: Float is noinit
+       init
+       do
+               total_price = price * (1.0 + tax_rate/100.0)
+       end
+end
+var tp = new TaxedProduct("ABC", "Bla bla", 15.95)
+assert tp.total_price == 17.52905
+~~~
+
+Note: The orchestration here is important. In order, the following is executed:
+
+1. All defauts values are computed and set
+2. Setters are invoked.
+3. `init` is invoked.
+
+Therefore, `total_price` cannot be initialised with a default value, because at the time of the computation of the default values, the attribute `price` in not yet initialised.
+
+
+## Generalized initializers
+
+Initializers are methods that are automatically invoked by the new.
+In fact, by default, the setter of an attribute is used as a initializer.
+
+`autoinit` is used to register a method as a setter.
+
+~~~
+class FooProduct
+       super Product
+       fun set_xy(x, y: Int) is autoinit do z = x * 10 + y
+       var z: Int is noinit
+end
+var fp = new FooProduct("ABC", "Bla bla", 15.96, 1, 3)
+assert fp.z == 13
+~~~
+
+Generalized setters are a powerful tool but often needed in only rare specific cases.
+In most case, there is no reason that an argument of a `new` construction is not stored in the object as a real attribute.
+
+
+## Inheritance
+
+As explained above, one of the main advantage of these constructors is their compatibility with multiple inheritance.
+
+~~~
+class MultiProduct
+       super OverpricedProduct
+       super TaxedProduct
+       super FooProduct
+end
+var mp = new MultiProduct("ABC", "Bla bla", 15.96, 1, 3)
+assert mp.id == "ABC"
+assert mp.price == 159.6
+assert mp.total_price == 175.4
+assert mp.z == 13
+~~~
+
+
+## Named init
+
+Named `init` are less flexible trough inheritance, thus should no be used.
+They allow to have additional constructor for classes and more control in the construction mechanism.
+
+~~~
+class Point
+       var x: Float
+       var y: Float
+
+       init origin
+       do
+               init(0.0, 0.0)
+       end
+
+       init polar(r, phi: Float)
+       do
+               var x = r * phi.cos
+               var y = r * phi.sin
+               init(x, y)
+       end
+
+       redef fun to_s do return "({x},{y})"
+end
+var p1 = new Point(1.0, 2.0)
+assert p1.to_s ==  "(1,2)"
+var p2 = new Point.origin
+assert p2.to_s ==  "(0,0)"
+var p3 = new Point.polar(1.0, 2.0)
+assert p3.to_s ==  "(-0.4161,0.9092)"
+~~~
+
+
+## Legacy `init`
+
+nameless `init` defined with argument or with an explicit visibility are still accepted as a fallback of the old-constructors.
+They should not be used since they will be removed in a near future.
+
+
+## `new` factories
+
+`new` factories permit to completely shortcut the class instantiation mechanim.
+It could be used to provide `new` syntax on non-concrete class (mainly `extern class`).
+
+`new` factories behave like a top-level function that return the result of the construction.
+It is basically some kind of syntactic sugar.
+
+~~~
+abstract class Person
+       var age: Int
+       new(age: Int)
+       do
+               if age >= 18 then
+                       return new Adult(age)
+               else
+                       return new Child(age)
+               end
+       end
+end
+class Adult
+       super Person
+       # ...
+end
+class Child
+       super Person
+       # ...
+end
+~~~
diff --git a/doc/manual/genericity.md b/doc/manual/genericity.md
new file mode 100644 (file)
index 0000000..0b96f92
--- /dev/null
@@ -0,0 +1,27 @@
+# Generic Classes
+
+Generic classes are defined with formal generic parameters
+declared within brackets. Formal generic parameters can then be used as
+a regular type inside the class. Generic classes must always be
+qualified when used.
+
+~~~
+class Pair[E]
+    var first: E
+    var second: E
+    fun is_same: Bool
+    do
+        return self.first == self.second
+    end
+end
+var p1 = new Pair[Int](1, 2)
+print p1.second * 10 # outputs "20"
+print p1.is_same # outputs "false"
+var p2 = new Pair[String]("hello", "world")
+p2.first = "world"
+print p2.is_same # outputs "true"
+~~~
+
+Unlike many object-oriented languages, generic classes in Nit yield a
+kind of sub-typing. For example, `Pair[Int]` is a subtype of
+`Pair[Object]`.
diff --git a/doc/manual/makedoc.sh b/doc/manual/makedoc.sh
new file mode 100755 (executable)
index 0000000..10f6452
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/sh
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+echo > blank
+cat \
+       syntax.md blank\
+       basic_type.md blank\
+       structure.md blank\
+       variable.md blank\
+       module.md blank\
+       class.md blank\
+       method.md blank\
+       attribute.md blank\
+       constructor.md blank\
+       genericity.md blank\
+       virtual_type.md\
+       | sed -e '/\[\[!template/d' \
+       -e 's/\[\[\([^|]*\)|\([^]]*\)\]\]/\1 \\goto{\2}/g' \
+       -e 's/\[\[\([^]]*\)\]\]/\1 \\goto{\1}/g' \
+       > nitreference-main.md
+pandoc nitreference-main.md -f markdown -t latex --listings -o nitreference-main.tex
+pdflatex nitreference.tex
+pandoc nitreference-main.md -V title="Nit Reference" -f markdown -t epub -o nitreference.epub
diff --git a/doc/manual/method.md b/doc/manual/method.md
new file mode 100644 (file)
index 0000000..f0a67d6
--- /dev/null
@@ -0,0 +1,213 @@
+# Methods
+
+`fun` declares methods. Methods must have a name, may have parameters, and may have a return type. Parameters are typed; however, a single type can be used for multiple parameters.
+
+~~~
+fun foo(x, y: Int, s: String): Bool ...
+~~~
+
+`do` declares the body of methods. Alike control structures, a one-liner version is available.
+Therefore, the two following methods are equivalent.
+
+~~~
+fun next1(i: Int): Int
+do
+    return i + 1
+end
+
+fun next2(i: Int): Int do return i + 1
+~~~
+
+Inside the method body, parameters are considered as variables. They can be assigned and are subject to adaptive typing.
+
+`self`, the current receiver, is a special parameter. It is not assignable but is subject to adaptive typing.
+
+`return` exits the method and returns to the caller. In a function, the return value must be provided with a return in all control flow paths.
+
+## Method Call
+
+Calling a method is usually done with the dotted notation `x.foo(y, z)`. The dotted notation can be chained.
+
+A method call with no argument does not need parentheses. Moreover, even with arguments, the parentheses are not required in the principal method of a statement.
+
+~~~
+var a = [1]
+a.add 5 # no () for add
+print a.length # no () for length, no () for print
+~~~
+
+However, this last facility requires that the first argument does not start with a parenthesis or a bracket.
+
+~~~
+foo (x).bar # will be interpreted as (foo(x)).bar
+foo [x].bar # will be interpreted as (foo[x]).bar
+~~~
+
+## Method Redefinition
+
+`redef` denotes methods that are redefined in subclasses or in class refinements. The number and the types of the parameters must be invariant. Thus, there is no need to reprecise the types of the parameters, only names are mandatory.
+
+The return type can be redefined to be a more precise type. If same type is returned, there is no need to reprecise it.
+
+The visibility, also, cannot be changed, thus there is also no need to reprecise it.
+
+~~~
+class Foo
+    # implicitly an Object
+    # therefore inherit '==' and 'to_s'
+    var i: Int
+    redef fun to_s do return "Foo{self.i}"
+    redef fun ==(f) do return f isa Foo and f.i == self.i
+end
+~~~
+
+## Abstract Methods
+
+`is abstract` indicates methods defined without a body. Subclasses and refinements can then redefine it (the `redef` is still mandatory) with a proper body.
+
+~~~
+interface Foo
+    fun derp(x: Int): Int is abstract
+end
+class Bar
+    super Foo
+    redef fun derp(x) do return x + 1
+end
+~~~
+
+Concrete classes may have abstract methods. It is up to a refinement to provide a body.
+
+## Call to Super
+
+`super` calls the “previous” definition of the method. It is used in a redefinition of a method in a subclass or in a refinement, It can be used with or without arguments; in the latter case, the original arguments are implicitly used.
+
+The `super` of Nit behave more like the `call-next-method` of CLOS that the `super` of Java or Smalltalk. It permits the traversal of complex class hierarchies and refinement. Basically, `super` is polymorphic: the method called by `super` is not only determined by the class of
+definition of the method but also by the dynamic type of `self`.
+
+The principle it to produce a strict order of the redefinitions of a method (the linearization). Each call to `super` call the next method definition in the linearization. From a technical point of view, the linearization algorithm used is based on C3. It ensures that:
+
+-   A definition comes after its redefinition.
+
+-   A redefinition in a refinement comes before a redefnition in its superclass.
+
+-   The order of the declaration of the superclasses is used as the
+    ultimate disambiguation.
+
+<!-- -->
+
+~~~
+class A
+    fun derp: String do return "A"
+end
+class B
+    super A
+    redef fun derp do return "B" + super
+end
+class C
+    super A
+    redef fun derp do return "C" + super
+end
+class D
+    super B
+    super C
+    redef fun derp do return "D" + super
+    # Here the linearization order of the class D is DBCA
+    # D before B because D specializes B
+    # B before A because B specializes A
+    # D before C because D specializes C
+    # C before A because C specializes A
+    # B before C because in D 'super B' is before 'super C'
+end
+var b = new B
+print b.derp # outputs "BA"
+var d = new D
+print d.derp # outputs "DBCA"
+~~~
+
+## Operators and Setters
+
+Operators and setters are methods that require a special syntax for their definition and their invocation.
+
+-   binary operators: `+`, `-`, `*`, `/`, `\%`, `==`, `<`, `>`, `<=`,`>=`, `<<`, `>>` and `<=>`. Their definitions require exactly one     parameter and a return value. Their invocation is done with `x + y` where `x` is the receiver, `+` is the operator, and `y` is the argument.
+
+-   unary operator: `-`. Its definition requires a return value but no parameter. Its invocation is done with `-x` where `x` is the receiver.
+
+-   bracket operator: `[]`. Its definition requires one parameter or more and a return value. Its invocation is done with `x[y, z]` where `x` is the receiver, `y` the first argument and `z` the second argument.
+
+-   setters: `something=` where `something` can be any valid method identifier. Their definitions require one parameter or more and no return value. If there is only one parameter, the invocation is done with `x.something = y` where `x` is the receiver and y the argument. If there is more that one parameter, the invocation is done with `x.something(y, z) = t` where `x` is the receiver, `y` the first argument, `z` the second argument and `t` the last argument.
+
+-   bracket setter: `[]=`. Its definition requires two parameters or more and no return value. Its invocation is done with `x[y, z] = t` where `x` is the receiver, `y` the first argument, `z` the second argument and `t` the last argument.
+
+<!-- -->
+
+~~~
+class Foo
+    fun +(a: Bar): Baz do ...
+    fun -: Baz do ...
+    fun [](a: Bar): Baz do ...
+    fun derp(a: Bar): Baz do ...
+    fun derp=(a: Bar, b: Baz) do ...
+    fun []= (a: Bar, b: Baz) do ...
+end
+var a: Foo = ...
+var b: Bar = ...
+var c: Baz = ...
+c = a + b
+c = -b
+c = a[b] # The bracket operator '[]'
+c = a.derp(b) # A normal method 'derp'
+a.derp(b) = c # A setter 'derp='
+a[b] = c # The bracket setter '[]='
+~~~
+
+`+=` and `-=` are combinations of the assignment (`=`) and a binary operator. These feature are extended to setters where a single `+=` is in fact three method calls: a function call, the operator call, then a setter call.
+
+~~~
+a += c # equiv. a = a + c
+a[b] += c # equiv. a[b] = a[b] + c
+a.foo += c # equiv. a.foo = a.foo + c
+a.bar(b) += c # equiv. a.bar(b) = a.bar(b) + c
+~~~
+
+## Variable Number of Arguments
+
+A method can accept a variable number of arguments using ellipsis (`...`). The definition use `x: Foo...` where `x` is the name of the parameter and `Foo` a type. Inside the body, the static type of `x` is `Array[Foo]`. The caller can use 0, 1, or more arguments for the parameter `x`. Only one ellipsis is allowed in a signature.
+
+~~~
+fun foo(x: Int, y: Int..., z: Int)
+do
+    print "{x};{y.join(",")};{z}"
+end
+foo(1, 2, 3, 4, 5) # outputs "1;2,3,4;5"
+foo(1, 2, 3) # outputs "1;2;3"
+~~~
+
+## Top-level Methods and Main Body
+
+Some functions, like `print`, are usable everywhere simply without using a specific receiver. Such methods are just defined outside any classes. In fact, these methods are implicitly defined in the
+`Object` interface, therefore inherited by all classes, therefore usable everywhere. However, this principle may change in a future version.
+
+In a module, the main body is a bunch of statements at the end of a file. The main body of the main module is the program entry point. In fact, the main method of a program is implicitly defined as the redefinition of the method `main` of the `Sys` class; and the start of the program is the implicit statement `(Sys.new).main`. Note that because it is a redefinition, the main part can use `super` to call the “previous” main part in the imported modules. If there is no main part
+in a module, it is inherited from imported modules.
+
+Top-level methods coupled with the main body can be used to program in a pseudo-procedural way. Therefore, the following programs are valid:
+
+~~~
+print "Hello World!"
+~~~
+
+~~~
+fun sum(i, j: Int): Int
+do
+    return i + j
+end
+print sum(4, 5)
+~~~
+
+## Intern and Extern Methods
+
+`intern` and `extern` indicate concrete methods whose body is not written in Nit.
+
+The body of `intern` methods is provided by the compiler itself for performance or bootstrap reasons. For the same reasons, some intern methods, like `+` in `Int` are not redefinable.
+
+The body of `extern` methods is provided by libraries written in C; for instance, the system libraries required for input/output. Extern methods are always redefinable. See [[FFI]] for more information on `extern` methods.
diff --git a/doc/manual/module.md b/doc/manual/module.md
new file mode 100644 (file)
index 0000000..7aa5f19
--- /dev/null
@@ -0,0 +1,92 @@
+# Modules
+
+`module` declares the name of a module. While optional it is recommended to use it, at least for documentation purpose. The basename of the source file must match the name declared with `module`. The extension of the source file must be `nit`.
+
+A module is made of, in order:
+
+-   the module declaration;
+-   module importations;
+-   class definitions (and refinements) ;
+-   top-level function definitions (and redefinitions) ;
+-   main instructions .
+
+## Module Importation
+
+`import` declares dependencies between modules. By default (that is without any `import` declaration), a module publicly imports the module `standard`. Dependencies must not produce cycles. By importing a module, the importer module can see and use classes and properties defined in the imported module.
+
+-   `import` indicates a public importation. Importers of a given module will also import its publicly imported modules. An analogy is using `#include` in a header file (`.h`) in C/C++.
+
+-   `private import` indicates a private importation. Importers of a given module will not  automatically import its privately imported modules. An analogy is using `#include` in a body file (`.c`) in C/C++.
+
+-   `intrude import` indicates an intrusive importation. `intrude` `import` bypasses the `private` visibility and gives to the importer module a full access on the imported module. Such an import may only be considered when modules are strongly bounded and developed together. The closest, but insufficient, analogy is something like including a body file in a body file in C/C++.
+
+## Visibility
+
+By default, all classes, methods, constructors and virtual types are public which means freely usable by any importer module. Once something is public it belongs to the API of the module and should not be changed.
+
+`private` indicates classes and methods that do not belong to the API. They are still freely usable inside the module but are invisible in other modules (except those that use `intrude import`).
+
+`protected` indicates restricted methods and constructors. Such methods belong to the API of the module but they can only be used with the `self` receiver. Basically, `protected` methods are limited to the current class and its subclasses. Note that inside the module (and in
+intrude importers), there is still no restriction.
+
+Visibility of attributes is more specific and is detailed in its own section.
+
+~~~
+module m1
+class Foo
+    fun pub do ...
+    protected fun pro
+    do ...
+    private fun pri
+    do ...
+end
+private class Bar
+    fun pri2 do ...
+end
+var x: Foo = ...
+var y: Bar = ...
+# All OK, it is
+# inside the module
+x.foo
+x.pro
+x.pro
+y.pri2
+~~~
+
+<!-- -->
+
+~~~
+module m2
+import m1
+class Baz
+    super Foo
+    fun derp
+    do
+        self.pro # OK
+    end
+end
+var x: Foo = ...
+x.pub # OK
+x.pro # Compile error:
+      # pro is protected
+x.pri # Compile error:
+      # unknown method pri
+
+var y: Bar
+# Compile error:
+# unknown class Bar
+~~~
+
+## Visibility Coherence
+
+In order to guarantee the coherence in the visibility, the following rules apply:
+
+-   Classes and properties privately imported are considered private:     they are not exported and do not belong to the API of the importer.
+
+-   Properties defined in a private class are private.
+
+-   A static type is private if it contains a private class or a private     virtual type.
+
+-   Signatures of public and protected properties cannot contain a private static type.
+
+-   Bounds of public generic class and public virtual types cannot contain a private static type.
diff --git a/doc/manual/nitlanguage.sty b/doc/manual/nitlanguage.sty
new file mode 100644 (file)
index 0000000..f8d8b11
--- /dev/null
@@ -0,0 +1,45 @@
+% This file is part of Nit ( http://www.nitlanguage.org ).
+%
+% Copyright 2011 Jean Privat <jean@pryen.org>
+%
+% Licensed under the Apache License, Version 2.0 (the "License");
+% you may not use this file except in compliance with the License.
+% You may obtain a copy of the License at
+%
+%     http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+% See the License for the specific language governing permissions and
+% limitations under the License.
+
+\usepackage{lmodern} % because there is a bizarre 'pdfTeX error (font expansion): auto expansion is only possible with scalable fonts' unless
+\usepackage{listings} % because we extends it
+\usepackage{xcolor} % because we like colors
+
+% definition of the nit language
+\lstdefinelanguage{nit}{%
+keywords={import,class,interface,universal,super,fun,var,redef,protected,private,module,init,do,end,new,%
+               return,if,then,else,while,for,loop,in,isa,isset,break,continue,label,%
+               is,abstract,self,true,false,null,nullable,writable,assert,and,or,not,extern,intern},%
+morecomment=[l]{\#},%
+morestring=[b]",%
+}
+
+% disable spaces ij strings by default
+\lstset{showstringspaces=false}
+
+% easy nice environement for nit listings
+%\lstnewenvironment{lst}[1][]{%
+       \lstset{basicstyle=\scriptsize\ttfamily,%
+       keywordstyle=\bf\color{blue!30!black},%
+       commentstyle=\itshape\color{green!30!black},%
+       language=nit,%
+       backgroundcolor=\color{black!10},%
+       moredelim=[is][\color{yellow!30!black}]{@}{@},%
+tabsize=3}%,%
+%      #1}}{}
+
+% makes @ a nice shortcut for inline Nit code
+%\lstMakeShortInline[basicstyle=\small\ttfamily\color{blue!30!black}]{@}
diff --git a/doc/manual/nitreference.tex b/doc/manual/nitreference.tex
new file mode 100644 (file)
index 0000000..432dba9
--- /dev/null
@@ -0,0 +1,75 @@
+% This file is part of Nit ( http://www.nitlanguage.org ).
+%
+% Copyright 2011 Jean Privat <jean@pryen.org>
+%
+% Licensed under the Apache License, Version 2.0 (the "License");
+% you may not use this file except in compliance with the License.
+% You may obtain a copy of the License at
+%
+%     http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+% See the License for the specific language governing permissions and
+% limitations under the License.
+\documentclass[10pt]{article}
+
+\usepackage[T1]{fontenc}
+\usepackage{nitlanguage}
+\usepackage{multicol}
+\usepackage{savetrees}
+\usepackage{listings}
+\usepackage{microtype}
+\usepackage{xcolor}
+\usepackage{comment}
+%\usepackage{../nit_version}
+
+\newcommand\thedoctitle{A Concise Reference of the Nit Language}
+\title{\thedoctitle}
+\author{Jean Privat}
+\date{\today}
+
+\usepackage[bookmarks=false,pdftitle={\thedoctitle}]{hyperref}
+\pdfcompresslevel=9 %best compression level for text and image
+
+%\setcounter{collectmore}{90} % Force better column breaks
+
+\lstMakeShortInline[basicstyle=\small\ttfamily\color{blue!30!black}]{@}
+\lstset{language=nit}
+
+\hypersetup{colorlinks=true}
+\newcommand\goto[1]{\hyperref[#1]{{\color{red}\scriptsize[\ref*{#1}]}}}
+\newcommand\future[1]{}
+\newcommand\passthrough[1]{#1}
+\newcommand\tightlist{}
+
+\geometry{margin=0.35in} % short margins
+% footer
+\usepackage{fancyhdr}
+\pagestyle{fancy}
+\lhead{}
+\chead{}
+\rhead{}
+\lfoot{\small\it\today}
+\cfoot{\small\it\thedoctitle}
+\rfoot{\small\it\thepage}
+\renewcommand{\headrulewidth}{0pt}
+\renewcommand{\footrulewidth}{0pt}
+\setlength\footskip{15pt}
+
+\begin{document}
+\setlength\columnsep{8pt} % space around big columns
+\begin{multicols}{2}
+\setlength\columnsep{4pt} % space around smalls columns (for examples)
+
+\noindent\textbf{A Concise Reference of the Nit Language}
+
+This document attempts to be as short as possible while covering all features of the language in deepth.
+It is not a real manual to learn the language since concepts are covered when required.
+%Forward and backward references about concepts are written like this~\goto{redef} which means Section~\ref*{redef}.
+%An index\goto{index} also lists concepts and keywords for an improved navigation.
+
+\input{nitreference-main.tex}
+\end{multicols}
+\end{document}
diff --git a/doc/manual/structure.md b/doc/manual/structure.md
new file mode 100644 (file)
index 0000000..ba1107f
--- /dev/null
@@ -0,0 +1,163 @@
+# Control Structures
+
+Traditional procedural control structures exist in Nit. They
+also often exist in two versions: a one-liner and a block version.
+
+## Control Flow
+
+Control structures dictate the control flow of the
+program. Nit heavily refers to the control flow in its specification:
+
+-   No unreachable statement;
+
+-   No usage of undefined variables;
+
+-   No function without a `return` with a value;
+
+-   Adaptive typing.
+
+Some structures alter the control flow but are not described in this
+section: `and`, `or`, `not`, `or else` and `return`.
+
+Note that the control flow is determined only from the position, the
+order and the nesting of the control structures. The real value of the
+expressions used has no effect on the control flow analyses.
+
+~~~
+if true then
+    return
+else
+    return
+end
+print 1 # Compile error: unreachable statement
+
+if true then
+    return
+end
+print 1 # OK, but never executed
+~~~
+
+## if
+
+~~~
+if exp then stm
+if exp then stm else stm
+if exp then
+    stms
+end
+
+if exp then
+    stms
+else if exp then
+    stms
+else
+    stms
+end
+~~~
+
+Note that the following example is invalid since the first line is
+syntactically complete thus the newline terminate the whole `if`
+structure; then an error is signaled since a statement cannot begin with
+`else`.
+
+~~~
+if exp then stm # OK: complete 'if' structure
+else stm # Syntax error: unexpected 'else'
+~~~
+
+## while
+
+~~~
+while exp do stm
+while exp do
+    stms
+end
+~~~
+
+## for
+
+`for` declares an automatic variable used to iterates on `Collection` (`Array` and `Range` are both `Collection`).
+
+~~~
+for x in [1..5] do print x # outputs 1 2 3 4 5
+for x in [1, 4, 6] do
+    print x # outputs 1 4 6
+end
+~~~
+
+`for` can also be used with reversed ranges to iterate in reverse order.
+
+Step can also be used to specify the size of each increment at the end of a for cycle.
+
+~~~
+for x in [9 .. 4].step(-1) do print x # outputs 9 8 7 6 5 4
+for x in [9 .. 4[.step(-2) do print x # outputs 9 7 5
+~~~
+
+## loop
+
+Infinite loops are mainly used with breaks. They are useful to implement *until* loops or to simulate the *exit when* control of Ada.
+
+~~~
+loop
+    stms
+    if exp then break
+    stms
+end
+~~~
+
+Note that `loop` is different from `while true` because the control flow does not consider the values of expression.
+
+## do
+
+Single `do` are used to create scope for variables or to be attached with labeled breaks.
+
+~~~
+do
+    var x = 5
+    print x
+end
+# x is not defined here
+~~~
+
+## break, continue and label
+
+Unlabeled `break` exits the current `for`, `while`, `loop`, Unlabeled `continue` skips the current `for`, `while`, `loop`.
+
+`label` can be used with `break` or `continue` to act on a specific control structure (not necessary the current one). The corresponding `label` must be defined after the `end` keyword of the designated control structure.
+
+~~~
+for i in [0..width[ do
+    for j in [0..height[ do
+        if foo(i, j) then break label outer_loop
+        # The 'break' breaks the 'for i' loop
+    end
+end label outer_loop
+~~~
+
+`label` can also be used with `break` and single `do` structures.
+
+~~~
+do
+    stmts
+    if expr then break label block
+    stmts
+end label block
+~~~
+
+## abort
+
+`abort` stops the program with a fatal error and prints a stack trace. Since there is currently no exception nor run-time-errors, abort is somewhat used to simulate them.
+
+## assert
+
+`assert` verifies that a given Boolean expression is true, or else it aborts. An optional label can be precised, it will be displayed on the error message. An optional `else` can also be added and will be executed before the abort.
+
+~~~
+assert bla: whatever else
+    # "bla" is the label
+    # "whatever" is the expression to verify
+    print "Fatal error in module blablabla."
+    print "Please contact the customer service."
+end
+~~~
diff --git a/doc/manual/syntax.md b/doc/manual/syntax.md
new file mode 100644 (file)
index 0000000..1f3deaf
--- /dev/null
@@ -0,0 +1,86 @@
+# Basic Syntax of Nit
+
+The syntax of Nit follows the Pascal tradition and is
+inspired by various script languages (especially Ruby). Its main objective is
+readability.
+
+Indentation is not meaningful in Nit; blocks usually starts with a
+specific keyword and finish with `end`. Newlines are only meaningful at
+the end of declarations, at the end of statements, and after some
+specific keywords. The philosophy is that the newline is ignored if
+something (a statement, a declaration, or whatever) obviously needs more
+input; while the newline terminates lines that seems completed. See the
+complete Nit grammar for more details.
+
+~~~
+# a first complete statement that outputs "2"
+print 1 + 1
+# the second statement is not yet finished
+print 2 +
+# the end of the second statement, outputs "4"
+2
+~~~
+
+Nit aims to achieve some uniformity in its usage of the common
+punctuation: equal (`=`) is for assignment, double equal (`==`) is for
+equality test, column (`:`) is for type declaration, dot (`.`) is for
+polymorphism, comma (`,`) separates elements, and quad (`::`) is for
+explicit designation.
+
+## Identifiers
+
+Identifiers of modules, variables, methods, attributes and
+labels must begin with a lowercase letter and can be followed by
+letters, digits, or underscores. However, the usage of uppercase letters
+(and camelcase) is discouraged and the usage of underscore to separate
+words in identifiers is preferred: `some_identifier`.
+
+Identifiers of classes and types must begin with an uppercase letter and
+can be followed by letters, digits, or underscores. However
+the usage of camelcase is preferred for class identifiers while formal types should be written in all uppercase: `SomeClass` and `SOME_VIRTUAL_TYPE`.
+
+## Style
+
+While Nit does not enforce any kind of source code formatting, the
+following is encouraged:
+
+- indentation uses the tabulation character and is displayed
+  as 8 spaces;
+
+- lines are less than 80 characters long;
+
+- binary operators have spaces around them: `4 + 5`, `x = 5`;
+
+- columns (`:`) and commas (`,`) have a space after them but not
+  before: `var x: X`, `[1, 2, 3]`;
+
+- parenthesis and brackets do not need spaces around them;
+
+- superfluous parenthesis should be avoided;
+
+- the `do` of methods and the single `do` is on its own line and not
+  indented;
+
+- the other `do` are not on a newline.
+
+## Comments and Documentation
+
+As in many script languages, comments begin with a sharp (`#`)
+and run up to the end of the line. Currently, there is no
+multiline-comments.
+
+A comment block right before any definition of module, class, or
+property, is considered as its documentation and will be displayed as
+such by the autodoc. At this point, documentation is displayed verbatim
+(no special formatting or meta-information).
+
+~~~
+# doc. of foo
+module foo
+
+# doc. of Bar
+class Bar
+   # doc. of baz
+   fun baz do end
+end
+~~~
diff --git a/doc/manual/variable.md b/doc/manual/variable.md
new file mode 100644 (file)
index 0000000..e9b0d8a
--- /dev/null
@@ -0,0 +1,242 @@
+# Local Variables and Static Typing
+
+`var` declares local variables. In fact there is no global variable in Nit, so in this document *variable* always refers to a local variable. A variable is visible up to the end of the current
+control structure. Two variables with the same name cannot coexist: no nesting nor masking.
+
+Variables are bound to values. A variable cannot be used unless it has a value in all control flow paths (à la Java).
+
+~~~
+var x
+var y
+if whatever then
+    x = 5
+    y = 6
+else
+    x = 7
+end
+print x # OK
+print y # Compile error: y is possibly not initialized
+~~~
+
+## Adaptive Typing
+
+Nit features adaptive typing, which means that the static type of a variable can change according to: the assignments of variables, the control flow, and some special operators (`and`, `or`,
+`or else`, `==`, `!=`, and `isa`).
+
+~~~
+var x # a variable
+x = 5
+# static type is Int
+print x + 1 # outputs 6
+x = [6, 7]
+# static type is Array[Int]
+print x[0] # outputs "6"
+
+var x
+if whatever then
+    x = 5
+else
+    x = 6
+end
+# Static type is Int
+~~~
+
+## Variable Upper Bound
+
+An optional type information can be added to a variable declaration. This type is used as an upper bound of the type of the variable. When a initial value is given in a variable declaration without a specific type information, the static type of the initial value is used as an upper bound. If no type and no initial value are given, the upper bound is set to `nullable Object`.
+
+~~~
+var x: Int # Upper bound is Int
+x = "Hello" # Compile error: expected Int
+var y: Object # Upper bound is Object
+y = 5 # OK since Int specializes Object
+var z = 5 # Upper bound is Int
+z = "Hello" # Compile error: expected Int
+var t: Object = 5 # Upper bound is Object
+t = "Hello" # OK
+~~~
+
+The adaptive typing flow is straightforward, therefore loops (`for`, `while`, `loop`) have a special requirement: on entry, the upper bound is set to the current static type; on exit, the upper bound is reset to its previous value.
+
+~~~
+var x: Object = ...
+# static type is Object, upper bound is Object
+x = 5
+# static type is Int, bound remains Object
+while x > 0 do
+    # static type remains Int, bound sets to Int
+    x -= 1 # OK
+    x = "Hello" # Compile error: expected Int
+end
+# static type is Int, bound reset to Object
+x = "Hello" # OK
+~~~
+
+## Type Checks
+
+`isa` tests if an object is an instance of a given type. If the expression used in an `isa` is a variable, then its static type is automatically adapted, therefore avoiding the need of a specific cast.
+
+~~~
+var x: Object = whatever
+if x isa Int then
+    # static type of x is Int
+    print x * 10 # OK
+end
+~~~
+
+Remember that adaptive typing follows the control flow, including the Boolean operators.
+
+~~~
+var a: Array[Object] = ...
+for i in a do
+    # the static type of i is Object
+    if not i isa Int then continue
+    # now the static type of i is Int
+    print i * 10 # OK
+end
+~~~
+
+An interesting example:
+
+~~~
+var max = 0
+for i in whatever do
+    if i isa Int and i > max then max = i
+    # the > is valid since, in the right part
+    # of the "and", the static type of i is Int
+end
+~~~
+
+Note that type adaptation occurs only in an `isa` if the target type is more specific that the current type.
+
+~~~
+var a: Collection[Int] = ...
+if a isa Comparable then
+    # the static type is still Collection[Int]
+    # even if the dynamic type of a is a subclass
+    # of both Collection[Int] and Comparable
+    ...
+end
+~~~
+
+## Nullable Types
+
+`null` is a literal value that is only accepted by some specific static types. However, thanks to adaptive typing, the static type management can be mainly automatic.
+
+`nullable` annotates types that can accept `null` or an expression of a compatible nullable static type.
+
+~~~
+var x: nullable Int
+var y: Int
+x = 1 # OK
+y = 1 # OK
+x = null # OK
+y = null # Compile error
+x = y # OK
+y = x # Compile error
+~~~
+
+Adaptive typing works well with nullable types.
+
+~~~
+var x
+if whatever then
+    x = 5
+else
+    x = null
+end
+# The static type of x is nullable Int
+~~~
+
+Moreover, like the `isa` keyword, the `==` and `!=` operators can adapt the static type of a variable when compared to `null`.
+
+~~~
+var x: nullable Int = whatever
+if x != null then
+    # The static type of x is Int (without nullable)
+    print x + 6
+end
+# The static type of x is nullable Int
+~~~
+
+And another example:
+
+~~~
+var x: nullable Int = whatever
+loop
+    if x == null then continue
+    # The static type of x is Int
+end
+~~~
+
+`or else` can be used to compose a nullable expression with any other expression. The value of `x or else y` is `x` if `x` is not `null` and is `y` if `x` is null. The static type of `x or else y` is the combination of the type of `y` and the not null version of the type of `x`.
+
+~~~
+var i: nullable Int = ...
+var j = i or else 0
+# the static type of j is Int (without nullable)
+~~~
+
+Note that nullable types require a special management for [[attributes|attribute]] and [[constructors|constructor]].
+
+## Explicit Cast
+
+`as` casts an expression to a type. The expression is either casted successfully or there is an `abort`.
+
+~~~
+var x: Object = 5 # static type of x is Object
+print x.as(Int) * 10 # outputs 50
+print x.as(String) # aborts: cast failed
+~~~
+
+Note that `as` does not change the object nor does perform conversion.
+
+~~~
+var x: Object = 5 # static type of x is Object
+print x.as(Int) + 10 # outputs "15"
+print x.to_s + "10" # outputs "510"
+~~~
+
+Because of type adaptation, `as` is rarely used on variables. `isa` (sometime coupled with `assert`) is preferred.
+
+~~~
+var x: Object = 5 # static type of x is Object
+assert x isa Int
+# static type of x is now Int
+print x * 10 # outputs 50
+~~~
+
+`as(not null)` can be used to cast an expression typed by a nullable type to its non nullable version. This form keeps the programmer from writing explicit static types.
+
+~~~
+var x: nullable Int = 5 # static type of x is nullable Int
+print x.as(not null) * 10 # cast, outputs 50
+print x.as(Int) * 10 # same cast, outputs 50
+assert x != null # same cast, but type of x is now Int
+print x * 10 # outputs 50
+~~~
+
+## Static Type Combination Rule
+
+Adaptive typing, literal arrays, and `or else` need to determine a static type by combining other static types. This is done by using the following rule:
+
+-   The final type is `nullable` if at least one of the types is `nullable`.
+
+-   The final type is the static type that is more general than all the other types.
+
+-   If there is no such a type, and the thing typed is a variable, then the final type is the upper bound type of the variable; else there is a compilation error.
+
+<!-- -->
+
+~~~
+var d: Discrete = ...
+# Note: Int < Discrete < Object
+var x
+if whatever then x = 1 else x = d
+# static type is Discrete
+if whatever then x = 1 else x = "1"
+# static type is nullable Object (upper bound)
+var a1 = [1, d] # a1 is a Array[Discrete]
+var a2 = [1, "1"] # Compile error:
+        # incompatible types Int and String
+~~~
diff --git a/doc/manual/virtual_type.md b/doc/manual/virtual_type.md
new file mode 100644 (file)
index 0000000..042c721
--- /dev/null
@@ -0,0 +1,20 @@
+# Virtual Types
+
+`type` declares a virtual types in a class. A bound type is
+mandatory. Virtual types can then be used as regular types in the class
+and its subclasses. Subclasses can also redefine it with a more specific
+bound type. One can see a virtual type as an internal formal generic
+parameter or as a redefinable *typedef*.
+
+~~~
+class Foo
+    type E: Object
+    var derp: E
+end
+class Bar
+    super Foo
+    redef type E: Int
+end
+var b = new Bar(5)
+print b.derp + 1 # outputs 6
+~~~