Browse Source

- Update doc
- Add more stuffs to some structs

tcheukueppo 2 years ago
parent
commit
0331cce9d8
2 changed files with 173 additions and 110 deletions
  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
 ### Examples
 
 
 ```
 ```
-var x = [ qw(one two three) ]
+let x = [ qw(one two three) ]
 
 
 # [ "Three", "Two", "One" ]
 # [ "Three", "Two", "One" ]
-var b = x.map(:.cap).rev
+let b = x.map(:.cap).rev
 
 
 # [ "0ne", "tw0", "three" ]
 # [ "0ne", "tw0", "three" ]
 x =~ s<o>«0»
 x =~ s<o>«0»
@@ -195,7 +195,7 @@ expression operators.
 ### Examples
 ### Examples
 
 
 ```
 ```
-var a = [ qw|ONE TWO THREE| ]
+let a = [ qw|ONE TWO THREE| ]
 a.each: .lc.say
 a.each: .lc.say
 
 
 say q"interpolation won't work"
 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
 they refer to remain untouched. You cannot temporarize lexically scoped variables and
 all package variables regardless of their types can to temporarize.
 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 {
 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}
         # a: {one => 1, two => 2}
-        var a += {two => 2}
+        let a += {two => 2}
 
 
         # could still use "One::Two::x" at declaration
         # could still use "One::Two::x" at declaration
         temp x = {}
         temp x = {}
@@ -283,7 +283,7 @@ explicitly indicate that it is a package variables.
 const z = 4
 const z = 4
 
 
 # constant package variables
 # constant package variables
-const pkg (x, y) = (2, 10)
+const our (x, y) = (2, 10)
 ```
 ```
 
 
 ## Special variables
 ## Special variables
@@ -334,7 +334,7 @@ support concurrency.
 
 
 ```
 ```
 for ^5 {
 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.
 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)    = 2, 10, -1, 5 # a: 2, b: 10, c: -1
 (a, b, c)    = array        # a: [1, 2, 3, 4, 5], b: nil, c: nil
 (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.
 result of the last evaluated expression.
 
 
 ```
 ```
-var v = do { 2 }
+let v = do { 2 }
 
 
 # output: 2
 # output: 2
 say v
 say v
@@ -490,7 +490,7 @@ say v
 do { false } || die "failed"
 do { false } || die "failed"
 
 
 # x: 18
 # x: 18
-var x = do { 2 ** 4 } + 2
+let x = do { 2 ** 4 } + 2
 ```
 ```
 
 
 ## Topic variables
 ## Topic variables
@@ -549,7 +549,7 @@ else {
 }
 }
 
 
 
 
-var x = Num.rand(120)
+let x = Num.rand(120)
 if x % 2 -> r {
 if x % 2 -> r {
     say "remainder is #{r}"
     say "remainder is #{r}"
 }
 }
@@ -561,7 +561,7 @@ in a new scope.
 ```
 ```
 say "one" if true
 say "one" if true
 
 
-var k = 2 if 1
+let k = 2 if 1
 # output: 2
 # output: 2
 k.say
 k.say
 ```
 ```
@@ -584,7 +584,7 @@ default topic variable `_` to the value returned by the their
 conditional expressions.
 conditional expressions.
 
 
 ```
 ```
-var (u, y) = 5, nil
+let (u, y) = 5, nil
 
 
 with u { say "defined, see: #{_}" }
 with u { say "defined, see: #{_}" }
 
 
@@ -597,7 +597,7 @@ else              { say "and never here too" }
 The `with` statement avoid you from doing the following
 The `with` statement avoid you from doing the following
 
 
 ```
 ```
-var x = (y + 1) / 2
+let x = (y + 1) / 2
 with x { .say }
 with x { .say }
 ```
 ```
 
 
@@ -616,7 +616,7 @@ Its statement modifer form.
 ```
 ```
 # output: 2 4 4 8
 # output: 2 4 4 8
 for 4, 8 {
 for 4, 8 {
-    var k = _ with _ / 2
+    let k = _ with _ / 2
     say k / _
     say k / _
 }
 }
 ```
 ```
@@ -640,7 +640,7 @@ Here are examples of iterations over a comma seperated list of values
 # three iterations
 # three iterations
 for "a", r/regex/, [2, 4] { .say }
 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
 # trailing comma to indicate it is a list and thus only one iteration
 for ar, { .say }
 for ar, { .say }
@@ -652,7 +652,7 @@ for ar, { .say }
 
 
 ---
 ---
 We have a.len + 1 iterations, the array destruction operator is used to
 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
 value to handle situations where we are out of elements
 ---
 ---
 for ar…, 2 -> m, n = 'default' { (n + '-' + m).say }
 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.
 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"
 # "grep" and "map" got registered and they later on get called for every element in "a"
 for a.lazy
 for a.lazy
@@ -729,7 +729,7 @@ given 34 {
 For topicalization, you can also use `given` as a standalone statement
 For topicalization, you can also use `given` as a standalone statement
 
 
 ```
 ```
-var x = [2, 5]
+let x = [2, 5]
 given x {
 given x {
     say "variable x has two elements" if .len == 2
     say "variable x has two elements" if .len == 2
 }
 }
@@ -746,10 +746,10 @@ loop [ [ INIT ] ; [ COND ] ; [ STEP ] ] { CODE }
 Just like the C-for loop
 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
 # you can skip some parts
-loop var k = 0;;k++ {
+loop let k = 0;;k++ {
     k.say
     k.say
     break if k == 10
     break if k == 10
 }
 }
@@ -762,7 +762,7 @@ loop { say "looping forever" }
 The basic `while` and `until` loop.
 The basic `while` and `until` loop.
 
 
 ```
 ```
-var k = 6
+let k = 6
 
 
 while k > 1 {
 while k > 1 {
     k.say
     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 {
 do {
     k.push(b.pop)
     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.
 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|
 amap.each_kv {|k,v|
     once say 'only once!'
     once say 'only once!'
@@ -929,7 +929,7 @@ Here we are declaring an anonymous function which takes a single
 parameter and then call it.
 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)
 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!
 single expression. `__FUNC__` does not work here!
 
 
 ```
 ```
-var sleep = :5.sleep
+let sleep = :5.sleep
 sleep.call
 sleep.call
 ```
 ```
 
 
@@ -953,16 +953,16 @@ It is possible to omit `_` when calling a method on the content of a topic
 variable.
 variable.
 
 
 ```
 ```
-var anony = { say _.Str * 2 }
+let anony = { say _.Str * 2 }
 
 
 # output: tanzaniatanzania
 # output: tanzaniatanzania
 anony.call("tanzania")
 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")
 anony.call("a", "b")
 
 
 # .ucfirst is the same as _.ucfirst
 # .ucfirst is the same as _.ucfirst
-var ar = {qw<tcheukam madjou monthe>}
+let ar = {qw<tcheukam madjou monthe>}
 say ar.map(:.ucfirst)
 say ar.map(:.ucfirst)
 ```
 ```
 
 
@@ -1072,7 +1072,7 @@ function was paused by a `take` call.
 
 
 ```
 ```
 fun factors(n) {
 fun factors(n) {
-    var k = 1
+    let k = 1
 
 
     while k ** 2 < n {
     while k ** 2 < n {
         take k, n.div(k) if n % k 
         take k, n.div(k) if n % k 
@@ -1225,7 +1225,7 @@ its updated status and result with the `status` and `done` methods
 respectively.
 respectively.
 
 
 ```
 ```
-var w = Work.new   # new Work object
+let w = Work.new   # new Work object
 say w.status       # output: Do
 say w.status       # output: Do
 w.done("I'm done")
 w.done("I'm done")
 say w.status       # output: 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.
 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}" })
             .catch({(e) say "Catched: #{e}" })
             .then({ say "My handler is the one above"; _ + 2 })
             .then({ say "My handler is the one above"; _ + 2 })
             .then({(r) say "Mine is below"; r - 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.
 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)
 Work.allof(k)
     .then: k.map(:.result).sum.say
     .then: k.map(:.result).sum.say

+ 135 - 72
src/ma_obj.h

@@ -34,17 +34,17 @@
 #if !defined(MA_NAN_TAGGING)
 #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++:
  *   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.
  *       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
  * parts. This variable already gathers all what is necessary to
  * represent booleans and nils values.
  * represent booleans and nils values.
  *
  *
@@ -52,7 +52,7 @@
  *
  *
  * - Bits 0-4:
  * - Bits 0-4:
  *   To represent the different types of values except for object
  *   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
  *   is an object then bits 0-4 determine its object's type. This
  *   gives us a maximum of 32 objects which suffices.
  *   gives us a maximum of 32 objects which suffices.
  *
  *
@@ -60,7 +60,7 @@
  *   To represent variants of certain (O_)?TYPE_.* types. You can
  *   To represent variants of certain (O_)?TYPE_.* types. You can
  *   have at most 3 variants for each base type which suffices.
  *   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 {
 typedef struct {
    Ubyte type;
    Ubyte type;
@@ -85,7 +85,7 @@ typedef struct {
 
 
 /*
 /*
  * Defines all the possible standard types of a value, V_TYPE_OBJ is
  * 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_NIL    0
 #define V_TYPE_BOOL   1
 #define V_TYPE_BOOL   1
@@ -154,11 +154,11 @@ typedef uint64_t Value;
 #endif
 #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 {
 typedef struct Header {
    Ubyte type;
    Ubyte type;
@@ -221,8 +221,10 @@ typedef struct Header {
  * as attributes.
  * as attributes.
  */
  */
 #define O_TYPEV_CCLASS  vary(O_TYPE_CLASS, 1)
 #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_cclass(v)  o_check_vartype(v, O_TYPEV_CCLASS)
+#define is_role(v)    o_check_vartype(v, O_TYPEV_ROLE)
 
 
 /* Immutable and mutable bags */
 /* Immutable and mutable bags */
 #define O_TYPEV_BAG   vary(O_TYPE_MAP, 1)
 #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)
 #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 {
 typedef struct {
@@ -269,15 +271,15 @@ typedef struct {
    unsigned int hash;
    unsigned int hash;
    size_t rlen;
    size_t rlen;
    size_t len;
    size_t len;
-   Byte str[1];
+   Byte *str;
 } 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 {
 typedef struct {
    Header obj;
    Header obj;
    Num x;
    Num x;
@@ -285,31 +287,68 @@ typedef struct {
 } Range;
 } 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 {
 typedef struct {
    Header obj;
    Header obj;
+   Value *array;
+   Uint asize;
+   Ubyte lsize;
+   Node *node;
 } Map;
 } 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.
  * 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
  * 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.
  * 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 {
 typedef struct Class {
@@ -318,23 +357,24 @@ typedef struct Class {
    union {
    union {
       struct {
       struct {
          Map *fields;
          Map *fields;
-         struct Class *roles, *supers, *c3;
+         struct Class *roles;
+         struct Class *supers;
+         struct Class *c3;
       } ma;
       } ma;
       struct {
       struct {
          Value cdata;
          Value cdata;
          size_t size;
          size_t size;
       } c;
       } c;
-   } as;
+   } in;
    Map *methods;
    Map *methods;
 } Class;
 } 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 {
 typedef struct {
    Header obj;
    Header obj;
@@ -342,55 +382,78 @@ typedef struct {
 } Instance;
 } 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;
    Header obj;
+   Str *name; 
    Map *ours;
    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;
    Header obj;
-   //...
+   Namespace *ns;
+   Buf code;
+   Buf constants;
+   Map *temps;
+   int num_up;
+   int arity;
 } Fun;
 } Fun;
 
 
 /*
 /*
  */
  */
-
 typedef struct Upvalue {
 typedef struct Upvalue {
    Header obj;
    Header obj;
-   Value *to;
+   Value *p;
    union {
    union {
       struct Upvalue *next;
       struct Upvalue *next;
       Value val;
       Value val;
    } state;
    } state;
 } Upvalue;
 } Upvalue;
 
 
-#endif
+typedef struct Closure {
+   Header obj;
+   Fun *fun;
+   Upvalue *upvalues;
+} Closure;
 
 
+
+#endif