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:
@@ -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.
|
||||
|
||||
@@ -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!
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user