From 3a49b821359f77ecba53a2b4ba242b52b851cb20 Mon Sep 17 00:00:00 2001 From: cozis Date: Sun, 13 Mar 2022 16:28:41 +0100 Subject: [PATCH] even cuter comments --- src/compiler/compile.c | 32 +++++------ src/compiler/parse.c | 51 ++++++++--------- src/objects/heap.c | 117 ++++++++++++++++---------------------- src/runtime/o_staticmap.c | 46 ++++++--------- 4 files changed, 105 insertions(+), 141 deletions(-) diff --git a/src/compiler/compile.c b/src/compiler/compile.c index 268b251..12d4156 100644 --- a/src/compiler/compile.c +++ b/src/compiler/compile.c @@ -26,23 +26,21 @@ ** | You should have received a copy of the GNU General Public License along | ** | with The Noja Interpreter. If not, see . | ** +--------------------------------------------------------------------------+ -*/ - -/* 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 `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`. -** -** 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 possible that the compilation fails -** bacause of internal errors (which usually means "out of memory"). -** +** | 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 | +** | `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`. | +** | | +** | 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 | +** | possible that the compilation fails bacause of internal errors (which | +** | usually means "out of memory"). | +** +--------------------------------------------------------------------------+ */ #include diff --git a/src/compiler/parse.c b/src/compiler/parse.c index 8101bf1..fc1eefd 100644 --- a/src/compiler/parse.c +++ b/src/compiler/parse.c @@ -26,33 +26,30 @@ ** | You should have received a copy of the GNU General Public License along | ** | with The Noja Interpreter. If not, see . | ** +--------------------------------------------------------------------------+ -*/ - -/* 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 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 and `parse_while_statement` parses while statements. -** These functions call each other recursively to parse the source -** and build the abstract syntax tree (AST) that can be then compiled -** into bytecode. If at any point the parsing fails because of an -** external or internal error, then the error is reported and the parsing -** is aborted. -** -** Since the nodes of the AST always have the same lifetime (they're -** 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 routines can allocate memory if it need it but doesn't need -** to free it if an error occurres. -** -** 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. -** +** | 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 | +** | 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 | +** | and `parse_while_statement` parses while statements. These functions | +** | call each other recursively to parse the source and build the abstract | +** | syntax tree (AST) that can be then compiled into bytecode. If at any | +** | point the parsing fails because of an external or internal error, then | +** | the error is reported and the parsing is aborted. | +** | | +** | Since the nodes of the AST always have the same lifetime (they're | +** | 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 | +** | routines can allocate memory if it need it but doesn't need to free it | +** | if an error occurres. | +** | | +** | 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 diff --git a/src/objects/heap.c b/src/objects/heap.c index a84234d..fc127f5 100644 --- a/src/objects/heap.c +++ b/src/objects/heap.c @@ -25,75 +25,54 @@ ** | | ** | You should have received a copy of the GNU General Public License along | ** | with The Noja Interpreter. If not, see . | -** +--------------------------------------------------------------------------+ -*/ - -/* WHAT IS THIS FILE? -** This is the implementation of the "Heap", an -** object that provides the rest of the program -** with memory and manages it by claiming it back -** implicitly when it's not in use anymore. To -** determine which memory is used or not, the -** heap system must be aware of the object graph. -** This is the reason why the Heap is tightly -** coupled to the object model. -** -** HOW DOES IT WORK? -** The collection algorithm is move-and-compact. -** The allocator is a bump-pointer allocator. -** When the base pool of memory is filled up, -** further allocations are forwarded to the -** stdlib's malloc, but are kept track of by -** putting them in a linked list. When the parent -** system decides to free up some memory, a new -** heap is allocated and the live objects are -** moved to it, then the old heap is freed. The -** references between live objects are updated -** when moving them. -** Some objects implement destructors that must -** be called when a new heap is allocated and -** they're not moved to it. An auxiliary list -** of allocated objects with destructors is stored -** alongside the heap. When the live objects -** are moved and the ones to be destroyed are -** left in the old one, the list of objects with -** destructors is iterated over and the objects -** in it that weren't moved are destroied and -** removed from the list. This approach becomes -** linearly slower with the number of allocated -** objects with destructors, but it's assumed -** that not many of them implement them. -** -** HOW ARE POINTERS UPDATED? -** Basically, when an object is moved from the -** old to the new heap, the location of the object -** in the old heap is overwritten with a placeholder -** object that holds the new location. Then all -** of it's references are iterated over and if -** they refer to placeholders they're updated -** with the new location of the object. If the -** 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. -** +** +--------------------------------------------------------------------------+ +** | | +** | WHAT IS THIS FILE? | +** | This is the implementation of the "Heap", an object that provides the | +** | rest of the program with memory and manages it by claiming it back | +** | implicitly when it's not in use anymore. To determine which memory is | +** | used or not, the heap system must be aware of the object graph. This is | +** | the reason why the Heap is tightly coupled to the object model. | +** | | +** | HOW DOES IT WORK? | +** | The collection algorithm is move-and-compact. The allocator is a | +** | bump-pointer allocator. When the base pool of memory is filled up, | +** | further allocations are forwarded to the stdlib's malloc, but are kept | +** | track of by putting them in a linked list. When the parent system decides| +** | to free up some memory, a new heap is allocated and the live objects are | +** | moved to it, then the old heap is freed. The references between live | +** | objects are updated when moving them.Some objects implement destructors | +** | that must be called when a new heap is allocated and they're not moved | +** | to it. An auxiliary list of allocated objects with destructors is stored | +** | alongside the heap. When the live objects are moved and the ones to be | +** | destroyed are left in the old one, the list of objects with destructors | +** | is iterated over and the objects in it that weren't moved are destroied | +** | and removed from the list. This approach becomes linearly slower with | +** | the number of allocated objects with destructors, but it's assumed that | +** | not many of them implement them. | +** | | +** | HOW ARE POINTERS UPDATED? | +** | Basically, when an object is moved from the old to the new heap, the | +** | location of the object in the old heap is overwritten with a placeholder | +** | object that holds the new location. Then all of it's references are | +** | iterated over and if they refer to placeholders they're updated with the | +** | new location of the object. If the 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 #include diff --git a/src/runtime/o_staticmap.c b/src/runtime/o_staticmap.c index 735226c..5c5a79a 100644 --- a/src/runtime/o_staticmap.c +++ b/src/runtime/o_staticmap.c @@ -26,35 +26,25 @@ ** | You should have received a copy of the GNU General Public License along | ** | with The Noja Interpreter. If not, see . | ** +--------------------------------------------------------------------------+ +** | 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 | +** | src/objects folder.) | +** | | +** | THE STATIC MAP OBJECT | +** | The statis map is a read-only collection of objects. You can see 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 | +** | accessed, a lookup is performed into the array. Something to note is that| +** | the array is converted to noja objects lazily when they are accessed, | +** | which makes the start-up times lower than a general purpose map. | +** +--------------------------------------------------------------------------+ +** | NOTES: | +** | - Only strings can be keys. There is no intrinsic reason why | +** | it should be like that, it's just simpler. | +** +--------------------------------------------------------------------------+ */ - -/* - * - * -- 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 src/objects folder.) - * ------------------------------------------------------------------ - * - * -- THE STATIC MAP OBJECT ----------------------------------------- - * The statis map is a read-only collection of objects. You can see - * 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 - * accessed, a lookup is performed into the array. Something to note - * is that the array is converted to noja objects lazily when they - * 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 #include #include "../runtime/runtime.h"