even cuter comments
This commit is contained in:
+15
-17
@@ -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
@@ -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
@@ -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
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user