Răsfoiți Sursa

- Update doc
- Add more stuffs to some structs

tcheukueppo 2 ani în urmă
părinte
comite
0331cce9d8
2 a modificat fișierele cu 173 adăugiri și 110 ștergeri
  1. 38 38
      docs/maat.md
  2. 135 72
      src/ma_obj.h

+ 38 - 38
docs/maat.md

@@ -174,10 +174,10 @@ and regular expression operators.
 ### Examples
 
 ```
-var x = [ qw(one two three) ]
+let x = [ qw(one two three) ]
 
 # [ "Three", "Two", "One" ]
-var b = x.map(:.cap).rev
+let b = x.map(:.cap).rev
 
 # [ "0ne", "tw0", "three" ]
 x =~ s<o>«0»
@@ -195,7 +195,7 @@ expression operators.
 ### Examples
 
 ```
-var a = [ qw|ONE TWO THREE| ]
+let a = [ qw|ONE TWO THREE| ]
 a.each: .lc.say
 
 say q"interpolation won't work"
@@ -227,17 +227,17 @@ name declared in its own package. Any modification made to temporary variables r
 they refer to remain untouched. You cannot temporarize lexically scoped variables and
 all package variables regardless of their types can to temporarize.
 
-We declare package variables with the keyword `pkg`, lexically scoped variables
-with `var` and temporary variables with `temp`.
+We declare package variables with the keyword `our`, lexically scoped variables
+with `let` and temporary variables with `temp`.
 
 ```
 package One::Two {
-    pkg x = [ qw<one two three> ]
+    our x = [ qw<one two three> ]
 
-    var a = {one => 1}
+    let a = {one => 1}
     {
         # a: {one => 1, two => 2}
-        var a += {two => 2}
+        let a += {two => 2}
 
         # could still use "One::Two::x" at declaration
         temp x = {}
@@ -283,7 +283,7 @@ explicitly indicate that it is a package variables.
 const z = 4
 
 # constant package variables
-const pkg (x, y) = (2, 10)
+const our (x, y) = (2, 10)
 ```
 
 ## Special variables
@@ -334,7 +334,7 @@ support concurrency.
 
 ```
 for ^5 {
-    var _
+    let _
 }
 ```
 
@@ -389,8 +389,8 @@ You can use the accumulator and destructor operator in assignments, here
 are some examples which are self-documentary.
 
 ```
-var (a, b, c, d, e, f)
-var array = [1, 2, 3, 4, 5]
+let (a, b, c, d, e, f)
+let array = [1, 2, 3, 4, 5]
 
 (a, b, c)    = 2, 10, -1, 5 # a: 2, b: 10, c: -1
 (a, b, c)    = array        # a: [1, 2, 3, 4, 5], b: nil, c: nil
@@ -479,7 +479,7 @@ do 'PATH/TO/A/MAAT/FILE'
 result of the last evaluated expression.
 
 ```
-var v = do { 2 }
+let v = do { 2 }
 
 # output: 2
 say v
@@ -490,7 +490,7 @@ say v
 do { false } || die "failed"
 
 # x: 18
-var x = do { 2 ** 4 } + 2
+let x = do { 2 ** 4 } + 2
 ```
 
 ## Topic variables
@@ -549,7 +549,7 @@ else {
 }
 
 
-var x = Num.rand(120)
+let x = Num.rand(120)
 if x % 2 -> r {
     say "remainder is #{r}"
 }
@@ -561,7 +561,7 @@ in a new scope.
 ```
 say "one" if true
 
-var k = 2 if 1
+let k = 2 if 1
 # output: 2
 k.say
 ```
@@ -584,7 +584,7 @@ default topic variable `_` to the value returned by the their
 conditional expressions.
 
 ```
-var (u, y) = 5, nil
+let (u, y) = 5, nil
 
 with u { say "defined, see: #{_}" }
 
@@ -597,7 +597,7 @@ else              { say "and never here too" }
 The `with` statement avoid you from doing the following
 
 ```
-var x = (y + 1) / 2
+let x = (y + 1) / 2
 with x { .say }
 ```
 
@@ -616,7 +616,7 @@ Its statement modifer form.
 ```
 # output: 2 4 4 8
 for 4, 8 {
-    var k = _ with _ / 2
+    let k = _ with _ / 2
     say k / _
 }
 ```
@@ -640,7 +640,7 @@ Here are examples of iterations over a comma seperated list of values
 # three iterations
 for "a", r/regex/, [2, 4] { .say }
 
-var ar = [ qw<one two three four five> ]
+let ar = [ qw<one two three four five> ]
 
 # trailing comma to indicate it is a list and thus only one iteration
 for ar, { .say }
@@ -652,7 +652,7 @@ for ar, { .say }
 
 ---
 We have a.len + 1 iterations, the array destruction operator is used to
-break 'ar' into a list. At topic var declaration, set a custom default
+break 'ar' into a list. At topic let declaration, set a custom default
 value to handle situations where we are out of elements
 ---
 for ar…, 2 -> m, n = 'default' { (n + '-' + m).say }
@@ -684,7 +684,7 @@ registers that method with its arguments so that it gets called
 for every lazy iteration.
 
 ```
-var a = [qw(nairobi niamey yaounde)]
+let a = [qw(nairobi niamey yaounde)]
 
 # "grep" and "map" got registered and they later on get called for every element in "a"
 for a.lazy
@@ -729,7 +729,7 @@ given 34 {
 For topicalization, you can also use `given` as a standalone statement
 
 ```
-var x = [2, 5]
+let x = [2, 5]
 given x {
     say "variable x has two elements" if .len == 2
 }
@@ -746,10 +746,10 @@ loop [ [ INIT ] ; [ COND ] ; [ STEP ] ] { CODE }
 Just like the C-for loop
 
 ```
-loop var k = 0; k ≤ 20; k² { k.say }
+loop let k = 0; k ≤ 20; k² { k.say }
 
 # you can skip some parts
-loop var k = 0;;k++ {
+loop let k = 0;;k++ {
     k.say
     break if k == 10
 }
@@ -762,7 +762,7 @@ loop { say "looping forever" }
 The basic `while` and `until` loop.
 
 ```
-var k = 6
+let k = 6
 
 while k > 1 {
     k.say
@@ -783,8 +783,8 @@ do { CODE } until COND
 ```
 
 ```
-var k = Set.new(2, 4, 5)
-var b = [2, 7, 3]
+let k = Set.new(2, 4, 5)
+let b = [2, 7, 3]
 
 do {
     k.push(b.pop)
@@ -857,7 +857,7 @@ it offers is freeing us from using a conditional construct to avoid
 the execution of a statement.
 
 ```
-var amap = {qw(one 1 two 2 three 3)}
+let amap = {qw(one 1 two 2 three 3)}
 
 amap.each_kv {|k,v|
     once say 'only once!'
@@ -929,7 +929,7 @@ Here we are declaring an anonymous function which takes a single
 parameter and then call it.
 
 ```
-var sleep = {|x| x.sleep; say "slept for #x seconds" }
+let sleep = {|x| x.sleep; say "slept for #x seconds" }
 sleep.call(5)
 ```
 
@@ -937,7 +937,7 @@ You can use the other syntax if your anonymous function is just a
 single expression. `__FUNC__` does not work here!
 
 ```
-var sleep = :5.sleep
+let sleep = :5.sleep
 sleep.call
 ```
 
@@ -953,16 +953,16 @@ It is possible to omit `_` when calling a method on the content of a topic
 variable.
 
 ```
-var anony = { say _.Str * 2 }
+let anony = { say _.Str * 2 }
 
 # output: tanzaniatanzania
 anony.call("tanzania")
 
-# Err: takes only one arg as the topic var is used in anony
+# Err: takes only one arg as the topic let is used in anony
 anony.call("a", "b")
 
 # .ucfirst is the same as _.ucfirst
-var ar = {qw<tcheukam madjou monthe>}
+let ar = {qw<tcheukam madjou monthe>}
 say ar.map(:.ucfirst)
 ```
 
@@ -1072,7 +1072,7 @@ function was paused by a `take` call.
 
 ```
 fun factors(n) {
-    var k = 1
+    let k = 1
 
     while k ** 2 < n {
         take k, n.div(k) if n % k 
@@ -1225,7 +1225,7 @@ its updated status and result with the `status` and `done` methods
 respectively.
 
 ```
-var w = Work.new   # new Work object
+let w = Work.new   # new Work object
 say w.status       # output: Do
 w.done("I'm done")
 say w.status       # output: Done
@@ -1257,7 +1257,7 @@ If the exception of the work created by `.then` is not handled, it inherits
 its exception handler from the highiest top level Work.
 
 ```
-var w = Work.does({ sleep 4; 10 })
+let w = Work.does({ sleep 4; 10 })
             .catch({(e) say "Catched: #{e}" })
             .then({ say "My handler is the one above"; _ + 2 })
             .then({(r) say "Mine is below"; r - 2 })
@@ -1302,7 +1302,7 @@ or `Failed`. The value return by `.result` method call on the returned
 work object is always `true` and practically useless.
 
 ```
-var k = ^5.map {|i| Work.does(:sleep i) }
+let k = ^5.map {|i| Work.does(:sleep i) }
 
 Work.allof(k)
     .then: k.map(:.result).sum.say

+ 135 - 72
src/ma_obj.h

@@ -34,17 +34,17 @@
 #if !defined(MA_NAN_TAGGING)
 
 /*
- * $val: The value itself.
- *   $n: Representation of a number (see 'ma_conf.h').
- *   $obj: Pointer to an object, here, $val is an object.
+ * #val: The value itself.
+ *   #n: Representation of a number (see 'ma_conf.h').
+ *   #obj: Pointer to an object, here, $val is an object.
  *
  *   The below attributes are used to extend Maat code with C/C++:
  *
- *   $cdata: Pointer to some memory representing data of a C class
- *   $f: Pointer to a C function, either represent a cdata's
+ *   #cdata: Pointer to some memory representing data of a C class
+ *   #f: Pointer to a C function, either represent a cdata's
  *       method or just a standalone function.
  *
- * $type: Determines $val's type, its bits are segmented into three
+ * #type: Determines $val's type, its bits are segmented into three
  * parts. This variable already gathers all what is necessary to
  * represent booleans and nils values.
  *
@@ -52,7 +52,7 @@
  *
  * - Bits 0-4:
  *   To represent the different types of values except for object
- *   values which is detected when the value's MSB is 1. If $val
+ *   values which is detected when the value's MSB is 1. If #val
  *   is an object then bits 0-4 determine its object's type. This
  *   gives us a maximum of 32 objects which suffices.
  *
@@ -60,7 +60,7 @@
  *   To represent variants of certain (O_)?TYPE_.* types. You can
  *   have at most 3 variants for each base type which suffices.
  *
- * - bit 7: Mark bit: if 1 then $val is an object, 0 otherwise.
+ * - bit 7: Mark bit: if 1 then #val is an object, 0 otherwise.
  */
 typedef struct {
    Ubyte type;
@@ -85,7 +85,7 @@ typedef struct {
 
 /*
  * Defines all the possible standard types of a value, V_TYPE_OBJ is
- * also a value. A value 'v' is an object if the MSB of its $type is 1.
+ * also a value. A value 'v' is an object if the MSB of its #type is 1.
  */
 #define V_TYPE_NIL    0
 #define V_TYPE_BOOL   1
@@ -154,11 +154,11 @@ typedef uint64_t Value;
 #endif
 
 /*
- * $$Header inherited by all the below objects
- * $type: type of the object
- * $mark: flag to mark the object during collection
- * $class: the object's class
- * $next: next obj,to keep track of all objects
+ * ##Header inherited by all the below objects
+ * #type: type of the object
+ * #mark: flag to mark the object during collection
+ * #class: the object's class
+ * #next: next obj,to keep track of all objects
  */
 typedef struct Header {
    Ubyte type;
@@ -221,8 +221,10 @@ typedef struct Header {
  * as attributes.
  */
 #define O_TYPEV_CCLASS  vary(O_TYPE_CLASS, 1)
+#define O_TYPEV_ROLE    vary(O_TYPE_CLASS, 2)
 
 #define is_cclass(v)  o_check_vartype(v, O_TYPEV_CCLASS)
+#define is_role(v)    o_check_vartype(v, O_TYPEV_ROLE)
 
 /* Immutable and mutable bags */
 #define O_TYPEV_BAG   vary(O_TYPE_MAP, 1)
@@ -257,11 +259,11 @@ typedef struct Header {
 #define is_schedq(v)  o_check_type(v, O_TYPEV_SCHEDQ)
 
 /*
- * $$string object
- * $str: utf-8 encoded string itself
- * $hash: hash value of $str
- * $rlen: real length of $str
- * $len: user-percieved length of $str
+ * ##String object
+ * #str: utf-8 encoded string itself
+ * #hash: hash value of $str
+ * #rlen: real length of $str
+ * #len: user-percieved length of $str
  */
 
 typedef struct {
@@ -269,15 +271,15 @@ typedef struct {
    unsigned int hash;
    size_t rlen;
    size_t len;
-   Byte str[1];
+   Byte *str;
 } Str;
 
 /*
- * $$Range object [x..y] (inclusive)
- * $x: the start
- * $y: and the end
+ * ##Range object [x..y] (inclusive)
+ *
+ * #x: the start
+ * #y: and the end
  */
-
 typedef struct {
    Header obj;
    Num x;
@@ -285,31 +287,68 @@ typedef struct {
 } Range;
 
 /*
+ * ##Representation of a node
+ *
+ * #val: node's value
+ * #k:
+ *   #key: node's key
+ *   #next: next node in case of collision
  */
+typedef struct Node {
+   struct NodeKey {
+      Value key;
+      Int next;
+   } k;
+   Value val;
+} Node;
 
+/*
+ * ##Representation of a Map(a.k.a Hash table), it has
+ * two parts, it has two parts, the array and the hash
+ * one.
+ *
+ * #lsize:
+ * #array:
+ * #asize:
+ * #node:
+ */
 typedef struct {
    Header obj;
+   Value *array;
+   Uint asize;
+   Ubyte lsize;
+   Node *node;
 } Map;
 
 /*
- * $$Representation of a class, every object has a class, even the class
+ * ##Representation of a class, every object has a class, even the class
  * itself. Class of objects which aren't first class values are useless.
  *
- * $name: The class' name.
- * $methods: A map for the class' methods.
+ * #name: The class' name.
+ * #methods: A map for the class' methods.
  *
  * A C class is a class whose implemented is done in foreign languages
  * like C or C++, it is similar to full userdata in Lua lang.
  *
- * $as: A union which contains data specific to each type of class.
- * The inherited field $type tells us which struct to use.
+ * #in: A union which defines data depending on the object variant, we
+ * have 2 variants which are Role and Cclass
+ *
+ *   For a Cclass we have #c:
+ *
+ *     #cdata: Pointer to the raw memory.
+ *     #size: Size of the memory pointed by cdata.
  *
- * $cdata: Pointer to the raw memory.
- * $size: Size of the memory pointed by cdata.
+ *   For a Ma class and a Role we have #ma:
  *
- * $c3: List of classes obtained after c3 method resolution was applied
- * $fields: Hash map for the class' fields, each field has the default
- * value 'nil' unless explicitly stated.
+ *     #c3: List of classes obtained after c3 method resolution was applied
+ *     #fields: Hash map for the class' fields, each field has the default
+ *     value 'nil' unless explicitly stated.
+ *     #roles: Keeps the list of roles the class does.
+ *     #supers: Keeps the list of directly inherited superclasses.
+ *
+ * #roles and $supers exist mainly for class/object introspection. method
+ * bindings are done so the classes have direct access to roles' field and
+ * methods they ":does" and inherited methods from superclasses they ":is".
  */
 
 typedef struct Class {
@@ -318,23 +357,24 @@ typedef struct Class {
    union {
       struct {
          Map *fields;
-         struct Class *roles, *supers, *c3;
+         struct Class *roles;
+         struct Class *supers;
+         struct Class *c3;
       } ma;
       struct {
          Value cdata;
          size_t size;
       } c;
-   } as;
+   } in;
    Map *methods;
 } Class;
 
-
 /*
- * $$Instance of a class.
+ * ##Instance of a class.
  *
- * $fields: A map, the instance's fields, during object instanciation we
- * copy the instance's class $fields map which contains all the defaults.
- * Is this a good idea?
+ * #fields: A map, the instance's fields, during object instanciation it
+ * is set to its class' #fields map that keeps fields' defaults. Is this
+ * a good idea?
  */
 typedef struct {
    Header obj;
@@ -342,55 +382,78 @@ typedef struct {
 } Instance;
 
 /*
- * $$Represents the spec of a namespace: the namespace value and
- * its variables which have to be fully qualified when accessed
- * from outside.
+ * ##Represents the spec of a namespace: the namespace value and its
+ * variables which have to be fully qualified when accessed from outside
+ * itself.
+ *
+ * #name: Namespace's name.
+ *
+ * #ours: A map for the namespace's "our" variables. For the main::
+ * namespace, #ours takes care of the following type I & II special
+ * variables:
+ *      ENV, ARGC, ARGV, INC, PATH, SIG, DATA, $v, $o, $,, $/, $\
+ *      $|, $", $$, $(, $), $<, $>, $f, and $0.
  *
- * $ours: A map for the namespace's "our" variables.
- * $val: Either a class, role or package.
+ * The "main::" namespace which is a package {}, is "use"d by all the
+ * other namespaces and these special variables can be accessed without
+ * using their FQN.
+ *
+ * #exports: Values for keys of to be exported "our" variables.
+ * #ns_value: Either a class{}, role{} or package{}.
  */
-typedef struct Namespace_Spec {
+typedef struct Namespace {
    Header obj;
+   Str *name; 
    Map *ours;
-   Value val;
-} Namespace_Spec;
-
-/*
- * $ns_spec: A buffer of namespaces, since namespaces are unique
- * and aren't restrained by the concept of scopes wether or not
- * a namespace is defined in another, w
- */
-typedef struct NameSpace {
-   Header obj;
-   NameSpace_Spec ns_spec;
-} NameSpace;
-
-typedef struct Ma {
-} Ma;
-
-typedef struct {
-   Ma ma;
-} Work;
+   Value *exports;
+   Value ns_val;
+} Namespace;
 
 /*
+ * ##Struct for a Function
+ *
+ * #ns: is mainly used for class/object instrospection.
+ *
+ * #code:
+ * #constants:
+ *
+ * #temp_vars: For temporarization(the 'temp' key word) of package variables
+ * it is a map with keys correspond to scope level counts since multiple
+ * scopes multiple scopes can temporarize indentical package variables, using
+ * a map because it uses its array part when necessary and optimizes into a
+ * real map when indexes are sparsed. $temps takes care of the following
+ * special variables:
+ *   $<digit>(e.g $1, $2, $3, etc), $., $`, $&, and $'
+ *
+ * It is internally implemented c code that have to appropiately set these
+ * variables in $temps e.g Regex's .gmatch method.
  */
-
-typedef struct {
+typedef struct Fun {
    Header obj;
-   //...
+   Namespace *ns;
+   Buf code;
+   Buf constants;
+   Map *temps;
+   int num_up;
+   int arity;
 } Fun;
 
 /*
  */
-
 typedef struct Upvalue {
    Header obj;
-   Value *to;
+   Value *p;
    union {
       struct Upvalue *next;
       Value val;
    } state;
 } Upvalue;
 
-#endif
+typedef struct Closure {
+   Header obj;
+   Fun *fun;
+   Upvalue *upvalues;
+} Closure;
 
+
+#endif