Browse Source

WIP docs.

Mark Sibly 8 years ago
parent
commit
c5ec770d44

+ 11 - 0
modules/monkey/docs/articles/articles.md

@@ -0,0 +1,11 @@
+
+@manpage Articles and tutorials
+
+# Articles and tutorials
+
+This section contains a number of articles and tutorials.
+
+@import operator-overloading.md
+@import lambda-functions.md
+@import namespaces-and-using.md
+@import multifile-projects.md

+ 32 - 0
modules/monkey/docs/articles/lambda-functions.md

@@ -0,0 +1,32 @@
+
+### What are 'lambda functions'?
+
+A lambda function is a special type of function that can be declared in the middle of an expression.
+
+You can think of a lambda function a bit like a ‘temporary’ function – instead of having to declare an entirely separate function to do what you need, you can just declare a lambda function ‘on the fly’ in the middle of an expression.
+
+ A lambda function is anonymous. It has no name so can only be used by the expression it is declared within.
+
+A lambda functions can make use of the same local variables as the expression it is declared within. It does this by ‘capturing’ these variables, which means the lambda function receives a copy of the local variable’s value at the point the lambda function is declared. This means that a lambda function will not ‘see’ any  future modifications to local variables. A lambda function cannot ‘see’ local variables that have not been declared yet!
+
+If a lambda function is declared within a method, it can also see (and modify) object fields, and call object methods.
+
+Here is a simple example:
+
+```
+Function Test( func:Void() )
+   
+   func()
+
+End
+
+Function Main()
+
+   Test( Lambda()
+
+      Print "Hello from lambda!"
+
+   End )
+
+End
+```

+ 58 - 0
modules/monkey/docs/articles/multifile-projects.md

@@ -0,0 +1,58 @@
+
+# Multifile projects and #Import.
+
+To add additional source files to a monkey2 project, you use the #Import directive. #Import can also be used to import other stuff into a project, but more on that late
+
+\#Imports should appear at the top of a source file before any declarations occur. #Import takes one parameter – the path to the file to import. If the file is a '.monkey2' file, the extensions can be omitted, eg:
+ 
+
+```
+'file1.monkey2
+'
+#Import "file2"
+#Import "file3"
+ 
+Function Something()
+End
+```
+
+The import path can be relative or absolute, and contain “../” etc, making it easy to get at source files located anywhere.
+
+When you build a monkey2 app (or module), the compiler starts with a single ‘root’ monkey2 source file and searches for all other monkey2 files reachable – directly or indirectly – from that root file via #Import directives. All files found via #Import this way will ultimately be included in the project and built  by the compiler.
+
+You only need to #Import a particular file once per project – duplicate #Imports of the same file are ignored by the compiler.
+
+Code in any imported monkey2 file can use code in any other imported monkey2 file, regardless of whether or not the files #Import each other. For example:
+
+```
+'***** file1.monkey2 *****
+'
+#Import "file2"
+#Import "file3"
+ 
+Function Func1()
+   Func1()
+   Func2()
+   Func3()
+End
+ 
+'***** file2.monkey2 *****
+ 
+Function Func2()
+   Func1()
+   Func2()
+   Func3()
+End
+ 
+'***** file3.monkey2 *****
+ 
+Function Func3()
+   Func1()
+   Func2()
+   Func3()
+End
+```
+
+This is perfectly valid, as long as file1.monkey2 is the ‘root file’ you compile.
+
+ 

+ 50 - 0
modules/monkey/docs/articles/namespaces-and-using.md

@@ -0,0 +1,50 @@
+
+### Namespaces and using.
+
+Monkey2 provides simple support for namespaces.
+
+Each file can have a Namespace directive at the top that specifies the ‘scope’ of all the declarations (functions, globals, classes etc) in the file. For example:
+
+```
+'***** file1.monkey2 *****
+'
+Namespace myapp 'declare namesapce
+ 
+Global SomeGlobal:Int
+ 
+Function SomeFunction()
+End
+```
+
+The ‘namespace myapp’ at the top here means that the SomeGlobal and SomeFunction declarations end up in the ‘myapp’ namespace. If you don’t have a Namespace at the top of a source file, a ‘default’ namespace is used. It is recommended that you use Namespace for all substantial projects though.
+
+To access stuff declared in a namespace, use the ‘.’ operator. For example, you can access the SomeGlobal variable above using myapp.SomeGlobal.
+
+However, you don’t need to do this if the declaration being accessed is in the same namespace (or a ‘parent’ namespace…see below) as the code doing the accessing. For example, any code within the above file can use SomeGlobal and SomeFunction without the need for  a ‘myapp.’ prefix, as that code is also in the myapp namespace.
+
+This also applies to multifile projects. If 2 separate monkey2 files are in the same namespace, then they can freely access each other declarations without the need for a namespace prefix.
+
+You can almost think of namespace as simple classes – albeit classes that can’t be new’d so can’t have fields or methods. The name of the class provides a ‘scope’ for the globals and functions declared in the class, and declarations with the class can directly access other declarations in the same class.
+
+Namespaces are also hierarchical. While ‘Namespace myapp’ creates a simple ‘top level’ namespace, it’s also possible to create child namespaces using ‘.’. For example ‘Namespace myapp.utils’ referes to a ‘utils’ namespace within the top level ‘myapp’ namespace.
+
+Finally, the Using directive can make it easier to access frequently used declarations inside a namespace. For example, the ChangeDir and CurrentDir functions are declared in the ‘std.filesystem’ namespace, but (depending on your self discipline level) it can be a hassle having to use std.filesystem.ChangeDir and std.filesystem.CurrentDir all the time.
+
+To help out here, the ‘Using’ directive can be used to instruct the compiler to search a particular namespace for identifiers that it can’t normally find. For example:
+
+```
+Namespace myapp
+ 
+Using std.filesystem
+ 
+Function Main()
+   ChangeDir( ".." )
+   Print CurrentDir()
+End
+```
+
+Without the Using declaration in the above code, you would need to use std.filesystem.ChangeDir and std.filesystem.CurrentDir.
+
+You can have multiple Usings in an app, and Usings must appear at the top of a file, before any declarations.
+
+The namespace specified in a Using must be ‘absolute’. That is, the namespace of the file is not taken into account when resolving the Using namespace.

+ 105 - 0
modules/monkey/docs/articles/operator-overloading.md

@@ -0,0 +1,105 @@
+
+### Operator Overloading
+
+Operator overloading is a very cool feature that allows you to customize the behaviour of the built-in monkey2 operators for classes and structs.
+
+You overload an operator by writing an ‘operator method’, which is effectively just a special kind of method. Operators must appear inside classes/structs – they cannot currently be ‘global’.
+
+Here is a simple example:
+
+```
+Struct Vec2
+
+   Field x:Float
+   Field y:Float
+
+   Method New( x:Float,y:Float )
+      Self.x=x
+      Self.y=y
+   End
+
+   Method ToString:String()
+      Return "Vec2("+x+","+y+")"
+   End
+
+   'Overload the addition operator.
+   Operator+:Vec2( rhs:Vec2 )
+      Return New Vec2( x+rhs.x,y+rhs.y )
+   End
+
+End
+```
+
+The ‘Operator+’ declaration here defines an addition operator for Vec2. This is then used whenever a Vec2 appears as the ‘left hand side’ of an addition. For example:
+
+```
+Function Main()
+   Local v1:=New Vec2( 10.0,20.0 )
+   Local v2:=New Vec2( 30.0,40.0 )
+   Local v3:=v1+v2    'note: calls Operator+ in Vec2.
+   Print v3.ToString()
+End
+```
+
+The following unary operators can be overloaded: + – ~
+
+The following binary operators can be overloaded: * / Mod + – Shl Shr & | ~ = <> < > <= >= <=>
+
+The following assignment operators can be overloaded: *= /= Mod= += -= Shl= Shr= &= |= ~=
+
+Indexing behaviour can also be overloaded using: [] []=
+
+Note that you cannot override ‘Not’, ‘And’ or ‘Or’ - would just be too confusing if the meaning of these weren't consistent IMO!
+
+Operators can return any type of value, and can take any type of value for their ‘right hand side’ argument(s). However, the precedence of operators cannot be changed.
+
+The ‘[]’ and ‘[]=’ operators allow you to define ‘indexing’ like behaviour. The ‘[]’ operator is used when an object is indexed, and ‘[]=’ is used when an object is indexed and assigned. Both of these operators can accept any number of parameters of any type. The ‘[]=’ operator requires an additional parameter that is the value to be assigned. This must appear at the end of the parameter list.
+
+Here is an example of some indexing operators for the Vec2 class above:
+
+```
+Struct Vec2
+
+   ...etc...
+
+   Operator[]:Float( index:Int )
+      Assert( index=0 Or index=1 )
+      If index=0 Return x Else Return y
+   End
+
+   Operator[]=( index:Int,value:Float )
+      Assert( index=0 Or index=1 )
+      If index=0 Then x=value Else y=value
+   End
+End
+```
+
+With these additions, you can access Vec2 coordinates ‘by index’, eg:
+
+```
+Function Main()
+   Local v:=New Vec2
+   v[0]=10.0
+   v[1]=20.0
+   Print v[0]
+   Print v[1]
+End
+```
+
+You can also overload assignment operators, for example:
+
+```
+Struct Vec2
+
+   ...etc...
+
+   Operator+=( v:Vec2 )
+      x+=v.x
+      y+=v.y
+   End
+End
+```
+
+If you have already written an Operator+ (as is the case here) this is not strictly necessary, as monkey2 will generate the code for Operator+= for you. However, you may still want to provide a custom version for Operator+= if your code can do so more efficiently.
+
+Note that you cannot overload the plain assignment operator '='.

+ 2 - 0
modules/monkey/docs/manual.md

@@ -13,6 +13,8 @@ Have fun!
 
 @import language/language.md
 
+@import articles/articles.md
+
 @import sdks.md
 
 @import mx2cc.md