even cuter comments

This commit is contained in:
cozis
2022-03-13 16:28:41 +01:00
parent 4f8aaa7eca
commit 3a49b82135
4 changed files with 105 additions and 141 deletions
+15 -17
View File
@@ -26,23 +26,21 @@
** | You should have received a copy of the GNU General Public License along | ** | You should have received a copy of the GNU General Public License along |
** | with The Noja Interpreter. If not, see <http://www.gnu.org/licenses/>. | ** | with The Noja Interpreter. If not, see <http://www.gnu.org/licenses/>. |
** +--------------------------------------------------------------------------+ ** +--------------------------------------------------------------------------+
*/ ** | WHAT IS THIS FILE? |
** | |
/* WHAT IS THIS FILE? ** | This file implements the routines that transform the AST into a list of |
** ** | bytecodes. The functionalities of this file are exposed through the |
** This file implements the routines that transform the AST ** | `compile` function, that takes as input an `AST` and outputs an |
** into a list of bytecodes. The functionalities of this file ** | `Executable`. |
** are exposed through the `compile` function, that takes as ** | |
** input an `AST` and outputs an `Executable`. ** | The function that does the heavy lifting is `emit_instr_for_node` which |
** ** | walks the tree and writes instructions to the `ExeBuilder`. |
** The function that does the heavy lifting is `emit_instr_for_node` ** | |
** which walks the tree and writes instructions to the `ExeBuilder`. ** | Some semantic errors are catched at this phase, in which case, they are |
** ** | reported by filling out the `error` structure and aborting. It's also |
** Some semantic errors are catched at this phase, in which ** | possible that the compilation fails bacause of internal errors (which |
** case, they are reported by filling out the `error` structure ** | usually means "out of memory"). |
** and aborting. It's also possible that the compilation fails ** +--------------------------------------------------------------------------+
** bacause of internal errors (which usually means "out of memory").
**
*/ */
#include <assert.h> #include <assert.h>
+24 -27
View File
@@ -26,33 +26,30 @@
** | You should have received a copy of the GNU General Public License along | ** | You should have received a copy of the GNU General Public License along |
** | with The Noja Interpreter. If not, see <http://www.gnu.org/licenses/>. | ** | with The Noja Interpreter. If not, see <http://www.gnu.org/licenses/>. |
** +--------------------------------------------------------------------------+ ** +--------------------------------------------------------------------------+
*/ ** | WHAT IS THIS FILE? |
** | |
/* WHAT IS THIS FILE? ** | This file implements the parser of the language, that transforms `Source`|
** ** | objects into `AST` objects. The functionalities of this file are exposed |
** This file implements the parser of the language, that transforms ** | throigh the `parse` function. |
** `Source` objects into `AST` objects. The functionalities of this ** | |
** file are exposed throigh the `parse` function. ** | It's mainly composed by routines that can each parse specific parts of a |
** ** | noja source string. For example, `parse_expression` parses expressions |
** It's mainly composed by routines that can each parse specific ** | and `parse_while_statement` parses while statements. These functions |
** parts of a noja source string. For example, `parse_expression` ** | call each other recursively to parse the source and build the abstract |
** parses expressions and `parse_while_statement` parses while statements. ** | syntax tree (AST) that can be then compiled into bytecode. If at any |
** These functions call each other recursively to parse the source ** | point the parsing fails because of an external or internal error, then |
** and build the abstract syntax tree (AST) that can be then compiled ** | the error is reported and the parsing is aborted. |
** into bytecode. If at any point the parsing fails because of an ** | |
** external or internal error, then the error is reported and the parsing ** | Since the nodes of the AST always have the same lifetime (they're |
** is aborted. ** | allocated at the same time and die all together), the allocator scheme |
** ** | of choise is a bump-pointer allocator. This way each of the parsing |
** Since the nodes of the AST always have the same lifetime (they're ** | routines can allocate memory if it need it but doesn't need to free it |
** allocated at the same time and die all together), the allocator ** | if an error occurres. |
** scheme of choise is a bump-pointer allocator. This way each of the ** | |
** parsing routines can allocate memory if it need it but doesn't need ** | The parsing routines don't operate directly on the source text, but on |
** to free it if an error occurres. ** | the tokenized version of it. Before parsing a linked list of tokens is |
** ** | produced through the `tokenize` function. |
** The parsing routines don't operate directly on the source text, but ** +--------------------------------------------------------------------------+
** on the tokenized version of it. Before parsing a linked list of
** tokens is produced through the `tokenize` function.
**
*/ */
#include <stdlib.h> #include <stdlib.h>
+47 -68
View File
@@ -26,74 +26,53 @@
** | You should have received a copy of the GNU General Public License along | ** | You should have received a copy of the GNU General Public License along |
** | with The Noja Interpreter. If not, see <http://www.gnu.org/licenses/>. | ** | with The Noja Interpreter. If not, see <http://www.gnu.org/licenses/>. |
** +--------------------------------------------------------------------------+ ** +--------------------------------------------------------------------------+
*/ ** | |
** | WHAT IS THIS FILE? |
/* WHAT IS THIS FILE? ** | This is the implementation of the "Heap", an object that provides the |
** This is the implementation of the "Heap", an ** | rest of the program with memory and manages it by claiming it back |
** object that provides the rest of the program ** | implicitly when it's not in use anymore. To determine which memory is |
** with memory and manages it by claiming it back ** | used or not, the heap system must be aware of the object graph. This is |
** implicitly when it's not in use anymore. To ** | the reason why the Heap is tightly coupled to the object model. |
** determine which memory is used or not, the ** | |
** heap system must be aware of the object graph. ** | HOW DOES IT WORK? |
** This is the reason why the Heap is tightly ** | The collection algorithm is move-and-compact. The allocator is a |
** coupled to the object model. ** | bump-pointer allocator. When the base pool of memory is filled up, |
** ** | further allocations are forwarded to the stdlib's malloc, but are kept |
** HOW DOES IT WORK? ** | track of by putting them in a linked list. When the parent system decides|
** The collection algorithm is move-and-compact. ** | to free up some memory, a new heap is allocated and the live objects are |
** The allocator is a bump-pointer allocator. ** | moved to it, then the old heap is freed. The references between live |
** When the base pool of memory is filled up, ** | objects are updated when moving them.Some objects implement destructors |
** further allocations are forwarded to the ** | that must be called when a new heap is allocated and they're not moved |
** stdlib's malloc, but are kept track of by ** | to it. An auxiliary list of allocated objects with destructors is stored |
** putting them in a linked list. When the parent ** | alongside the heap. When the live objects are moved and the ones to be |
** system decides to free up some memory, a new ** | destroyed are left in the old one, the list of objects with destructors |
** heap is allocated and the live objects are ** | is iterated over and the objects in it that weren't moved are destroied |
** moved to it, then the old heap is freed. The ** | and removed from the list. This approach becomes linearly slower with |
** references between live objects are updated ** | the number of allocated objects with destructors, but it's assumed that |
** when moving them. ** | not many of them implement them. |
** Some objects implement destructors that must ** | |
** be called when a new heap is allocated and ** | HOW ARE POINTERS UPDATED? |
** they're not moved to it. An auxiliary list ** | Basically, when an object is moved from the old to the new heap, the |
** of allocated objects with destructors is stored ** | location of the object in the old heap is overwritten with a placeholder |
** alongside the heap. When the live objects ** | object that holds the new location. Then all of it's references are |
** are moved and the ones to be destroyed are ** | iterated over and if they refer to placeholders they're updated with the |
** left in the old one, the list of objects with ** | new location of the object. If the references don't refer to placeholder |
** destructors is iterated over and the objects ** | objects, then the referred objects are moved too. This is a recursive |
** in it that weren't moved are destroied and ** | process that, when applied to the root object of the program, moves all |
** removed from the list. This approach becomes ** | reachable objects to the new heap and updates the pointers. The |
** linearly slower with the number of allocated ** | complexity of this algorithm is proportional to the number of live |
** objects with destructors, but it's assumed ** | objects. |
** that not many of them implement them. ** | |
** ** | WHAT IS A BUMP-POINTER ALLOCATOR? |
** HOW ARE POINTERS UPDATED? ** | A bump-pointer allocator is a minimal memory management system. A |
** Basically, when an object is moved from the ** | contiguous pool of memory is allocated. On a higher level, allocations |
** old to the new heap, the location of the object ** | are stacked one after another until the pool is all used up. This is done|
** in the old heap is overwritten with a placeholder ** | by having a pointer that points to the first free buffer of the pool. |
** object that holds the new location. Then all ** | Initially, it points to the first byte of the pool. When N bytes are |
** of it's references are iterated over and if ** | requested, the value of the pointer is given to the caller and then it's |
** they refer to placeholders they're updated ** | incremented by the allocated amount. When the pool has less free memory |
** with the new location of the object. If the ** | than what is requested, the allocation fails. |
** references don't refer to placeholder objects, ** +--------------------------------------------------------------------------+
** then the referred objects are moved too. This
** is a recursive process that, when applied to
** the root object of the program, moves all reachable
** objects to the new heap and updates the pointers.
** The complexity of this algorithm is proportional
** to the number of live objects.
**
** WHAT IS A BUMP-POINTER ALLOCATOR?
** A bump-pointer allocator is a minimal memory
** management system. A contiguous pool of memory
** is allocated. On a higher level, allocations
** are stacked one after another until the pool is
** all used up. This is done by having a pointer
** that points to the first free buffer of the pool.
** Initially, it points to the first byte of the pool.
** When N bytes are requested, the value of the
** pointer is given to the caller and then it's
** incremented by the allocated amount. When the
** pool has less free memory than what is requested,
** the allocation fails.
**
*/ */
#include <stdint.h> #include <stdint.h>
#include <assert.h> #include <assert.h>
+18 -28
View File
@@ -26,34 +26,24 @@
** | You should have received a copy of the GNU General Public License along | ** | You should have received a copy of the GNU General Public License along |
** | with The Noja Interpreter. If not, see <http://www.gnu.org/licenses/>. | ** | with The Noja Interpreter. If not, see <http://www.gnu.org/licenses/>. |
** +--------------------------------------------------------------------------+ ** +--------------------------------------------------------------------------+
*/ ** | WHAT IS THIS FILE? |
** | This file implements the "static map" object. The static map object |
/* ** | behaves like a read-only "map". (Note that "implementing an object" means|
* ** | a very specific thing in this interpreter. If you didn't know, check the |
* -- WHAT IS THIS FILE? -------------------------------------------- ** | src/objects folder.) |
* This file implements the "static map" object. The static map ** | |
* object behaves like a read-only "map". (Note that "implementing ** | THE STATIC MAP OBJECT |
* an object" means a very specific thing in this interpreter. If ** | The statis map is a read-only collection of objects. You can see it as |
* you didn't know, check the src/objects folder.) ** | an interface for static arrays. You can define an array of |
* ------------------------------------------------------------------ ** | `StaticMapSlot`s and then wrap it in this object. When the map is |
* ** | accessed, a lookup is performed into the array. Something to note is that|
* -- THE STATIC MAP OBJECT ----------------------------------------- ** | the array is converted to noja objects lazily when they are accessed, |
* The statis map is a read-only collection of objects. You can see ** | which makes the start-up times lower than a general purpose map. |
* it as an interface for static arrays. You can define an array of ** +--------------------------------------------------------------------------+
* `StaticMapSlot`s and then wrap it in this object. When the map is ** | NOTES: |
* accessed, a lookup is performed into the array. Something to note ** | - Only strings can be keys. There is no intrinsic reason why |
* is that the array is converted to noja objects lazily when they ** | it should be like that, it's just simpler. |
* are accessed, which makes the start-up times lower than a general ** +--------------------------------------------------------------------------+
* purpose map.
* ------------------------------------------------------------------
*
* NOTES:
* - This object, unlike the others implemented in src/objects,
* depends on the Runtime objects. This is because it needs
* to be able to create `NativeFuncObject`s.
*
* - Only strings can be keys. There is no intrinsic reason why
* it should be like that, it's just simpler.
*/ */
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>