diff --git a/content/content/oop_macro.md b/content/content/oop_macro.md
deleted file mode 100644
index 0b13042..0000000
--- a/content/content/oop_macro.md
+++ /dev/null
@@ -1,274 +0,0 @@
----
-title: OOP Macro
----
-
-
-# OOP Macro
-This is the code that we currently must write to use OOP in Nim:
-
-```nimrod
-type Animal = ref object of RootObj
- name: string
- age: int
-method vocalize(this: Animal): string = "..."
-method ageHumanYrs(this: Animal): int = this.age
-
-type Dog = ref object of Animal
-method vocalize(this: Dog): string = "woof"
-method ageHumanYrs(this: Dog): int = this.age * 7
-
-type Cat = ref object of Animal
-method vocalize(this: Cat): string = "meow"
-```
-
-All these typedefs and `this: T` parameters are repetitive, so it'd be good to write a macro to mask them. Something like this would be best:
-
-```nimrod
-class Animal of RootObj:
- var name: string
- var age: int
- method vocalize: string = "..."
- method age_human_yrs: int = this.age # `this` is injected
-
-class Dog of Animal:
- method vocalize: string = "woof"
- method age_human_yrs: int = this.age * 7
-
-class Cat of Animal:
- method vocalize: string = "meow"
-```
-
-To get that nice notation, we can use a macro:
-
-```nimrod
-import macros
-
-macro class*(head, body: untyped): untyped =
- # The macro is immediate, since all its parameters are untyped.
- # This means, it doesn't resolve identifiers passed to it.
-
- var typeName, baseName: NimNode
-
- # flag if object should be exported
- var exported: bool
-
- if head.kind == nnkInfix and head[0].ident == !"of":
- # `head` is expression `typeName of baseClass`
- # echo head.treeRepr
- # --------------------
- # Infix
- # Ident !"of"
- # Ident !"Animal"
- # Ident !"RootObj"
- typeName = head[1]
- baseName = head[2]
-
- elif head.kind == nnkInfix and head[0].ident == !"*" and
- head[2].kind == nnkPrefix and head[2][0].ident == !"of":
- # `head` is expression `typeName* of baseClass`
- # echo head.treeRepr
- # --------------------
- # Infix
- # Ident !"*"
- # Ident !"Animal"
- # Prefix
- # Ident !"of"
- # Ident !"RootObj"
- typeName = head[1]
- baseName = head[2][1]
- exported = true
-
- else:
- quit "Invalid node: " & head.lispRepr
-
- # The following prints out the AST structure:
- #
- # import macros
- # dumptree:
- # type X = ref object of Y
- # z: int
- # --------------------
- # StmtList
- # TypeSection
- # TypeDef
- # Ident !"X"
- # Empty
- # RefTy
- # ObjectTy
- # Empty
- # OfInherit
- # Ident !"Y"
- # RecList
- # IdentDefs
- # Ident !"z"
- # Ident !"int"
- # Empty
-
- # create a type section in the result
- result =
- if exported:
- # mark `typeName` with an asterisk
- quote do:
- type `typeName`* = ref object of `baseName`
- else:
- quote do:
- type `typeName` = ref object of `baseName`
-
- # echo treeRepr(body)
- # --------------------
- # StmtList
- # VarSection
- # IdentDefs
- # Ident !"name"
- # Ident !"string"
- # Empty
- # IdentDefs
- # Ident !"age"
- # Ident !"int"
- # Empty
- # MethodDef
- # Ident !"vocalize"
- # Empty
- # Empty
- # FormalParams
- # Ident !"string"
- # Empty
- # Empty
- # StmtList
- # StrLit ...
- # MethodDef
- # Ident !"age_human_yrs"
- # Empty
- # Empty
- # FormalParams
- # Ident !"int"
- # Empty
- # Empty
- # StmtList
- # DotExpr
- # Ident !"this"
- # Ident !"age"
-
- # var declarations will be turned into object fields
- var recList = newNimNode(nnkRecList)
-
- # expected name of constructor
- let ctorName = newIdentNode("new" & $typeName)
-
- # Iterate over the statements, adding `this: T`
- # to the parameters of functions, unless the
- # function is a constructor
- for node in body.children:
- case node.kind:
-
- of nnkMethodDef, nnkProcDef:
- # check if it is the ctor proc
- if node.name.kind != nnkAccQuoted and node.name.basename == ctorName:
- # specify the return type of the ctor proc
- node.params[0] = typeName
- else:
- # inject `self: T` into the arguments
- node.params.insert(1, newIdentDefs(ident("self"), typeName))
- result.add(node)
-
- of nnkVarSection:
- # variables get turned into fields of the type.
- for n in node.children:
- recList.add(n)
-
- else:
- result.add(node)
-
- # Inspect the tree structure:
- #
- # echo result.treeRepr
- # --------------------
- # StmtList
- # TypeSection
- # TypeDef
- # Ident !"Animal"
- # Empty
- # RefTy
- # ObjectTy
- # Empty
- # OfInherit
- # Ident !"RootObj"
- # Empty <= We want to replace this
- # MethodDef
- # ...
-
- result[0][0][2][0][2] = recList
-
- # Lets inspect the human-readable version of the output
- # echo repr(result)
- # Output:
- # type
- # Animal = ref object of RootObj
- # name: string
- # age: int
- #
- # method vocalize(this: Animal): string {.base.} =
- # "..."
- #
- # method age_human_yrs(this: Animal): int {.base.} =
- # this.age
- # ...
- #
- # type
- # Rabbit = ref object of Animal
- #
- # proc newRabbit(name: string; age: int): Rabbit =
- # result = Rabbit(name: name, age: age)
- #
- # method vocalize(this: Rabbit): string =
- # "meep"
-
-# ---
-
-class Animal of RootObj:
- var name: string
- var age: int
- method vocalize: string {.base.} = "..." # use `base` pragma to annonate base methods
- method age_human_yrs: int {.base.} = this.age # `this` is injected
- proc `$`: string = "animal:" & this.name & ":" & $this.age
-
-class Dog of Animal:
- method vocalize: string = "woof"
- method age_human_yrs: int = this.age * 7
- proc `$`: string = "dog:" & this.name & ":" & $this.age
-
-class Cat of Animal:
- method vocalize: string = "meow"
- proc `$`: string = "cat:" & this.name & ":" & $this.age
-
-class Rabbit of Animal:
- proc newRabbit(name: string, age: int) = # the constructor doesn't need a return type
- result = Rabbit(name: name, age: age)
- method vocalize: string = "meep"
- proc `$`: string = "rabbit:" & this.name & ":" & $this.age
-
-# ---
-
-var animals: seq[Animal] = @[]
-animals.add(Dog(name: "Sparky", age: 10))
-animals.add(Cat(name: "Mitten", age: 10))
-
-for a in animals:
- echo a.vocalize()
- echo a.age_human_yrs()
-
-let r = newRabbit("Fluffy", 3)
-echo r.vocalize()
-echo r.age_human_yrs()
-echo r
-```
-``` console
-$ nim c -r oopmacro.nim
-woof
-70
-meow
-10
-meep
-3
-rabbit:Fluffy:3
-```
diff --git a/content/content/exceptions.md b/content/exceptions.md
similarity index 100%
rename from content/content/exceptions.md
rename to content/exceptions.md
diff --git a/content/fonts/fontelloe.eot b/content/fonts/fontelloe.eot
new file mode 100644
index 0000000..cffe901
Binary files /dev/null and b/content/fonts/fontelloe.eot differ
diff --git a/content/fonts/fontellos.svg b/content/fonts/fontellos.svg
new file mode 100644
index 0000000..5a187a3
--- /dev/null
+++ b/content/fonts/fontellos.svg
@@ -0,0 +1,14 @@
+
+
+
\ No newline at end of file
diff --git a/content/fonts/fontellot.ttf b/content/fonts/fontellot.ttf
new file mode 100644
index 0000000..6f31fe8
Binary files /dev/null and b/content/fonts/fontellot.ttf differ
diff --git a/content/fonts/fontellow.woff b/content/fonts/fontellow.woff
new file mode 100644
index 0000000..5be5972
Binary files /dev/null and b/content/fonts/fontellow.woff differ
diff --git a/content/content/for_iterators.md b/content/for_iterators.md
similarity index 100%
rename from content/content/for_iterators.md
rename to content/for_iterators.md
diff --git a/content/content/getting_started.md b/content/getting_started.md
similarity index 79%
rename from content/content/getting_started.md
rename to content/getting_started.md
index 513f454..867064a 100644
--- a/content/content/getting_started.md
+++ b/content/getting_started.md
@@ -7,7 +7,7 @@ When installing Nim, you have two options: downloading a copy directly from git,
## Downloading a Nim Distribution
To get started with Nim, head over to the [downloads page](http://nim-lang.org/download.html) and download the version you'd like.
-The Windows distribution comes with the MinGW compiler, which is recommended, but if you'd like to use your own compiler, download the version without MinGW. If you get an error like `Error: unhandled exception: The system cannot find the file specified.`, then make sure that the C compiler is on your path.
+The Windows distribution comes with the MinGW compiler, which is recommended, but if you'd like to use your own compiler, download the version without MinGW.
On Mac and Linux, it is recommended to use either GCC or Clang.
@@ -17,9 +17,9 @@ Once you have downloaded the appropriate distribution and extracted the files so
To install Nim from git, ensure that you have gcc installed on Windows, Linux, and BSDs and clang on Mac. Afterwards, run the following series of commands to download and bootstrap Nim:
```console
-$ git clone -b master git://github.com/Araq/Nim.git
-$ cd Nim
-$ git clone --depth 1 git://github.com/nim-lang/csources
+$ git clone -b master git://github.com/Araq/Nimrod.git
+$ cd Nimrod
+$ git clone --depth 1 git://github.com/nimrod-code/csources
$ cd csources
$ sh build.sh # Replace with build.bat on windows
$ cd ..
diff --git a/content/content/hello_world.md b/content/hello_world.md
similarity index 100%
rename from content/content/hello_world.md
rename to content/hello_world.md
diff --git a/content/content/if_else_while.md b/content/if_else_while.md
similarity index 97%
rename from content/content/if_else_while.md
rename to content/if_else_while.md
index 93b01c7..026d43a 100644
--- a/content/content/if_else_while.md
+++ b/content/if_else_while.md
@@ -11,7 +11,7 @@ When inside a loop, `continue` can be used to skip the rest of the loop body and
Along with [its other uses](/block/), the `block` statement can be used to create a label so that it's possible to break out of nested loops.
``` nim
-import strutils, random
+import strutils, math
randomize()
let answer = random(10) + 1
diff --git a/content/images/triangle.png b/content/images/triangle.png
new file mode 100644
index 0000000..985a136
Binary files /dev/null and b/content/images/triangle.png differ
diff --git a/content/content/index.md b/content/index.md
similarity index 100%
rename from content/content/index.md
rename to content/index.md
diff --git a/content/content/oop.md b/content/oop.md
similarity index 76%
rename from content/content/oop.md
rename to content/oop.md
index 9edbdd7..4befd90 100644
--- a/content/content/oop.md
+++ b/content/oop.md
@@ -4,7 +4,7 @@ title: Object Oriented Programming
# Object Oriented Programming
-Object oriented programming is supported through inheritance and methods, which are virtual procedures. Methods work in the same way as [procs](/procs/), including UFCS, but the runtime type of the object that a method is called with is used to determine which version to call.
+Object oriented programming is supported through inheritance and methods, which are virtual procedures. Methods work in the same was as [procs](/procs/), including UFCS, but the runtime type of the object that a method is called with is used to determine which version to call.
Inheritance is created with the `of` keyword in the type declaration of an object. A method is overridden by creating a new method with parameter types of the subtype.
@@ -38,19 +38,3 @@ woof
meow
10
```
-
-## Testing subtypes
-
-It is also possible to check if an object is of a given subtype with the `of` keyword. For example,
-
-``` nimrod
-echo(animals[0] of Dog)
-echo(animals[0] of Cat)
-echo(animals[0] of Animal)
-```
-``` console
-$ nim c -r of_op.nim
-true
-false
-true
-```
diff --git a/content/oop_macro.md b/content/oop_macro.md
new file mode 100644
index 0000000..03d1e6a
--- /dev/null
+++ b/content/oop_macro.md
@@ -0,0 +1,343 @@
+---
+title: OOP Macro
+---
+
+
+# OOP Macro
+This is the code that we currently must write to use OOP in Nim:
+
+```nimrod
+type Animal = ref object of RootObj
+ name: string
+ age: int
+method vocalize(this: Animal): string = "..."
+method vocalizeAnimal(this: Animal): string = "..."
+method ageHumanYrs(this: Animal): int = this.age
+
+type Dog = ref object of Animal
+method vocalize(this: Dog): string = "woof"
+method ageHumanYrs(this: Dog): int = this.age * 7
+
+type Cat = ref object of Animal
+method vocalize(this: Cat): string = this.vocalize_animal() & "meow"
+method vocalizeCat(this: Cat): string = this.vocalize_animal() & "meow"
+
+type Tiger = ref object of Cat
+method vocalize(this: Tiger): string = this.vocalize_animal() & "Rawr!"
+```
+
+All these typedefs, `this: T` parameters, and extra methods are repetitive, so it'd be good to write a macro to mask them. Something like this would be best:
+
+```nimrod
+class Animal of RootObj:
+ var name: string
+ var age: int
+ method vocalize: string = "..."
+ method age_human_yrs: int = this.age # `this` is injected
+
+class Dog of Animal:
+ method vocalize: string = "woof"
+ method age_human_yrs: int = this.age * 7
+
+class Cat of Animal:
+ method vocalize: string =
+ # call the base class method
+ this.vocalize_animal() & "meow"
+
+class Tiger of Cat:
+ method vocalize: string =
+ # no need for super.super!
+ this.vocalize_animal() & "Rawr!"
+```
+
+To get that nice notation, we can use a macro. Note that this looks pretty complicated, and it is, but it will give us almost full OOP capabilities like other languages such as Java and Python. Here's the macro in all it's glory:
+
+```nimrod
+import macros
+
+macro class*(head: expr, body: stmt): stmt {.immediate.} =
+ # The macro is immediate so that it doesn't
+ # resolve identifiers passed to it
+
+ # object reference name inside methods.
+ # ie: self, this
+ let obj_reference = "this"
+
+ var typeName, baseName: PNimrodNode
+
+ if head.kind == nnkIdent:
+ # `head` is expression `typeName`
+ # echo head.treeRepr
+ # --------------------
+ # Ident !"Animal"
+ typeName = head
+
+ elif head.kind == nnkInfix and $head[0] == "of":
+ # `head` is expression `typeName of baseClass`
+ # echo head.treeRepr
+ # --------------------
+ # Infix
+ # Ident !"of"
+ # Ident !"Animal"
+ # Ident !"TObject"
+ typeName = head[1]
+ baseName = head[2]
+
+ else:
+ quit "Invalid node: " & head.lispRepr
+
+ # echo treeRepr(body)
+ # --------------------
+ # StmtList
+ # VarSection
+ # IdentDefs
+ # Ident !"name"
+ # Ident !"string"
+ # Empty
+ # IdentDefs
+ # Ident !"age"
+ # Ident !"int"
+ # Empty
+ # MethodDef
+ # Ident !"vocalize"
+ # Empty
+ # Empty
+ # FormalParams
+ # Ident !"string"
+ # Empty
+ # Empty
+ # StmtList
+ # StrLit ...
+ # MethodDef
+ # Ident !"age_human_yrs"
+ # Empty
+ # Empty
+ # FormalParams
+ # Ident !"int"
+ # Empty
+ # Empty
+ # StmtList
+ # DotExpr
+ # Ident !"this"
+ # Ident !"age"
+
+ # create a new stmtList for the result
+ result = newStmtList()
+
+ # var declarations will be turned into object fields
+ var recList = newNimNode(nnkRecList)
+
+ # Make forward declarations so that function order
+ # does not matter, just like in real OOP!
+ for node in body.children:
+ case node.kind:
+ of nnkMethodDef, nnkProcDef:
+ # inject `this: T` into the arguments
+ let n = copyNimTree(node)
+ n.params.insert(1, newIdentDefs(ident(obj_reference), typeName))
+ # clear the body so we only get a
+ # declaration
+ n.body = newEmptyNode()
+ result.add(n)
+
+ # forward declare the inheritable method
+ let n2 = copyNimTree(n)
+ let proc_name = $(n2.name.toStrLit())
+ let type_name = $(typeName.toStrLit())
+ let new_name = ident(proc_name & type_name)
+ n2.name = new_name
+ result.add(n2)
+ else:
+ discard
+
+ # Iterate over the statements, adding `this: T`
+ # to the parameters of functions
+ for node in body.children:
+ case node.kind:
+ of nnkMethodDef, nnkProcDef:
+ # inject `this: T` into the arguments
+ let n = copyNimTree(node)
+ n.params.insert(1, newIdentDefs(ident(obj_reference), typeName))
+
+ # Copy the proc or method for inheritance
+ # ie: procName_ClassName()
+ let n2 = copyNimTree(node)
+ n2.params.insert(1, newIdentDefs(ident(obj_reference), typeName))
+ let proc_name = $(n2.name.toStrLit())
+ let type_name = $(typeName.toStrLit())
+ let new_name = ident(proc_name & type_name)
+ n2.name = new_name
+ result.add(n2)
+
+ # simply call the class method from here
+ # proc procName=
+ # procName_ClassName()
+ var p: seq[PNimrodNode] = @[]
+ for i in 1..n.params.len-1:
+ p.add(n.params[i][0])
+ n.body = newStmtList(newCall(proc_name & type_name, p))
+
+ result.add(n)
+
+ of nnkVarSection:
+ # variables get turned into fields of the type.
+ for n in node.children:
+ recList.add(n)
+ else:
+ result.add(node)
+
+ # The following prints out the AST structure:
+ #
+ # import macros
+ # dumptree:
+ # type X = ref object of Y
+ # z: int
+ # --------------------
+ # TypeSection
+ # TypeDef
+ # Ident !"X"
+ # Empty
+ # RefTy
+ # ObjectTy
+ # Empty
+ # OfInherit
+ # Ident !"Y"
+ # RecList
+ # IdentDefs
+ # Ident !"z"
+ # Ident !"int"
+ # Empty
+
+ var type_decl: PNimrodNode
+ if baseName == nil:
+ type_decl = quote do:
+ type `typeName` = ref object of RootObj
+ else:
+ type_decl = quote do:
+ type `typeName` = ref object of `baseName`
+
+ # Inspect the tree structure:
+ #
+ # echo type_decl.treeRepr
+ # --------------------
+ # StmtList
+ # TypeSection
+ # TypeDef
+ # Ident !"Animal"
+ # Empty
+ # RefTy
+ # ObjectTy
+ # Empty
+ # OfInherit
+ # Ident !"TObject"
+ # Empty <= We want to replace this
+ type_decl[0][0][2][0][2] = recList
+ result.insert(0, type_decl)
+
+ # Lets inspect the human-readable version of the output
+ # echo repr(result)
+ # Output:
+ # type
+ # Animal = ref object of RootObj
+ # name: string
+ # age: int
+ #
+ # method vocalize(this: Animal): string
+ # method vocalizeAnimal(this: Animal): string <= this is the magic for calling base class methods
+ # method age_human_yrs(this: Animal): int
+ # method age_human_yrsAnimal(this: Animal): int <= this is the magic for calling base class methods
+ # method vocalize(this: Animal): string =
+ # "..."
+ #
+ # method vocalizeAnimal(this: Animal): string =
+ # "..."
+ #
+ # method age_human_yrs(this: Animal): int =
+ # this.age
+ #
+ # method age_human_yrsAnimal(this: Animal): int =
+ # this.age
+ #
+ #
+ # type
+ # Dog = ref object of Animal
+ #
+ # method vocalize(this: Dog): string
+ # method vocalizeDog(this: Dog): string
+ # method age_human_yrs(this: Dog): int
+ # method age_human_yrsDog(this: Dog): int
+ # method vocalize(this: Dog): string =
+ # "woof"
+ #
+ # method vocalizeDog(this: Dog): string =
+ # "woof"
+ #
+ # method age_human_yrs(this: Dog): int =
+ # this.age * 7
+ #
+ # method age_human_yrsDog(this: Dog): int =
+ # this.age * 7
+ #
+ #
+ # type
+ # Cat = ref object of Animal
+ #
+ # method vocalize(this: Cat): string
+ # method vocalizeCat(this: Cat): string
+ # method vocalize(this: Cat): string =
+ # this.vocalize_animal() & "meow"
+ #
+ # method vocalizeCat(this: Cat): string =
+ # this.vocalize_animal() & "meow"
+ #
+ #
+ # type
+ # Tiger = ref object of Cat
+ #
+ # method vocalize(this: Tiger): string
+ # method vocalizeTiger(this: Tiger): string
+ # method vocalize(this: Tiger): string =
+ # this.vocalize_animal() & "Rawr!"
+ #
+ # method vocalizeTiger(this: Tiger): string =
+ # this.vocalize_animal() & "Rawr!"
+
+
+class Animal of RootObj:
+ var name: string
+ var age: int
+ method vocalize: string = "..."
+ method age_human_yrs: int = this.age # `this` is injected
+
+class Dog of Animal:
+ method vocalize: string = "woof"
+ method age_human_yrs: int = this.age * 7
+
+class Cat of Animal:
+ method vocalize: string =
+ # call the base class method
+ this.vocalize_animal() & "meow"
+
+class Tiger of Cat:
+ method vocalize: string =
+ # no need for super.super!
+ this.vocalize_animal() & "Rawr!"
+
+var animals: seq[Animal] = @[]
+animals.add(Dog(name: "Sparky", age: 10))
+animals.add(Cat(name: "Mitten", age: 10))
+animals.add(Tiger(name: "Jean", age: 2))
+
+for a in animals:
+ echo a.name, " says ", a.vocalize()
+ echo a.age_human_yrs()
+```
+``` console
+$ nim c -r oopmacro.nim
+Sparky says woof
+70
+Mitten says ...meow
+10
+Jean says ...Rawr!
+2
+```
diff --git a/content/opengl/triangle.md b/content/opengl/triangle.md
new file mode 100644
index 0000000..5da0d17
--- /dev/null
+++ b/content/opengl/triangle.md
@@ -0,0 +1,132 @@
+---
+title: OpenGL - Triangle
+---
+# OpenGL: Triangle
+
+The following code depends on the ``opengl`` and ``nim-glfw`` packages which
+can be installed via babel by executing ``babel install opengl@#head nim-glfw@#head``.
+You will need the GLFW DLL in order to run this on Windows.
+
+
+
+One thing to keep in mind when writing OpenGL code in Nim is that ``float``
+is actually ``float64``. But vertices must be ``float32`` so you must explicitly
+specify that by casting or using ``'f32`` as is done in the example.
+
+```nimrod
+import os, glfw/glfw, opengl, times, math
+
+proc assertShader(shader: GLuint) =
+ var status: GLint
+ glGetShaderiv(shader, GL_COMPILE_STATUS, addr status)
+ if status != GL_TRUE:
+ var buff: array[512, char]
+ glGetShaderInfoLog(shader, 512, nil, buff)
+ echo(buff)
+ assert false
+
+const
+ vertexSource = """
+#version 150
+
+in vec2 position;
+in vec3 color;
+
+out vec3 Color;
+
+void main()
+{
+ Color = color;
+ gl_Position = vec4(position, 0.0, 1.0);
+}
+"""
+ fragmentSource = """
+#version 150
+
+in vec3 Color;
+
+out vec4 outColor;
+
+void main()
+{
+ outColor = vec4(Color, 1.0);
+}
+"""
+
+
+proc setup(shaderProgram: var TGLUint) =
+ var vertices = [
+ 0.0'f32, 0.5, 1, 0, 0,
+ 0.5, -0.5, 0, 1, 0,
+ -0.5, -0.5, 0, 0, 1
+ ]
+ echo(vertices.repr)
+ var vertexBuffer: GLuint
+ glGenBuffers(1, addr vertexBuffer)
+ echo("Verter Buff: ", vertexBuffer)
+
+ var vertexArray: GLuint
+ glGenVertexArrays(1, addr vertexArray)
+ glBindVertexArray(vertexArray)
+
+
+ glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer)
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices).int32, addr vertices,
+ GL_STATIC_DRAW)
+
+ var vertexShader = glCreateShader(GL_VERTEX_SHADER)
+ var vertexSrcArray = [vertexSource.cstring]
+ glShaderSource(vertexShader, 1, cast[cstringArray](addr vertexSrcArray), nil)
+ glCompileShader(vertexShader)
+ assertShader(vertexShader)
+
+ var fragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
+ var fragmentSrcArray = [fragmentSource.cstring]
+ glShaderSource(fragmentShader, 1, cast[cstringArray](addr fragmentSrcArray),
+ nil)
+ glCompileShader(fragmentShader)
+ assertShader(fragmentShader)
+
+ shaderProgram = glCreateProgram()
+ glAttachShader(shaderProgram, vertexShader)
+ glAttachShader(shaderProgram, fragmentShader)
+
+ # Apparently this is not necessary according to http://open.gl
+ glBindFragDataLocation(shaderProgram, 0, "outColor")
+
+ glLinkProgram(shaderProgram)
+ glUseProgram(shaderProgram)
+
+ # Vertex data <-> attributes
+ var posAttrib = glGetAttribLocation(shaderProgram, "position").gluint
+ glEnableVertexAttribArray(posAttrib)
+ glVertexAttribPointer(posAttrib, 2, cGL_FLOAT, false,
+ 5*sizeof(GLFloat).int32, nil)
+
+ var colAttrib = glGetAttribLocation(shaderProgram, "color").gluint
+ glEnableVertexAttribArray(colAttrib)
+ glVertexAttribPointer(colAttrib, 3, cGL_FLOAT, false,
+ 5*sizeof(GLFloat).int32,
+ cast[pointer](2*sizeof(GLFloat)))
+
+when isMainModule:
+ glfw.init()
+ var win = newWin()
+ win.makeContextCurrent()
+
+ loadExtensions()
+
+ var shaderProgram: TGLuint
+ setup(shaderProgram)
+
+ while not win.shouldClose:
+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
+
+ glDrawArrays(GL_TRIANGLES, 0, 3)
+ win.swapBufs()
+
+ pollEvents()
+
+ win.destroy()
+ glfw.terminate()
+```
diff --git a/content/content/primitives.md b/content/primitives.md
similarity index 100%
rename from content/content/primitives.md
rename to content/primitives.md
diff --git a/content/content/procs.md b/content/procs.md
similarity index 95%
rename from content/content/procs.md
rename to content/procs.md
index 39d0475..9e3eb9f 100644
--- a/content/content/procs.md
+++ b/content/procs.md
@@ -57,7 +57,7 @@ echo([[1, 2], [3, 4]]) # See varargs for
# how echo works
proc `^&*^@%`(a, b: string): string =
- ## A confusingly named useless operator
+ ## An confusingly named useless operator
result = a[0] & b[high(b)]
assert("foo" ^&*^@% "bar" == "fr")
@@ -78,7 +78,7 @@ proc `+`(a, b: string): string =
proc `*`[T](a: T, b: int): T =
result = zero
for i in 0..b:
- result = result + a # calls `+` from line 3
+ result = result + a
assert("a" * 10 == "aaaaaaaaaaa")
```
diff --git a/content/content/procvars.md b/content/procvars.md
similarity index 82%
rename from content/content/procvars.md
rename to content/procvars.md
index 12a6921..53c6ad1 100644
--- a/content/content/procvars.md
+++ b/content/procvars.md
@@ -20,10 +20,10 @@ $ nim c -r filterclosure.nim
@[64, 128, 256]
```
-Existing procedures can also be passed as functions, but only if they are annotated with the `{.procvar.}` pragma. This is because there may be default parameters, which must be specially handled by the compiler.
+Existing procedures can also be passed as functions, but only if they are annotated with the `{.procvar.}` pragma.
``` nimrod
proc greaterThan32(x: int): bool {.procvar.} = x > 32
echo powersOfTwo.filter(greaterThan32)
-```
+```
\ No newline at end of file
diff --git a/content/content/seqs.md b/content/seqs.md
similarity index 51%
rename from content/content/seqs.md
rename to content/seqs.md
index 70bd106..e6b43ab 100644
--- a/content/content/seqs.md
+++ b/content/seqs.md
@@ -19,14 +19,14 @@ for i, v in a:
for i in 4..100:
b.add(i * i)
-b.delete(0) # takes O(n) time
+b.delete(0) # takes «O(n)» time
b = a[0] & b # Same as original b
```
## Immutability
-Sequences are dynamiclly allocated (i.e. allocated on the heap, not the stack), but they are immutable unless marked as `var`. That means
+While sequences are dynamiclly allocated, they are still immutable.
``` nimrod
let a = @[1, 2, 3]
@@ -40,16 +40,7 @@ var b = @[1, 2, 3]
b.add(4)
```
-will work without any problems. Sequences passed as "argument by value" are not modifiable. For example, the following will fail to compile.
-
-``` nimrod
-def do_something(mySeq: seq[int]) =
- mySeq[0] = 2 # this is a compile-time error
-var testSeq = [1, 2, 3]
-do_something(testSeq)
-```
-
-`seq` arguments can be mutable if they are passed as "argument by reference", ie. the parameter is annotated with the `var` or `ref`:
+will work without any problems. If wanted, a seq can be passed to a method with the `var` or `ref` annotation to make it modifiable, so
``` nimrod
proc foo(mySeq: var seq[int]) =
@@ -60,15 +51,3 @@ foo(thisSeq)
assert thisSeq[9] == 999
```
-
-You can copy a sequence passed as "argument by value" and modify the copy:
-
-``` nimrod
-def do_something(mySeq: seq[int]) =
- var varMySeq = mySeq # copy the seq
- varMySeq[0] = 999
- assert varMySeq[0] == 999
-var testSeq = [1, 2, 3]
-do_something(testSeq)
-assert testSeq[0] == 1
-```
diff --git a/content/content/strings.md b/content/strings.md
similarity index 56%
rename from content/content/strings.md
rename to content/strings.md
index 58b3eb1..dfaf6c2 100644
--- a/content/content/strings.md
+++ b/content/strings.md
@@ -16,7 +16,7 @@ echo """
proc re(s: string): string = s
-echo r".""."
+echo r" "" "
echo re"\b[a-z]++\b"
```
``` console
@@ -29,23 +29,17 @@ words words words ⚑