Tweaked tabs-vs-spaces

This commit is contained in:
2025-01-12 11:16:46 +11:00
parent 101833934b
commit 4282268f3d
10 changed files with 82 additions and 77 deletions

View File

@@ -25,3 +25,8 @@
gtag('config', 'G-57STKDE8LE'); gtag('config', 'G-57STKDE8LE');
</script> </script>
<!-- tweak for markdown layouts -->
<style>
* {tab-size: 4;}
</style>

View File

@@ -10,19 +10,19 @@ To use the drive system, first you must designate specific folders which can be
#include "drive_system.h" #include "drive_system.h"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
//the drive system uses a LiteralDictionary, which must be initialized with this //the drive system uses a LiteralDictionary, which must be initialized with this
Toy_initDriveSystem(); Toy_initDriveSystem();
Toy_setDrivePath("scripts", "assets/scripts"); Toy_setDrivePath("scripts", "assets/scripts");
Toy_setDrivePath("sprites", "assets/sprites"); Toy_setDrivePath("sprites", "assets/sprites");
Toy_setDrivePath("fonts", "assets/fonts"); Toy_setDrivePath("fonts", "assets/fonts");
//TODO: do you stuff here //TODO: do you stuff here
//clean up the drive dictionary when you're done //clean up the drive dictionary when you're done
Toy_freeDriveSystem(); Toy_freeDriveSystem();
return 0; return 0;
} }
``` ```

View File

@@ -91,7 +91,7 @@ Sometimes, native functions will receive `Toy_Literal` identifiers instead of th
```c ```c
Toy_Literal foobarIdn = foobar; Toy_Literal foobarIdn = foobar;
if (TOY_IS_IDENTIFIER(foobar) && Toy_parseIdentifierToValue(interpreter, &foobar)) { if (TOY_IS_IDENTIFIER(foobar) && Toy_parseIdentifierToValue(interpreter, &foobar)) {
freeLiteral(foobarIdn); //remember to free the identifier freeLiteral(foobarIdn); //remember to free the identifier
} }
``` ```
@@ -101,7 +101,7 @@ This function sets the function called by the `print` keyword. By default, the f
```c ```c
static void printWrapper(const char* output) { static void printWrapper(const char* output) {
printf("%s\n", output); printf("%s\n", output);
} }
``` ```
@@ -113,7 +113,7 @@ This function sets the function called by the `assert` keyword on failure. By de
```c ```c
static void assertWrapper(const char* output) { static void assertWrapper(const char* output) {
fprintf(stderr, "Assertion failure: %s\n", output); fprintf(stderr, "Assertion failure: %s\n", output);
} }
``` ```
@@ -123,6 +123,6 @@ This function sets the function called when an error occurs within the interpret
```c ```c
static void errorWrapper(const char* output) { static void errorWrapper(const char* output) {
fprintf(stderr, "%s", output); //no newline fprintf(stderr, "%s", output); //no newline
} }
``` ```

View File

@@ -15,17 +15,17 @@ Next, you'll want to run make the from within Toy's `source`, assuming the outpu
```make ```make
toy: $(OUTDIR) toy: $(OUTDIR)
$(MAKE) -C Toy/source $(MAKE) -C Toy/source
$(OUTDIR): $(OUTDIR):
mkdir $(OUTDIR) mkdir $(OUTDIR)
``` ```
Finally, link against the outputted library, with the source directory as the location of the header files. Finally, link against the outputted library, with the source directory as the location of the header files.
```make ```make
all: $(OBJ) toy all: $(OBJ) toy
$(CC) $(CFLAGS) -o $(OUT) $(OBJ) -L$(TOY_OUTDIR) -ltoy $(CC) $(CFLAGS) -o $(OUT) $(OBJ) -L$(TOY_OUTDIR) -ltoy
``` ```
These snippets of makefile are only an example - the repository has a more fully featured set of makefiles which can also produce a usable REPL program. These snippets of makefile are only an example - the repository has a more fully featured set of makefiles which can also produce a usable REPL program.

View File

@@ -237,34 +237,34 @@ Opcodes within the bytecode are 1 byte in length, and specify a single action to
The interpreter is stack-based; most, if not all, the actions are preformed on literals within a specially designated array called `stack`. For example: The interpreter is stack-based; most, if not all, the actions are preformed on literals within a specially designated array called `stack`. For example:
```c ```c
case TOY_OP_PRINT: case TOY_OP_PRINT:
if (!execPrint(interpreter)) { if (!execPrint(interpreter)) {
return; return;
} }
break; break;
``` ```
When the opcode `TOY_OP_PRINT` is encountered, the top literal within the stack is popped off, and printed (more info on literals below). When the opcode `TOY_OP_PRINT` is encountered, the top literal within the stack is popped off, and printed (more info on literals below).
```c ```c
static bool execPrint(Toy_Interpreter* interpreter) { static bool execPrint(Toy_Interpreter* interpreter) {
//get the top literal //get the top literal
Toy_Literal lit = Toy_popLiteralArray(&interpreter->stack); Toy_Literal lit = Toy_popLiteralArray(&interpreter->stack);
//if the top literal is an identifier, get it's value //if the top literal is an identifier, get it's value
Toy_Literal idn = lit; Toy_Literal idn = lit;
if (TOY_IS_IDENTIFIER(lit) && Toy_parseIdentifierToValue(interpreter, &lit)) { if (TOY_IS_IDENTIFIER(lit) && Toy_parseIdentifierToValue(interpreter, &lit)) {
Toy_freeLiteral(idn); Toy_freeLiteral(idn);
} }
//print as a string to the current print method //print as a string to the current print method
Toy_printLiteralCustom(lit, interpreter->printOutput); Toy_printLiteralCustom(lit, interpreter->printOutput);
//free the literal //free the literal
Toy_freeLiteral(lit); Toy_freeLiteral(lit);
//continue the loop //continue the loop
return true; return true;
} }
``` ```
@@ -275,7 +275,7 @@ As in most programming languages, variables can be represented by names specifie
```c ```c
Toy_Literal idn = literal; //cache the literal, just in case it's an identifier Toy_Literal idn = literal; //cache the literal, just in case it's an identifier
if (TOY_IS_IDENTIFIER(literal) && Toy_parseIdentifierToValue(interpreter, &literal)) { //if it is an identifier, parse it... if (TOY_IS_IDENTIFIER(literal) && Toy_parseIdentifierToValue(interpreter, &literal)) { //if it is an identifier, parse it...
Toy_freeLiteral(idn); //always remember to free the original identifier, otherwise you'll have a memory leak! Toy_freeLiteral(idn); //always remember to free the original identifier, otherwise you'll have a memory leak!
} }
``` ```

View File

@@ -62,23 +62,23 @@ Hooks can simply inject native functions into the current scope, or they can do
```c ```c
//a utility structure for storing the native C functions //a utility structure for storing the native C functions
typedef struct Natives { typedef struct Natives {
char* name; char* name;
Toy_NativeFn fn; Toy_NativeFn fn;
} Natives; } Natives;
int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) { int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
//the list of available native C functions that can be called from Toy //the list of available native C functions that can be called from Toy
Natives natives[] = { Natives natives[] = {
{"clock", nativeClock}, {"clock", nativeClock},
{NULL, NULL} {NULL, NULL}
}; };
//inject each native C functions into the current scope //inject each native C functions into the current scope
for (int i = 0; natives[i].name; i++) { for (int i = 0; natives[i].name; i++) {
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn); Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
} }
return 0; return 0;
} }
``` ```
@@ -88,7 +88,7 @@ In some situations, you may find it convenient to call a function written in Toy
```c ```c
TOY_API bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_LiteralArray* arguments, Toy_LiteralArray* returns); TOY_API bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_LiteralArray* arguments, Toy_LiteralArray* returns);
TOY_API bool Toy_callFn (Toy_Interpreter* interpreter, char* name, Toy_LiteralArray* arguments, Toy_LiteralArray* returns); TOY_API bool Toy_callFn (Toy_Interpreter* interpreter, char* name, Toy_LiteralArray* arguments, Toy_LiteralArray* returns);
``` ```
The first argument must be an interpreter. The third argument is a pointer to a `Toy_LiteralArray` containing a list of arguments to pass to the function, and the fourth is a pointer to a `Toy_LiteralArray` where the return values can be stored (an array is used here for a potential future feature). The contents of the argument array are consumed and left in an indeterminate state (but is safe to free), while the returns array always has one value - if the function did not return a value, then it contains a `null` literal. The first argument must be an interpreter. The third argument is a pointer to a `Toy_LiteralArray` containing a list of arguments to pass to the function, and the fourth is a pointer to a `Toy_LiteralArray` where the return values can be stored (an array is used here for a potential future feature). The contents of the argument array are consumed and left in an indeterminate state (but is safe to free), while the returns array always has one value - if the function did not return a value, then it contains a `null` literal.

View File

@@ -21,19 +21,19 @@ The engine proper is invoked with just three lifecycle functions`:
#include "box_engine.h" #include "box_engine.h"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
//initialize the drive system //initialize the drive system
Toy_initDriveSystem(); Toy_initDriveSystem();
Toy_setDrivePath("scripts", "assets/scripts"); Toy_setDrivePath("scripts", "assets/scripts");
//invoke the engine //invoke the engine
Box_initEngine("scripts:/init.toy"); //passing in the specified init file Box_initEngine("scripts:/init.toy"); //passing in the specified init file
Box_execEngine(); Box_execEngine();
Box_freeEngine(); Box_freeEngine();
//clean up the drive system when you're done //clean up the drive system when you're done
Toy_freeDriveSystem(); Toy_freeDriveSystem();
return 0; return 0;
} }
``` ```

View File

@@ -46,19 +46,19 @@ You can control the program flow with either `if`, `while` or `for`. The only fa
``` ```
if (check()) { if (check()) {
//do this //do this
} }
else { else {
//otherwise do this //otherwise do this
} }
var i = 0; var i = 0;
while (i < 10) { while (i < 10) {
print i++; print i++;
} }
for (var i = 0; i < 10; i++) { for (var i = 0; i < 10; i++) {
print i; print i;
} }
``` ```
@@ -70,7 +70,7 @@ Functions are defined with the `fn` keyword, and can take any number of argument
``` ```
fn combine(a, b, c) { fn combine(a, b, c) {
return [a, b, c]; return [a, b, c];
} }
print combine(1, 2, 3); print combine(1, 2, 3);
@@ -80,7 +80,7 @@ Variable number of parameters, called rest parameters, can be passed in as an ar
``` ```
fn combine(...rest) { fn combine(...rest) {
return rest; return rest;
} }
print combine(1, 2, 3); print combine(1, 2, 3);
@@ -92,7 +92,7 @@ Functions can be called using the universal function call syntax, which is just
``` ```
fn printMe(self) { fn printMe(self) {
print self; print self;
} }
array.printMe(); array.printMe();

View File

@@ -104,7 +104,7 @@ This function takes either an array or a dictionary as the `self` argument and a
import standard; import standard;
fn p(i, x) { fn p(i, x) {
print x; print x;
} }
var a = [1, 3, 5]; var a = [1, 3, 5];
@@ -136,7 +136,7 @@ This function takes either an array or a dictionary as the `self` argument, and
import standard; import standard;
fn increment(k, v) { fn increment(k, v) {
return v + 1; return v + 1;
} }
var a = [1, 2, 3]; var a = [1, 2, 3];
@@ -152,7 +152,7 @@ This function takes either an array or a dictionary as the `self` argument, a de
import standard; import standard;
fn f(acc, k, v) { fn f(acc, k, v) {
return acc + v; return acc + v;
} }
var a = [1, 2, 3, 4]; var a = [1, 2, 3, 4];
@@ -172,7 +172,7 @@ This function takes an array as the `self` argument, and a comparison function a
import standard; import standard;
fn less(a, b) { fn less(a, b) {
return a < b; return a < b;
} }
var a = [4, 1, 3, 2]; var a = [4, 1, 3, 2];

View File

@@ -46,8 +46,8 @@ var entry: type = astype [string: [string]];
//define a phonebook which follows the above signature //define a phonebook which follows the above signature
var phonebook: entry = [ var phonebook: entry = [
"Lucy": ["1234", "Cabbage Ln"], "Lucy": ["1234", "Cabbage Ln"],
"Bob": ["5678", "Candy Rd"] "Bob": ["5678", "Candy Rd"]
]; ];
``` ```
@@ -82,12 +82,12 @@ Types are first-class citizens. What this means is that they can be used just li
``` ```
fn decide(question) { fn decide(question) {
if (question) { if (question) {
return int; return int;
} }
else { else {
return float; return float;
} }
} }
var t = decide(true); var t = decide(true);