Skip to content

Commit

Permalink
Added mecha-style comment docs to a bunch of headers
Browse files Browse the repository at this point in the history
  • Loading branch information
Ratstail91 committed Jul 20, 2023
1 parent 3d7d117 commit cdfe17a
Show file tree
Hide file tree
Showing 20 changed files with 1,165 additions and 59 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ bin/
*.stackdump
*.tb
*.filters
[Dd]ocs/

#Shell files
*.bat
Expand Down
17 changes: 17 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,23 @@ $(TOY_OUTDIR):
install-tools:
cp -rf tools/toylang.vscode-highlighting ~/.vscode/extensions

#utils
build-mecha: $(TOY_OUTDIR)
g++ -o $(TOY_OUTDIR)/mecha tools/mecha.cpp

build-docs: build-mecha
$(TOY_OUTDIR)/mecha $(wildcard source/*.h)

docs:
mkdir docs

move-docs: docs
mv -u $(wildcard source/*.md) docs

documentation:
$(MAKE) build-docs
$(MAKE) move-docs

.PHONY: clean

clean:
Expand Down
1 change: 1 addition & 0 deletions source/toy_ast_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,5 @@ union Toy_private_node {
Toy_NodeImport import;
};

//see toy_parser.h for more documentation on this function
TOY_API void Toy_freeASTNode(Toy_ASTNode* node);
63 changes: 58 additions & 5 deletions source/toy_common.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
#pragma once

/*!
# toy_common.h
This file is generally included in most header files within Toy, as it is where the TOY_API macro is defined. It also has some utilities intended for use only by the repl.
## Defined Macros
!*/

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#define TOY_VERSION_MAJOR 1
#define TOY_VERSION_MINOR 1
#define TOY_VERSION_PATCH 6
#define TOY_VERSION_BUILD Toy_private_version_build()
/*!
### TOY_API
This definition of this macro is platform-dependant, and used to enable cross-platform compilation of shared and static libraries.
!*/

//platform/compiler-specific instructions
#if defined(__linux__) || defined(__MINGW32__) || defined(__GNUC__)

#define TOY_API extern
Expand All @@ -28,8 +36,53 @@

#endif

/*!
### TOY_VERSION_MAJOR
The current major version of Toy. This value is embedded into the bytecode, and the interpreter will refuse to run bytecode with a major version that does not match it’s own version.
This value MUST fit into an unsigned char.
!*/

#define TOY_VERSION_MAJOR 1

/*!
### TOY_VERSION_MINOR
The current minor version of Toy. This value is embedded into the bytecode, and the interpreter will refuse to run bytecode with a minor version that is greater than its own minor version.
This value MUST fit into an unsigned char.
!*/

#define TOY_VERSION_MINOR 1

/*!
### TOY_VERSION_PATCH
The current patch version of Toy. This value is embedded into the bytecode.
This value MUST fit into an unsigned char.
!*/

#define TOY_VERSION_PATCH 6

/*!
### TOY_VERSION_BUILD
The current build version of Toy. This value is embedded into the bytecode.
This evaluates to a c-string, which contains build information such as compilation date and time of the interpreter. When in verbose mode, the compiler will display a warning if the build version of the bytecode does not match the build version of the interpreter.
This macro may also be used to store additonal information about forks of the Toy codebase.
!*/

#define TOY_VERSION_BUILD Toy_private_version_build()
TOY_API const char* Toy_private_version_build();

/*
The following code is intended only for use within the repl.
*/

//for processing the command line arguments in the repl
typedef struct {
bool error;
Expand Down
18 changes: 9 additions & 9 deletions source/toy_compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ static int writeLiteralTypeToCache(Toy_LiteralArray* literalCache, Toy_Literal l
}

//optimisation: check if exactly this literal array exists
int index = Toy_findLiteralIndex(literalCache, literal);
int index = Toy_private_findLiteralIndex(literalCache, literal);
if (index < 0) {
index = Toy_pushLiteralArray(literalCache, literal);
}
Expand All @@ -74,7 +74,7 @@ static int writeNodeCompoundToCache(Toy_Compiler* compiler, Toy_ASTNode* node) {
switch(node->compound.nodes[i].pair.left->type) {
case TOY_AST_NODE_LITERAL: {
//keys are literals
int key = Toy_findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].pair.left->atomic.literal);
int key = Toy_private_findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].pair.left->atomic.literal);
if (key < 0) {
key = Toy_pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].pair.left->atomic.literal);
}
Expand Down Expand Up @@ -103,7 +103,7 @@ static int writeNodeCompoundToCache(Toy_Compiler* compiler, Toy_ASTNode* node) {
switch(node->compound.nodes[i].pair.right->type) {
case TOY_AST_NODE_LITERAL: {
//values are literals
int val = Toy_findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].pair.right->atomic.literal);
int val = Toy_private_findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].pair.right->atomic.literal);
if (val < 0) {
val = Toy_pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].pair.right->atomic.literal);
}
Expand Down Expand Up @@ -142,7 +142,7 @@ static int writeNodeCompoundToCache(Toy_Compiler* compiler, Toy_ASTNode* node) {
switch(node->compound.nodes[i].type) {
case TOY_AST_NODE_LITERAL: {
//values
int val = Toy_findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].atomic.literal);
int val = Toy_private_findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].atomic.literal);
if (val < 0) {
val = Toy_pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].atomic.literal);
}
Expand Down Expand Up @@ -230,7 +230,7 @@ static int writeNodeCollectionToCache(Toy_Compiler* compiler, Toy_ASTNode* node)

static int writeLiteralToCompiler(Toy_Compiler* compiler, Toy_Literal literal) {
//get the index
int index = Toy_findLiteralIndex(&compiler->literalCache, literal);
int index = Toy_private_findLiteralIndex(&compiler->literalCache, literal);

if (index < 0) {
if (TOY_IS_TYPE(literal)) {
Expand Down Expand Up @@ -550,7 +550,7 @@ static Toy_Opcode Toy_writeCompilerWithJumps(Toy_Compiler* compiler, Toy_ASTNode
}

//write each piece of the declaration to the bytecode
int identifierIndex = Toy_findLiteralIndex(&compiler->literalCache, node->varDecl.identifier);
int identifierIndex = Toy_private_findLiteralIndex(&compiler->literalCache, node->varDecl.identifier);
if (identifierIndex < 0) {
identifierIndex = Toy_pushLiteralArray(&compiler->literalCache, node->varDecl.identifier);
}
Expand Down Expand Up @@ -597,7 +597,7 @@ static Toy_Opcode Toy_writeCompilerWithJumps(Toy_Compiler* compiler, Toy_ASTNode
Toy_Literal fnLiteral = ((Toy_Literal){ .as = { .generic = fnCompiler }, .type = TOY_LITERAL_FUNCTION_INTERMEDIATE});

//push the name
int identifierIndex = Toy_findLiteralIndex(&compiler->literalCache, node->fnDecl.identifier);
int identifierIndex = Toy_private_findLiteralIndex(&compiler->literalCache, node->fnDecl.identifier);
if (identifierIndex < 0) {
identifierIndex = Toy_pushLiteralArray(&compiler->literalCache, node->fnDecl.identifier);
}
Expand Down Expand Up @@ -653,7 +653,7 @@ static Toy_Opcode Toy_writeCompilerWithJumps(Toy_Compiler* compiler, Toy_ASTNode
}

//write each argument to the bytecode
int argumentsIndex = Toy_findLiteralIndex(&compiler->literalCache, node->fnCall.arguments->fnCollection.nodes[i].atomic.literal);
int argumentsIndex = Toy_private_findLiteralIndex(&compiler->literalCache, node->fnCall.arguments->fnCollection.nodes[i].atomic.literal);
if (argumentsIndex < 0) {
argumentsIndex = Toy_pushLiteralArray(&compiler->literalCache, node->fnCall.arguments->fnCollection.nodes[i].atomic.literal);
}
Expand All @@ -675,7 +675,7 @@ static Toy_Opcode Toy_writeCompilerWithJumps(Toy_Compiler* compiler, Toy_ASTNode

//push the argument COUNT to the top of the stack
Toy_Literal argumentsCountLiteral = TOY_TO_INTEGER_LITERAL(node->fnCall.argumentCount); //argumentCount is set elsewhere to support dot operator
int argumentsCountIndex = Toy_findLiteralIndex(&compiler->literalCache, argumentsCountLiteral);
int argumentsCountIndex = Toy_private_findLiteralIndex(&compiler->literalCache, argumentsCountLiteral);
if (argumentsCountIndex < 0) {
argumentsCountIndex = Toy_pushLiteralArray(&compiler->literalCache, argumentsCountLiteral);
}
Expand Down
44 changes: 41 additions & 3 deletions source/toy_compiler.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
#pragma once

/*!
# toy_compiler.h
This header defines the compiler structure, which is used to transform abstract syntax trees into usable intermediate bytecode. There are two steps to generating bytecode - the writing step, and the collation step.
During the writing step, the core of the program is generated, along with a series of literals representing the values within the program; these values are compressed and flattened into semi-unrecognizable forms. If the same literal is used multiple times in a program, such as a variable name, the name itself is replaced by a reference to the flattened literals within the cache.
During the collation step, everything from the core program’s execution instructions, the flattened literals, the functions (which have their own sections and protocols within the bytecode) and version information (such as the macros defined in toy_common.h) are all combined into a single buffer of bytes, known as bytecode. This bytecode can then be safely saved to a file or immediately executed.
!*/

#include "toy_common.h"
#include "toy_opcodes.h"
#include "toy_ast_node.h"
#include "toy_literal_array.h"

//the compiler takes the nodes, and turns them into sequential chunks of bytecode, saving literals to an external array
typedef struct Toy_Compiler {
Toy_LiteralArray literalCache;
unsigned char* bytecode;
Expand All @@ -14,9 +23,38 @@ typedef struct Toy_Compiler {
bool panic;
} Toy_Compiler;

/*!
## Define Functions
Executing the following functions out-of-order causes undefiend behaviour.
!*/

/*!
### void Toy_initCompiler(Toy_Compiler* compiler)
This function initializes the given compiler.
!*/
TOY_API void Toy_initCompiler(Toy_Compiler* compiler);

/*!
### void Toy_writeCompiler(Toy_Compiler* compiler, Toy_ASTNode* node)
This function writes the given `node` argument to the compiler. During the writing step, this function may be called repeatedly, with a stream of results from `Toy_scanParser()`, until `Toy_scanParser()` returns `NULL`.
!*/
TOY_API void Toy_writeCompiler(Toy_Compiler* compiler, Toy_ASTNode* node);
TOY_API void Toy_freeCompiler(Toy_Compiler* compiler);

//embed the header, data section, code section, function section, etc.
/*!
### unsigned char* Toy_collateCompiler(Toy_Compiler* compiler, size_t* size)
This function returns a buffer of bytes, known as "bytecode", created from the given compiler; it also stores the size of the bytecode in the variable pointed to by `size`.
Calling `Toy_collateCompiler()` multiple times on the same compiler will produce undefined behaviour.
!*/
TOY_API unsigned char* Toy_collateCompiler(Toy_Compiler* compiler, size_t* size);

/*!
### void Toy_freeCompiler(Toy_Compiler* compiler)
This function frees a compiler. Calling this on a compiler which has not been collated will free that compiler as expected - anything written to it will be lost.
!*/
TOY_API void Toy_freeCompiler(Toy_Compiler* compiler);
68 changes: 66 additions & 2 deletions source/toy_drive_system.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,76 @@
#pragma once

/*!
# toy_drive_system.h
When accessing the file system through toy (such as with the runner library), it's best practice to utilize Toy's built-in drive system - this system (tries to) prevent malicious accessing of files outside of the designated folders. It does this by causing an error when a script tries to access a parent directory.
To use the drive system, first you must designate specific folders which can be accessed, like so:
```c
#include "toy_drive_system.h"
int main(int argc, char* argv[]) {
//the drive system uses a LiteralDictionary, which must be initialized with this
Toy_initDriveSystem();
Toy_setDrivePath("scripts", "assets/scripts");
Toy_setDrivePath("sprites", "assets/sprites");
Toy_setDrivePath("fonts", "assets/fonts");
//TODO: do you stuff here
//clean up the drive dictionary when you're done
Toy_freeDriveSystem();
return 0;
}
```
This utility is intended mainly for libraries to use - as such, the core of Toy does not utilize it.
### Implementation Details
The drive system uses a Toy's Dictionary structure to store the mappings between keys and values - this dictionary object is a static global which persists for the lifetime of the program.
!*/

#include "toy_common.h"

#include "toy_literal.h"
#include "toy_interpreter.h"

//file system API - these need to be set by the host
/*!
## Defined Functions
!*/

/*!
### void Toy_initDriveSystem()
This function initializes the drive system.
!*/
TOY_API void Toy_initDriveSystem();

/*!
### void Toy_freeDriveSystem()
This function cleans up after the drive system is no longer needed.
!*/
TOY_API void Toy_freeDriveSystem();

//file system API - for use with libs
/*!
### void Toy_setDrivePath(char* drive, char* path)
This function sets a key-value pair in the drive system. It uses C strings, since its intended to be called directly from `main()`.
!*/
TOY_API void Toy_setDrivePath(char* drive, char* path);

/*!
### Toy_Literal Toy_getDrivePathLiteral(Toy_Interpreter* interpreter, Toy_Literal* drivePathLiteral)
This function, when given a string literal of the correct format, will return a new string literal containing the relative filepath to a specified file.
The correct format is `drive:/path/to/filename`, where `drive` is a drive that was specified with `Toy_setDrivePath()`.
On failure, this function returns a null literal.
!*/
TOY_API Toy_Literal Toy_getDrivePathLiteral(Toy_Interpreter* interpreter, Toy_Literal* drivePathLiteral);
Loading

0 comments on commit cdfe17a

Please sign in to comment.