mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Tweaked tabs-vs-spaces
This commit is contained in:
@@ -25,3 +25,8 @@
|
|||||||
|
|
||||||
gtag('config', 'G-57STKDE8LE');
|
gtag('config', 'G-57STKDE8LE');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!-- tweak for markdown layouts -->
|
||||||
|
<style>
|
||||||
|
* {tab-size: 4;}
|
||||||
|
</style>
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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!
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user