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');
</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"
int main(int argc, char* argv[]) {
//the drive system uses a LiteralDictionary, which must be initialized with this
Toy_initDriveSystem();
//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");
Toy_setDrivePath("scripts", "assets/scripts");
Toy_setDrivePath("sprites", "assets/sprites");
Toy_setDrivePath("fonts", "assets/fonts");
//TODO: do you stuff here
//TODO: do you stuff here
//clean up the drive dictionary when you're done
Toy_freeDriveSystem();
//clean up the drive dictionary when you're done
Toy_freeDriveSystem();
return 0;
return 0;
}
```

View File

@@ -91,7 +91,7 @@ Sometimes, native functions will receive `Toy_Literal` identifiers instead of th
```c
Toy_Literal foobarIdn = 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
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
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
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
toy: $(OUTDIR)
$(MAKE) -C Toy/source
$(MAKE) -C Toy/source
$(OUTDIR):
mkdir $(OUTDIR)
mkdir $(OUTDIR)
```
Finally, link against the outputted library, with the source directory as the location of the header files.
```make
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.

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:
```c
case TOY_OP_PRINT:
if (!execPrint(interpreter)) {
return;
}
break;
case TOY_OP_PRINT:
if (!execPrint(interpreter)) {
return;
}
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).
```c
static bool execPrint(Toy_Interpreter* interpreter) {
//get the top literal
Toy_Literal lit = Toy_popLiteralArray(&interpreter->stack);
//get the top literal
Toy_Literal lit = Toy_popLiteralArray(&interpreter->stack);
//if the top literal is an identifier, get it's value
Toy_Literal idn = lit;
if (TOY_IS_IDENTIFIER(lit) && Toy_parseIdentifierToValue(interpreter, &lit)) {
Toy_freeLiteral(idn);
}
//if the top literal is an identifier, get it's value
Toy_Literal idn = lit;
if (TOY_IS_IDENTIFIER(lit) && Toy_parseIdentifierToValue(interpreter, &lit)) {
Toy_freeLiteral(idn);
}
//print as a string to the current print method
Toy_printLiteralCustom(lit, interpreter->printOutput);
//print as a string to the current print method
Toy_printLiteralCustom(lit, interpreter->printOutput);
//free the literal
Toy_freeLiteral(lit);
//free the literal
Toy_freeLiteral(lit);
//continue the loop
return true;
//continue the loop
return true;
}
```
@@ -275,7 +275,7 @@ As in most programming languages, variables can be represented by names specifie
```c
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...
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
//a utility structure for storing the native C functions
typedef struct Natives {
char* name;
Toy_NativeFn fn;
char* name;
Toy_NativeFn fn;
} Natives;
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
Natives natives[] = {
{"clock", nativeClock},
{NULL, NULL}
};
//the list of available native C functions that can be called from Toy
Natives natives[] = {
{"clock", nativeClock},
{NULL, NULL}
};
//inject each native C functions into the current scope
for (int i = 0; natives[i].name; i++) {
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
}
//inject each native C functions into the current scope
for (int i = 0; natives[i].name; i++) {
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
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.

View File

@@ -21,19 +21,19 @@ The engine proper is invoked with just three lifecycle functions`:
#include "box_engine.h"
int main(int argc, char* argv[]) {
//initialize the drive system
Toy_initDriveSystem();
Toy_setDrivePath("scripts", "assets/scripts");
//initialize the drive system
Toy_initDriveSystem();
Toy_setDrivePath("scripts", "assets/scripts");
//invoke the engine
Box_initEngine("scripts:/init.toy"); //passing in the specified init file
Box_execEngine();
Box_freeEngine();
//invoke the engine
Box_initEngine("scripts:/init.toy"); //passing in the specified init file
Box_execEngine();
Box_freeEngine();
//clean up the drive system when you're done
Toy_freeDriveSystem();
//clean up the drive system when you're done
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()) {
//do this
//do this
}
else {
//otherwise do this
//otherwise do this
}
var i = 0;
while (i < 10) {
print i++;
print 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) {
return [a, b, c];
return [a, b, c];
}
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) {
return rest;
return rest;
}
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) {
print self;
print self;
}
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;
fn p(i, x) {
print x;
print x;
}
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;
fn increment(k, v) {
return v + 1;
return v + 1;
}
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;
fn f(acc, k, v) {
return acc + v;
return acc + v;
}
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;
fn less(a, b) {
return a < b;
return a < b;
}
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
var phonebook: entry = [
"Lucy": ["1234", "Cabbage Ln"],
"Bob": ["5678", "Candy Rd"]
"Lucy": ["1234", "Cabbage Ln"],
"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) {
if (question) {
return int;
}
else {
return float;
}
if (question) {
return int;
}
else {
return float;
}
}
var t = decide(true);