[SCM] Lisaac compiler branch, master, updated. lisaac-0.12-612-gaeb4a35

Mildred Ki'Lya silkensedai at online.fr
Sun Mar 7 20:28:06 UTC 2010


The following commit has been merged in the master branch:
commit aeb4a3594328ff882004d368c2b49c47fc0a388b
Author: Mildred Ki'Lya <silkensedai at online.fr>
Date:   Sun Mar 7 21:27:57 2010 +0100

    Documentation continues

diff --git a/src/HACKING b/src/HACKING
index d2d2209..bdaceaa 100644
--- a/src/HACKING
+++ b/src/HACKING
@@ -1,99 +1,279 @@
 A Guide to Hacking in the Compiler Source
 =========================================
 
-Type Hierarchy
+You can generate the type hierarchy using the script `src/hierarchy.sh`
+
+Questions to Benoit
+===================
+
+- Why `&` and `|` are duplicated in `EXPR_AND_LOGIC`, `EXPR_AND`,
+  `EXPR_OR_LOGIC` and `EXPR_OR`. Is that for optimization purposes knowing that
+  the logic AND might not have to keep the exact result of the arithmetic AND?
+
+- Why no postcondition in `LIST.execute` ?
+
+        [ // make sure LIST.execute return a list
+          +? { + l:LIST; l ?= Result != NULL };
+        ]
+
+Global Variables
+================
+
+Found in `ANY`.
+
+- `list_main:LIST` is the list of the `main()` function.
+
+- `profil_current:PROFIL`: the profil being executed in the current execution
+  pass
+
+- `seq_list:FAST_ARRAY(LIST)`: the list hierarchy during the execute pass.
+  First comes the containing lists and then the contained lists. This is sort of
+  a stack trace.
+
+- `list_current:LIST`: the current list being executed. This is not always the
+  last element of `seq_list` as when a `PROFIL` is executed, the `list_current`
+  is reset to `NULL`.
+
+
+Passes
+======
+
+Passes can be found in `PROTOTYPE.depend`
+
+Depending Pass
+--------------
+
+Main code in `NODE.extend_pass`.
+
+This is where all the parsing happens and all the abstract syntax tree (AST) is
+generated.
+
+Executing Pass
 --------------
 
-### `INSTR`
-
-`external`:
-
-- `FORALL_DATA`
-- `CALL_NULL`
-
-`code_life`:
-
-- `LOOP_END`
-- `COP_LOCK`
-- `LIST`
-- `CALL_SLOT`
-- `PUSH`
-- `COP_UNLOCK`
-- `NOP`
-- `LOOP`
-- `SWITCH`
-- `NODE`
-- `EXPR`
-- `WRITE`
-    - `WRITE_SLOT`
-    - `WRITE_LOCAL`
-    - `WRITE_GLOBAL`
-    - `PUT_TO` (external)
-
-### `EXPR`
-
-`external`:
-
-- `EXTERNAL_C`
-- `SIZE_OF`
-- `ITEM`
-- `GET_TYPE_ID`
-- `IS_EXPANDED`
-- `PUT_TO`
-
-`external/comparison`:
-
-- `EXPR_BINARY_CMP`
-    - `EXPR_SUP_EQ`
-    - `EXPR_SUP`
-    - `EXPR_INF`
-    - `EXPR_EQUAL`
-    - `EXPR_INF_EQ`
-    - `EXPR_NOT_EQUAL`
-
-`external/logic`:
-
-- `EXPR_BINARY_LOGIC`
-    - `EXPR_AND_LOGIC`
-        - `EXPR_AND_AND_LOGIC`
-    - `EXPR_OR_LOGIC`
-        - `EXPR_OR_OR_LOGIC`
-- `EXPR_UNARY_LOGIC`
-    - `EXPR_NOT_LOGIC`
-
-`external/arithmetic`:
-
-- `EXPR_UNARY`
-    - `EXPR_NEG`
-    - `EXPR_NOT`
-- `EXPR_BINARY`
-    - `EXPR_AND`
-    - `EXPR_DIV`
-    - `EXPR_MOD`
-    - `EXPR_MUL`
-    - `EXPR_SUB`
-    - `EXPR_SHIFT_L`
-    - `EXPR_SHIFT_R`
-    - `EXPR_ADD`
-    - `EXPR_OR`
-    - `EXPR_XOR`
-
-`code_life`:
-
-- `CAST`
-- `EXPR_MULTIPLE`
-- `RESULT`
-- `READ`
-    - `READ_SLOT`
-    - `READ_LOCAL`
-    - `READ_GLOBAL`
-
-`constant`:
-
-- `CONSTANT`
-    - `CHARACTER_CST`
-    - `INTEGER_CST`
-    - `NATIVE_ARRAY_CHARACTER_CST`
-    - `PROTOTYPE_CST`
-    - `REAL_CST`
-    - `STRING_CST`
+Recursive executing pass is in `PROFIL_LIST.execute_pass_recursive`
+
+Main code in `PROFIL_LIST.execute` with some code before and after in
+`PROTOTYPE.depend` to cleanup before a new pass or check something that would
+trigger a new pass.
+
+`PROFIL_LIST` contain all profils for slots generated. They are ordered with the
+profils that are alive first, and the dead profils last. There are three
+categories of profils:
+- the profils that are always alive (`Section External`) below `life_limit_base`
+- the profils alive for the current executing pass below `life_limit`
+- the dead profils with an index greater or equal to `life_limit`.
+
+A standard execution pass is like this:
+
+1. First, all profils alive from the previous pass are marked dead (lower
+   `life_limit` to `life_limit_base`)
+2. It call `execute` on `list_main`
+3. For the profils (`profil_current`) that were marked alive during the previous
+   step, it call `execute` on them.
+4. Clean the dead profils.
+5. Determine if there is a need for a new executing pass.
+
+A recursive execution pass has `PROFIL.mode_recursive` to `TRUE` and is similar
+to a normal execution pass, with some differences.
+
+Code Generation
+---------------
+
+Generate function signatures: `PROFIL_LIST.genere_handler`
+
+Generate the `main()` source code: `LIST.genere_extern`
+
+Generate functions: `PROFIL_LIST.genere`
+
+Particular Types
+================
+
+AST Objects (items)
+-------------------
+
+The objects descending from `ITM_CODE` and `ITM_ARGUMENT` and `ITM_TYPE` and
+more generally, all items in the `item` directory form the abstract syntax tree.
+
+# `ITM_ARGUMENT` #
+
+- `ITM_ARGUMENT` (`item`)
+    - `ITM_ARG` (`item`)
+    - `ITM_ARGS` (`item`)
+
+
+This represents an argument type list. This is a list of `ITM_TYPE_MONO` and is
+specialized in two versions. `ITM_ARG` contains only one type while `ITM_ARGS`
+can contain multiple types
+
+# `ITM_CODE` #
+
+- `ITM_CODE` (`item`)
+    - `ITM_LIST` (`item`)
+    - `ITM_BLOCK` (`item`)
+    - `ITM_RESULT` (`item`)
+    - `ITM_BINARY` (`item`)
+    - `ITM_OLD` (`item`)
+    - `ITM_LDOTS` (`item`)
+    - `ITM_EXPRESSION` (`item`)
+    - `ITM_OPERATOR` (`item`)
+    - `ITM_LIST_IDF` (`item`)
+    - `ITM_READ` (`item`)
+        - `ITM_READ_ARG1` (`item`)
+        - `ITM_READ_ARGS` (`item`)
+        - `ITM_READ_ARG2` (`item`)
+    - `ITM_EXTERN` (`item`)
+        - `ITM_EXTERNAL` (`item`)
+        - `ITM_EXTERNAL_TYPE` (`item`)
+    - `ITM_WRITE` (`item`)
+        - `ITM_WRITE_CAST` (`item`)
+        - `ITM_WRITE_VALUE` (`item`)
+        - `ITM_WRITE_CODE` (`item`)
+    - `ITM_CONSTANT` (`item`)
+        - `ITM_PROTOTYPE` (`item`)
+        - `ITM_REAL` (`item`)
+        - `ITM_CHARACTER` (`item`)
+        - `ITM_STRING` (`item`)
+        - `ITM_NUMBER` (`item`)
+
+This represents a bit of code in the AST. It can be transformed in code_life
+objects (instructions and expressions) using the `to_run` for instructions and
+`to_run_expr` for expressions.
+
+The default behaviour of `to_run` is to return the expression from `to_run_expr`
+as an instruction is an instruction (`EXPR` inherit from `INSTR`).
+
+# `ITM_TYPE` #
+
+- `ITM_TYPE` (`item`)
+    - `ITM_TYPE_MULTI` (`item`)
+    - `ITM_TYPE_MONO` (`item`)
+        - `ITM_TYPE_GENERIC_ELT` (`item`)
+        - `ITM_TYPE_BLOCK` (`item`)
+        - `ITM_TYPE_SIMPLE` (`item`)
+            - `ITM_TYPE_PARAMETER` (`item`)
+            - `ITM_TYPE_STYLE` (`item`)
+                - `ITM_TYPE_GENERIC` (`item`)
+
+
+
+
+Code Life Types
+---------------
+
+# `INSTR` #
+
+- `INSTR` (`code_life`)
+    - `FORALL_DATA` (`external`)
+    - `CALL_NULL` (`external`)
+    - `PUT_TO` (`external`)
+    - `LOOP_END` (`code_life`)
+    - `COP_LOCK` (`code_life`)
+    - `LIST` (`code_life`)
+    - `CALL_SLOT` (`code_life`)
+    - `PUSH` (`code_life`)
+    - `COP_UNLOCK` (`code_life`)
+    - `NOP` (`code_life`)
+    - `LOOP` (`code_life`)
+    - `SWITCH` (`code_life`)
+    - `WRITE` (`code_life`)
+        - `PUT_TO` (`external`)
+        - `WRITE_SLOT` (`code_life`)
+        - `WRITE_LOCAL` (`code_life`)
+        - `WRITE_GLOBAL` (`code_life`)
+    - `NODE` (`dispatcher`)
+        - `NODE_TYPE` (`dispatcher`)
+        - `NODE_STYLE` (`dispatcher`)
+    - `EXPR` (`code_life`)
+        - ...
+
+This is an instruction. Instructions can be generated in the target language
+using the `genere` slot and they are subject to the execution pass through the
+`execute` slot.
+
+When executed, an instruction returns a better version of itself as a return
+value, or return `NULL` in case it wishes to remove itself.
+
+TODO: What is `remove` exactly?
+
+# `EXPR` #
+
+- `EXPR` (`code_life`)
+    - `CAST` (`code_life`)
+    - `RESULT` (`code_life`)
+    - `EXPR_MULTIPLE` (`code_life`)
+    - `READ` (`code_life`)
+        - `READ_SLOT` (`code_life`)
+        - `READ_LOCAL` (`code_life`)
+        - `READ_GLOBAL` (`code_life`)
+    - `EXTERNAL_C` (`external`)
+    - `SIZE_OF` (`external`)
+    - `GET_TYPE_ID` (`external`)
+    - `ITEM` (`external`)
+    - `IS_EXPANDED` (`external`)
+    - `EXPR_BINARY_CMP` (`external/comparison`), contains basic operators for
+      `>=`, `>`, `<`, `<=`, `=`, `!=`
+    - `EXPR_BINARY_LOGIC` (`external/logic`), contains basic operators for
+      `&`, `&&`, `|`, `||`
+    - `EXPR_UNARY_LOGIC` (`external/logic`), contains basic operator `!`
+    - `EXPR_UNARY` (`external/arithmetic`), contains basic operator `~` (not)
+       and `-` (minus),
+    - `EXPR_BINARY` (`external/arithmetic`), contains basic operator `^` (xor),
+      `%` (mod), `+`, `-`, `/`, `*`, `&`, `|`, `<<`, `>>`
+    - `CONSTANT` (`constant`)
+        - `STRING_CST` (`constant`)
+        - `PROTOTYPE_CST` (`constant`)
+        - `CHARACTER_CST` (`constant`)
+        - `INTEGER_CST` (`constant`)
+        - `REAL_CST` (`constant`)
+        - `NATIVE_ARRAY_CHARACTER_CST` (`constant`)
+
+
+This is an instruction and represents an expression. It does have a
+`static_type`. As for all instructions, it is subject to the excuting pass
+through the `execute` slot.
+
+TODO: What are `execute_link` and `execute_unlink`
+
+# `LIST` #
+
+This is a list of instructions (`INSTR`) and is itself an instruction. This can
+be either a list in Lisaac (in braces), a block (curly braces) or contract
+blocks (brackets). It has an embedded index that point to a specific
+instruction.
+
+TODO: understand how the list return its expressions, given that they are
+expressions and not instructions, and that there can be more than one
+expression. Is it through `RESULT`?
+
+## Execution ##
+
+When executed, it puts itself as `list_current` for the time of its execution
+and restore the old value afterwards. Then, for all the instructions it
+contains, it excutes the instruction and replace the new instruction (returned
+by `execute`) in the list.
+
+The new list (which is the same but modified on the fly) is returned from the
+execution step except in the following optimizing cases:
+
+- When there is a call on NULL, all following instructions are removed as they
+  are not expected to be executed
+- When there is a `list_current` (a parent list). The list move all its
+  instructions in the `list_current` just before the child list.
+
+# `PROFIL` #
+
+A profil is a function signature in C. It represents a slot in Lisaac that might
+be customized with generic parameters or for optimization purposes.
+
+A profil can be living or dead in the `PROFIL_LIST`. Just look at the
+documentation on the executing pass for more information about `PROFIL_LIST`.
+
+A profil contains `code` which is a `LIST`. This is the implementation of the
+function. When executed through the `execute` slot, it forward the message
+calling `code.execute`. And the resulting instruction has better to still be
+a `LIST`
+
+`execute_recursive` is not called by `PROFIL_LIST` but by `PROFIL.set_life`
+only when in a recursive pass.
+
diff --git a/src/code_life/instr.li b/src/code_life/instr.li
index b081bf9..760cf8f 100644
--- a/src/code_life/instr.li
+++ b/src/code_life/instr.li
@@ -49,6 +49,8 @@ Section Public
 
   - my_copy:SELF <-
   // TODO: Documentation
+  // Would be to copy the instruction and make sure memory is allocated
+  // correctly. Not really sure though.
   // Deferred
   (
     debug_display;
@@ -62,9 +64,15 @@ Section Public
 
   - cmp other:INSTR :BOOLEAN := FALSE;
   // TODO: Documentation
+  // Not redefined, Not used as far as I can grep. Seems unused.
 
   - i_am_the_last i:INSTR :BOOLEAN <- (i = Self);
   // TODO: Documentation
+  // It seems to have something to do with the last expression of a list that
+  // is also a return value. Perhaps it checks whether the instruction i is the
+  // returned instruction of an instruction.
+  // Redefined in LIST, SWITCH and PROFIL
+  // Used in LIST, CALL_SLOT, SWITCH and PROFIL
 
   - execute:INSTR <-
   // TODO: Documentation
@@ -128,6 +136,7 @@ Section Public
 
   - simplify_type v:VARIABLE <-
   // TODO: Documentation
+  // Not redefined anywhere, used in LIST, READ and WRITE
   ( + tmp_type:TYPES_TMP;
 
     ((! v.is_static) && {! v.type.is_strict}).if {
diff --git a/src/code_life/list.li b/src/code_life/list.li
index b264f6e..7a19baa 100644
--- a/src/code_life/list.li
+++ b/src/code_life/list.li
@@ -246,7 +246,11 @@ Section Public
     execute_case;
 
     (list_current != NULL).if {
-      // Fusion list.
+      // Merge the child list in the parent list
+      //
+      // Optimization: don't copy the last instruction but instead return it
+      // so it avoid shifting all elements of 1 position before shifting them
+      // back because the list is no longer there.
       (is_empty).if_false {
         lower.to (upper-1) do { j:INTEGER;
           list_current.insert_before (item j);
@@ -410,6 +414,7 @@ Section Public
 Section Private
 
   - add_local tab:FAST_ARRAY(LOCAL) in buf:STRING <-
+  // Generate C code to add locals
   ( + loc:LOCAL;
     + t:TYPE_FULL;
     + cur:INTEGER;
diff --git a/src/hierarchy.sh b/src/hierarchy.sh
new file mode 100755
index 0000000..cbc2782
--- /dev/null
+++ b/src/hierarchy.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+
+cd "`dirname "$0"`"
+
+op_markdown=false
+
+while true; do
+  case "$1" in
+    -h)
+      echo "`basename "$0"` -h"
+      echo "`basename "$0"` [OPTIONS ...] [TYPE ...]"
+      echo
+      echo "Print type hierarchy starting from the types given or the root of the"
+      echo "hierarchy tree detected by the script. The resulting output is"
+      echo "compatible with the markdown syntax."
+      echo
+      echo "-m      Markdown Syntax"
+      echo
+      exit 0
+      ;;
+    -m)
+      op_markdown=true
+      ;;
+    *)
+      break;
+  esac
+  shift
+done
+
+inheritance="$(find . -name "*.li" | \
+  xargs grep '[+-] parent_' | \
+  sed -r 's/^.*\/([^\/]*)\.li:.*[^A-Z0-9_]([A-Z][A-Z0-9_]*)[^A-Z0-9_].*$/\1 \2/' | \
+  tr a-z A-Z)"
+
+#echo "$inheritance"
+
+roots=$(echo $@ | tr a-z A-Z)
+
+if [ -z "$roots" ]; then
+
+  all_types="$(find . -name "*.li" | \
+    xargs -n 1 basename | \
+    cut -d. -f1 | \
+    tr a-z A-Z | \
+    sort | uniq)"
+
+  roots="$all_types"
+
+  while read line; do
+    foo=($line)
+    child="${foo[0]}"
+    parent="${foo[1]}"
+    if grep "^$parent$" <<<"$all_types" >/dev/null; then
+      #echo "Remove $child from roots because its parent $parent exists"
+      roots="$(grep -v "^$child$" <<<"$roots")"
+    fi
+  done <<<"$inheritance"
+
+fi
+
+parse(){
+  local parent=$1
+  local indent="$2"
+  local dir
+  dir=$(find . -name "`tr A-Z a-z <<<"${parent}"`.li" | xargs -n 1 dirname | cut -d/ -f2-)
+  if [ . = "$dir" ] || [ -z "$dir" ]; then
+    if $op_markdown; then
+      echo "$indent- \`$parent\`"
+    else
+      echo "$indent- $parent"
+    fi
+  else
+    if $op_markdown; then
+      echo "$indent- \`$parent\` (\`$dir\`)"
+    else
+      echo "$indent- $parent ($dir)"
+    fi
+  fi
+  indent="$indent    "
+  local children=$(echo "$inheritance" | grep " $parent$" | cut -d" " -f1)
+  if [ -n "$children" ]; then
+    for child in $children; do
+      parse $child "$indent"
+    done
+    echo
+  fi
+}
+
+for root in $roots; do
+  parse $root
+done
\ No newline at end of file

-- 
Lisaac compiler



More information about the Lisaac-commits mailing list