Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aeb008c684 | |||
| 53012dbce1 | |||
| 4fe57f9562 | |||
| 3ba2e420ea | |||
| c81a139c97 | |||
| 66ea684a90 | |||
| a26a6a56d0 | |||
| ee226ea426 | |||
| 76a0290290 |
@@ -36,7 +36,6 @@ Run `make install-tools` to install a number of tools, including:
|
|||||||
```
|
```
|
||||||
import standard; //for a bunch of utility functions
|
import standard; //for a bunch of utility functions
|
||||||
|
|
||||||
|
|
||||||
print "Hello world"; //"print" is a keyword
|
print "Hello world"; //"print" is a keyword
|
||||||
|
|
||||||
var msg = "foobar"; //declare a variable like this
|
var msg = "foobar"; //declare a variable like this
|
||||||
@@ -60,8 +59,6 @@ var tally = makeCounter();
|
|||||||
print tally(); //1
|
print tally(); //1
|
||||||
print tally(); //2
|
print tally(); //2
|
||||||
print tally(); //3
|
print tally(); //3
|
||||||
|
|
||||||
export tally; //export this variable to the host program
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|||||||
+486
-21
@@ -115,6 +115,351 @@ static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nativeContainsKey(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 2) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _containsKey\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the args
|
||||||
|
Toy_Literal keyLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
//parse to value if needed
|
||||||
|
Toy_Literal selfLiteralIdn = selfLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
|
||||||
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal keyLiteralIdn = keyLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(keyLiteral) && Toy_parseIdentifierToValue(interpreter, &keyLiteral)) {
|
||||||
|
Toy_freeLiteral(keyLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check type
|
||||||
|
if (!(/* TOY_IS_ARRAY(selfLiteral) || */ TOY_IS_DICTIONARY(selfLiteral) )) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to _containsKey\n");
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
Toy_freeLiteral(keyLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(false);
|
||||||
|
if (TOY_IS_DICTIONARY(selfLiteral) && Toy_existsLiteralDictionary( TOY_AS_DICTIONARY(selfLiteral), keyLiteral )) {
|
||||||
|
//return true of it contains the key
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
resultLiteral = TOY_TO_BOOLEAN_LITERAL(true);
|
||||||
|
}
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
Toy_freeLiteral(keyLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeContainsValue(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 2) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _containsValue\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the args
|
||||||
|
Toy_Literal valueLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
//parse to value if needed
|
||||||
|
Toy_Literal selfLiteralIdn = selfLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
|
||||||
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal valueLiteralIdn = valueLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(valueLiteral) && Toy_parseIdentifierToValue(interpreter, &valueLiteral)) {
|
||||||
|
Toy_freeLiteral(valueLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check type
|
||||||
|
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) )) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to _containsValue\n");
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
Toy_freeLiteral(valueLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(false);
|
||||||
|
if (TOY_IS_DICTIONARY(selfLiteral)) {
|
||||||
|
for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) {
|
||||||
|
if (!TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key) && Toy_literalsAreEqual( TOY_AS_DICTIONARY(selfLiteral)->entries[i].value, valueLiteral )) {
|
||||||
|
//return true of it contains the value
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
resultLiteral = TOY_TO_BOOLEAN_LITERAL(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (TOY_IS_ARRAY(selfLiteral)) {
|
||||||
|
for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) {
|
||||||
|
Toy_Literal indexLiteral = TOY_TO_INTEGER_LITERAL(i);
|
||||||
|
Toy_Literal elementLiteral = Toy_getLiteralArray(TOY_AS_ARRAY(selfLiteral), indexLiteral);
|
||||||
|
|
||||||
|
|
||||||
|
if (Toy_literalsAreEqual(elementLiteral, valueLiteral)) {
|
||||||
|
Toy_freeLiteral(indexLiteral);
|
||||||
|
Toy_freeLiteral(elementLiteral);
|
||||||
|
|
||||||
|
//return true of it contains the value
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
resultLiteral = TOY_TO_BOOLEAN_LITERAL(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteral(indexLiteral);
|
||||||
|
Toy_freeLiteral(elementLiteral);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
Toy_freeLiteral(valueLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 2) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _every\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the args
|
||||||
|
Toy_Literal fnLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
//parse to value if needed
|
||||||
|
Toy_Literal selfLiteralIdn = selfLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
|
||||||
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal fnLiteralIdn = fnLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) {
|
||||||
|
Toy_freeLiteral(fnLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check type
|
||||||
|
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to _every\n");
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
Toy_freeLiteral(fnLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//call the given function on each element, based on the compound type
|
||||||
|
if (TOY_IS_ARRAY(selfLiteral)) {
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
//
|
||||||
|
for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) {
|
||||||
|
Toy_Literal indexLiteral = TOY_TO_INTEGER_LITERAL(i);
|
||||||
|
|
||||||
|
Toy_LiteralArray arguments;
|
||||||
|
Toy_initLiteralArray(&arguments);
|
||||||
|
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
|
||||||
|
Toy_pushLiteralArray(&arguments, indexLiteral);
|
||||||
|
|
||||||
|
Toy_LiteralArray returns;
|
||||||
|
Toy_initLiteralArray(&returns);
|
||||||
|
|
||||||
|
Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns);
|
||||||
|
|
||||||
|
//grab the results
|
||||||
|
Toy_Literal lit = Toy_popLiteralArray(&returns);
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&arguments);
|
||||||
|
Toy_freeLiteralArray(&returns);
|
||||||
|
Toy_freeLiteral(indexLiteral);
|
||||||
|
|
||||||
|
//if not truthy
|
||||||
|
if (!TOY_IS_TRUTHY(lit)) {
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_IS_DICTIONARY(selfLiteral)) {
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) {
|
||||||
|
//skip nulls
|
||||||
|
if (TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_LiteralArray arguments;
|
||||||
|
Toy_initLiteralArray(&arguments);
|
||||||
|
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
|
||||||
|
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key);
|
||||||
|
|
||||||
|
Toy_LiteralArray returns;
|
||||||
|
Toy_initLiteralArray(&returns);
|
||||||
|
|
||||||
|
Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns);
|
||||||
|
|
||||||
|
//grab the results
|
||||||
|
Toy_Literal lit = Toy_popLiteralArray(&returns);
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&arguments);
|
||||||
|
Toy_freeLiteralArray(&returns);
|
||||||
|
|
||||||
|
//if not truthy
|
||||||
|
if (!TOY_IS_TRUTHY(lit)) {
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteral(fnLiteral);
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeFilter(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 2) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _filter\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the args
|
||||||
|
Toy_Literal fnLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
//parse to value if needed
|
||||||
|
Toy_Literal selfLiteralIdn = selfLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
|
||||||
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal fnLiteralIdn = fnLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) {
|
||||||
|
Toy_freeLiteral(fnLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check type
|
||||||
|
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to _filter\n");
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
Toy_freeLiteral(fnLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//call the given function on each element, based on the compound type
|
||||||
|
if (TOY_IS_ARRAY(selfLiteral)) {
|
||||||
|
Toy_LiteralArray* result = TOY_ALLOCATE(Toy_LiteralArray, 1);
|
||||||
|
Toy_initLiteralArray(result);
|
||||||
|
|
||||||
|
//
|
||||||
|
for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) {
|
||||||
|
Toy_Literal indexLiteral = TOY_TO_INTEGER_LITERAL(i);
|
||||||
|
|
||||||
|
Toy_LiteralArray arguments;
|
||||||
|
Toy_initLiteralArray(&arguments);
|
||||||
|
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
|
||||||
|
Toy_pushLiteralArray(&arguments, indexLiteral);
|
||||||
|
|
||||||
|
Toy_LiteralArray returns;
|
||||||
|
Toy_initLiteralArray(&returns);
|
||||||
|
|
||||||
|
Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns);
|
||||||
|
|
||||||
|
//grab the results
|
||||||
|
Toy_Literal lit = Toy_popLiteralArray(&returns);
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&arguments);
|
||||||
|
Toy_freeLiteralArray(&returns);
|
||||||
|
Toy_freeLiteral(indexLiteral);
|
||||||
|
|
||||||
|
//if truthy
|
||||||
|
if (TOY_IS_TRUTHY(lit)) {
|
||||||
|
Toy_pushLiteralArray(result, TOY_AS_ARRAY(selfLiteral)->literals[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_ARRAY_LITERAL(result);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_IS_DICTIONARY(selfLiteral)) {
|
||||||
|
Toy_LiteralDictionary* result = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
|
||||||
|
Toy_initLiteralDictionary(result);
|
||||||
|
|
||||||
|
for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) {
|
||||||
|
//skip nulls
|
||||||
|
if (TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_LiteralArray arguments;
|
||||||
|
Toy_initLiteralArray(&arguments);
|
||||||
|
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
|
||||||
|
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key);
|
||||||
|
|
||||||
|
Toy_LiteralArray returns;
|
||||||
|
Toy_initLiteralArray(&returns);
|
||||||
|
|
||||||
|
Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns);
|
||||||
|
|
||||||
|
//grab the results
|
||||||
|
Toy_Literal lit = Toy_popLiteralArray(&returns);
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&arguments);
|
||||||
|
Toy_freeLiteralArray(&returns);
|
||||||
|
|
||||||
|
//if truthy
|
||||||
|
if (TOY_IS_TRUTHY(lit)) {
|
||||||
|
Toy_setLiteralDictionary(result, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_DICTIONARY_LITERAL(result);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteral(fnLiteral);
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
//no arguments
|
//no arguments
|
||||||
if (arguments->count != 2) {
|
if (arguments->count != 2) {
|
||||||
@@ -141,6 +486,7 @@ static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
|
|||||||
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
|
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to _forEach\n");
|
interpreter->errorOutput("Incorrect argument type passed to _forEach\n");
|
||||||
Toy_freeLiteral(selfLiteral);
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
Toy_freeLiteral(fnLiteral);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,6 +655,7 @@ static int nativeMap(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
|
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to _map\n");
|
interpreter->errorOutput("Incorrect argument type passed to _map\n");
|
||||||
Toy_freeLiteral(selfLiteral);
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
Toy_freeLiteral(fnLiteral);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,6 +764,8 @@ static int nativeReduce(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
|
|||||||
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
|
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to _reduce\n");
|
interpreter->errorOutput("Incorrect argument type passed to _reduce\n");
|
||||||
Toy_freeLiteral(selfLiteral);
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
Toy_freeLiteral(defaultLiteral);
|
||||||
|
Toy_freeLiteral(fnLiteral);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,6 +833,122 @@ static int nativeReduce(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 2) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _some\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the args
|
||||||
|
Toy_Literal fnLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
//parse to value if needed
|
||||||
|
Toy_Literal selfLiteralIdn = selfLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
|
||||||
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal fnLiteralIdn = fnLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) {
|
||||||
|
Toy_freeLiteral(fnLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check type
|
||||||
|
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to _some\n");
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
Toy_freeLiteral(fnLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//call the given function on each element, based on the compound type
|
||||||
|
if (TOY_IS_ARRAY(selfLiteral)) {
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
//
|
||||||
|
for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) {
|
||||||
|
Toy_Literal indexLiteral = TOY_TO_INTEGER_LITERAL(i);
|
||||||
|
|
||||||
|
Toy_LiteralArray arguments;
|
||||||
|
Toy_initLiteralArray(&arguments);
|
||||||
|
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
|
||||||
|
Toy_pushLiteralArray(&arguments, indexLiteral);
|
||||||
|
|
||||||
|
Toy_LiteralArray returns;
|
||||||
|
Toy_initLiteralArray(&returns);
|
||||||
|
|
||||||
|
Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns);
|
||||||
|
|
||||||
|
//grab the results
|
||||||
|
Toy_Literal lit = Toy_popLiteralArray(&returns);
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&arguments);
|
||||||
|
Toy_freeLiteralArray(&returns);
|
||||||
|
Toy_freeLiteral(indexLiteral);
|
||||||
|
|
||||||
|
//if not truthy
|
||||||
|
if (TOY_IS_TRUTHY(lit)) {
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_IS_DICTIONARY(selfLiteral)) {
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) {
|
||||||
|
//skip nulls
|
||||||
|
if (TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_LiteralArray arguments;
|
||||||
|
Toy_initLiteralArray(&arguments);
|
||||||
|
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
|
||||||
|
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key);
|
||||||
|
|
||||||
|
Toy_LiteralArray returns;
|
||||||
|
Toy_initLiteralArray(&returns);
|
||||||
|
|
||||||
|
Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns);
|
||||||
|
|
||||||
|
//grab the results
|
||||||
|
Toy_Literal lit = Toy_popLiteralArray(&returns);
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&arguments);
|
||||||
|
Toy_freeLiteralArray(&returns);
|
||||||
|
|
||||||
|
//if not truthy
|
||||||
|
if (TOY_IS_TRUTHY(lit)) {
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteral(fnLiteral);
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
//no arguments
|
//no arguments
|
||||||
if (arguments->count != 1) {
|
if (arguments->count != 1) {
|
||||||
@@ -506,13 +971,13 @@ static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
|
|||||||
}
|
}
|
||||||
|
|
||||||
Toy_RefString* selfRefString = TOY_AS_STRING(selfLiteral);
|
Toy_RefString* selfRefString = TOY_AS_STRING(selfLiteral);
|
||||||
char* self = Toy_toCString(selfRefString);
|
const char* self = Toy_toCString(selfRefString);
|
||||||
|
|
||||||
//allocate buffer space for the result
|
//allocate buffer space for the result
|
||||||
char* result = TOY_ALLOCATE(char, Toy_lengthRefString(selfRefString) + 1);
|
char* result = TOY_ALLOCATE(char, Toy_lengthRefString(selfRefString) + 1);
|
||||||
|
|
||||||
//set each new character
|
//set each new character
|
||||||
for (int i = 0; i < Toy_lengthRefString(selfRefString); i++) {
|
for (int i = 0; i < (int)Toy_lengthRefString(selfRefString); i++) {
|
||||||
result[i] = tolower(self[i]);
|
result[i] = tolower(self[i]);
|
||||||
}
|
}
|
||||||
result[Toy_lengthRefString(selfRefString)] = '\0'; //end the string
|
result[Toy_lengthRefString(selfRefString)] = '\0'; //end the string
|
||||||
@@ -533,7 +998,7 @@ static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
|
|||||||
|
|
||||||
static char* toStringUtilObject = NULL;
|
static char* toStringUtilObject = NULL;
|
||||||
static void toStringUtil(const char* input) {
|
static void toStringUtil(const char* input) {
|
||||||
int len = strlen(input) + 1;
|
size_t len = strlen(input) + 1;
|
||||||
|
|
||||||
if (len > TOY_MAX_STRING_LENGTH) {
|
if (len > TOY_MAX_STRING_LENGTH) {
|
||||||
len = TOY_MAX_STRING_LENGTH; //TODO: don't truncate
|
len = TOY_MAX_STRING_LENGTH; //TODO: don't truncate
|
||||||
@@ -606,13 +1071,13 @@ static int nativeToUpper(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
|
|||||||
}
|
}
|
||||||
|
|
||||||
Toy_RefString* selfRefString = TOY_AS_STRING(selfLiteral);
|
Toy_RefString* selfRefString = TOY_AS_STRING(selfLiteral);
|
||||||
char* self = Toy_toCString(selfRefString);
|
const char* self = Toy_toCString(selfRefString);
|
||||||
|
|
||||||
//allocate buffer space for the result
|
//allocate buffer space for the result
|
||||||
char* result = TOY_ALLOCATE(char, Toy_lengthRefString(selfRefString) + 1);
|
char* result = TOY_ALLOCATE(char, Toy_lengthRefString(selfRefString) + 1);
|
||||||
|
|
||||||
//set each new character
|
//set each new character
|
||||||
for (int i = 0; i < Toy_lengthRefString(selfRefString); i++) {
|
for (int i = 0; i < (int)Toy_lengthRefString(selfRefString); i++) {
|
||||||
result[i] = toupper(self[i]);
|
result[i] = toupper(self[i]);
|
||||||
}
|
}
|
||||||
result[Toy_lengthRefString(selfRefString)] = '\0'; //end the string
|
result[Toy_lengthRefString(selfRefString)] = '\0'; //end the string
|
||||||
@@ -675,10 +1140,10 @@ static int nativeTrim(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
int bufferEnd = Toy_lengthRefString(selfRefString);
|
int bufferEnd = Toy_lengthRefString(selfRefString);
|
||||||
|
|
||||||
//for each character in self, check it against each character in trimChars - on a fail, go to end
|
//for each character in self, check it against each character in trimChars - on a fail, go to end
|
||||||
for (int i = 0; i < Toy_lengthRefString(selfRefString); i++) {
|
for (int i = 0; i < (int)Toy_lengthRefString(selfRefString); i++) {
|
||||||
int trimIndex = 0;
|
int trimIndex = 0;
|
||||||
|
|
||||||
while (trimIndex < Toy_lengthRefString(trimCharsRefString)) {
|
while (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) {
|
||||||
//there is a match - DON'T increment anymore
|
//there is a match - DON'T increment anymore
|
||||||
if (Toy_toCString(selfRefString)[i] == Toy_toCString(trimCharsRefString)[trimIndex]) {
|
if (Toy_toCString(selfRefString)[i] == Toy_toCString(trimCharsRefString)[trimIndex]) {
|
||||||
break;
|
break;
|
||||||
@@ -688,7 +1153,7 @@ static int nativeTrim(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if the match is found, increment buffer begin
|
//if the match is found, increment buffer begin
|
||||||
if (trimIndex < Toy_lengthRefString(trimCharsRefString)) {
|
if (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) {
|
||||||
bufferBegin++;
|
bufferBegin++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -701,7 +1166,7 @@ static int nativeTrim(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
for (int i = Toy_lengthRefString(selfRefString); i >= 0; i--) {
|
for (int i = Toy_lengthRefString(selfRefString); i >= 0; i--) {
|
||||||
int trimIndex = 0;
|
int trimIndex = 0;
|
||||||
|
|
||||||
while (trimIndex < Toy_lengthRefString(trimCharsRefString)) {
|
while (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) {
|
||||||
//there is a match - DON'T increment anymore
|
//there is a match - DON'T increment anymore
|
||||||
if (Toy_toCString(selfRefString)[i-1] == Toy_toCString(trimCharsRefString)[trimIndex]) {
|
if (Toy_toCString(selfRefString)[i-1] == Toy_toCString(trimCharsRefString)[trimIndex]) {
|
||||||
break;
|
break;
|
||||||
@@ -711,7 +1176,7 @@ static int nativeTrim(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if the match is found, increment buffer begin
|
//if the match is found, increment buffer begin
|
||||||
if (trimIndex < Toy_lengthRefString(trimCharsRefString)) {
|
if (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) {
|
||||||
bufferEnd--;
|
bufferEnd--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -786,10 +1251,10 @@ static int nativeTrimBegin(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
|
|||||||
int bufferEnd = Toy_lengthRefString(selfRefString);
|
int bufferEnd = Toy_lengthRefString(selfRefString);
|
||||||
|
|
||||||
//for each character in self, check it against each character in trimChars - on a fail, go to end
|
//for each character in self, check it against each character in trimChars - on a fail, go to end
|
||||||
for (int i = 0; i < Toy_lengthRefString(selfRefString); i++) {
|
for (int i = 0; i < (int)Toy_lengthRefString(selfRefString); i++) {
|
||||||
int trimIndex = 0;
|
int trimIndex = 0;
|
||||||
|
|
||||||
while (trimIndex < Toy_lengthRefString(trimCharsRefString)) {
|
while (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) {
|
||||||
//there is a match - DON'T increment anymore
|
//there is a match - DON'T increment anymore
|
||||||
if (Toy_toCString(selfRefString)[i] == Toy_toCString(trimCharsRefString)[trimIndex]) {
|
if (Toy_toCString(selfRefString)[i] == Toy_toCString(trimCharsRefString)[trimIndex]) {
|
||||||
break;
|
break;
|
||||||
@@ -799,7 +1264,7 @@ static int nativeTrimBegin(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if the match is found, increment buffer begin
|
//if the match is found, increment buffer begin
|
||||||
if (trimIndex < Toy_lengthRefString(trimCharsRefString)) {
|
if (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) {
|
||||||
bufferBegin++;
|
bufferBegin++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -874,10 +1339,10 @@ static int nativeTrimEnd(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
|
|||||||
int bufferEnd = Toy_lengthRefString(selfRefString);
|
int bufferEnd = Toy_lengthRefString(selfRefString);
|
||||||
|
|
||||||
//again, from the back
|
//again, from the back
|
||||||
for (int i = Toy_lengthRefString(selfRefString); i >= 0; i--) {
|
for (int i = (int)Toy_lengthRefString(selfRefString); i >= 0; i--) {
|
||||||
int trimIndex = 0;
|
int trimIndex = 0;
|
||||||
|
|
||||||
while (trimIndex < Toy_lengthRefString(trimCharsRefString)) {
|
while (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) {
|
||||||
//there is a match - DON'T increment anymore
|
//there is a match - DON'T increment anymore
|
||||||
if (Toy_toCString(selfRefString)[i-1] == Toy_toCString(trimCharsRefString)[trimIndex]) {
|
if (Toy_toCString(selfRefString)[i-1] == Toy_toCString(trimCharsRefString)[trimIndex]) {
|
||||||
break;
|
break;
|
||||||
@@ -887,7 +1352,7 @@ static int nativeTrimEnd(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if the match is found, increment buffer begin
|
//if the match is found, increment buffer begin
|
||||||
if (trimIndex < Toy_lengthRefString(trimCharsRefString)) {
|
if (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) {
|
||||||
bufferEnd--;
|
bufferEnd--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -928,10 +1393,10 @@ int Toy_hookCompound(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L
|
|||||||
//build the natives list
|
//build the natives list
|
||||||
Natives natives[] = {
|
Natives natives[] = {
|
||||||
{"_concat", nativeConcat}, //array, dictionary, string
|
{"_concat", nativeConcat}, //array, dictionary, string
|
||||||
// {"_containsKey", native}, //dictionary
|
{"_containsKey", nativeContainsKey}, //dictionary
|
||||||
// {"_containsValue", native}, //array, dictionary
|
{"_containsValue", nativeContainsValue}, //array, dictionary
|
||||||
// {"_every", native}, //array, dictionary, string
|
{"_every", nativeEvery}, //array, dictionary
|
||||||
// {"_filter", native}, //array, dictionary
|
{"_filter", nativeFilter}, //array, dictionary
|
||||||
{"_forEach", nativeForEach}, //array, dictionary
|
{"_forEach", nativeForEach}, //array, dictionary
|
||||||
{"_getKeys", nativeGetKeys}, //dictionary
|
{"_getKeys", nativeGetKeys}, //dictionary
|
||||||
{"_getValues", nativeGetValues}, //dictionary
|
{"_getValues", nativeGetValues}, //dictionary
|
||||||
@@ -941,7 +1406,7 @@ int Toy_hookCompound(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L
|
|||||||
{"_reduce", nativeReduce}, //array, dictionary
|
{"_reduce", nativeReduce}, //array, dictionary
|
||||||
// {"_remove", native}, //array, dictionary
|
// {"_remove", native}, //array, dictionary
|
||||||
// {"_replace", native}, //string
|
// {"_replace", native}, //string
|
||||||
// {"_some", native}, //array, dictionary, string
|
{"_some", nativeSome}, //array, dictionary
|
||||||
// {"_sort", native}, //array
|
// {"_sort", native}, //array
|
||||||
{"_toLower", nativeToLower}, //string
|
{"_toLower", nativeToLower}, //string
|
||||||
{"_toString", nativeToString}, //array, dictionary
|
{"_toString", nativeToString}, //array, dictionary
|
||||||
|
|||||||
+7
-7
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
typedef struct Toy_Runner {
|
typedef struct Toy_Runner {
|
||||||
Toy_Interpreter interpreter;
|
Toy_Interpreter interpreter;
|
||||||
unsigned char* bytecode;
|
const unsigned char* bytecode;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
bool dirty;
|
bool dirty;
|
||||||
@@ -43,12 +43,12 @@ static int nativeLoadScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argu
|
|||||||
Toy_freeLiteral(drivePathLiteral);
|
Toy_freeLiteral(drivePathLiteral);
|
||||||
|
|
||||||
//use raw types - easier
|
//use raw types - easier
|
||||||
char* filePath = Toy_toCString(TOY_AS_STRING(filePathLiteral));
|
const char* filePath = Toy_toCString(TOY_AS_STRING(filePathLiteral));
|
||||||
int filePathLength = Toy_lengthRefString(TOY_AS_STRING(filePathLiteral));
|
int filePathLength = Toy_lengthRefString(TOY_AS_STRING(filePathLiteral));
|
||||||
|
|
||||||
//load and compile the bytecode
|
//load and compile the bytecode
|
||||||
size_t fileSize = 0;
|
size_t fileSize = 0;
|
||||||
char* source = Toy_readFile(filePath, &fileSize);
|
const char* source = Toy_readFile(filePath, &fileSize);
|
||||||
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
interpreter->errorOutput("Failed to load source file\n");
|
interpreter->errorOutput("Failed to load source file\n");
|
||||||
@@ -56,7 +56,7 @@ static int nativeLoadScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argu
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* bytecode = Toy_compileString(source, &fileSize);
|
const unsigned char* bytecode = Toy_compileString(source, &fileSize);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
|
|
||||||
if (!bytecode) {
|
if (!bytecode) {
|
||||||
@@ -105,7 +105,7 @@ static int nativeLoadScriptBytecode(Toy_Interpreter* interpreter, Toy_LiteralArr
|
|||||||
Toy_RefString* drivePath = Toy_copyRefString(TOY_AS_STRING(drivePathLiteral));
|
Toy_RefString* drivePath = Toy_copyRefString(TOY_AS_STRING(drivePathLiteral));
|
||||||
|
|
||||||
//get the drive and path as a string (can't trust that pesky strtok - custom split) TODO: move this to refstring library
|
//get the drive and path as a string (can't trust that pesky strtok - custom split) TODO: move this to refstring library
|
||||||
int driveLength = 0;
|
size_t driveLength = 0;
|
||||||
while (Toy_toCString(drivePath)[driveLength] != ':') {
|
while (Toy_toCString(drivePath)[driveLength] != ':') {
|
||||||
if (driveLength >= Toy_lengthRefString(drivePath)) {
|
if (driveLength >= Toy_lengthRefString(drivePath)) {
|
||||||
interpreter->errorOutput("Incorrect drive path format given to loadScriptBytecode\n");
|
interpreter->errorOutput("Incorrect drive path format given to loadScriptBytecode\n");
|
||||||
@@ -492,7 +492,7 @@ static int nativeCheckScriptDirty(Toy_Interpreter* interpreter, Toy_LiteralArray
|
|||||||
|
|
||||||
//call the hook
|
//call the hook
|
||||||
typedef struct Natives {
|
typedef struct Natives {
|
||||||
char* name;
|
const char* name;
|
||||||
Toy_NativeFn fn;
|
Toy_NativeFn fn;
|
||||||
} Natives;
|
} Natives;
|
||||||
|
|
||||||
@@ -585,7 +585,7 @@ Toy_Literal Toy_getFilePathLiteral(Toy_Interpreter* interpreter, Toy_Literal* dr
|
|||||||
Toy_RefString* drivePath = Toy_copyRefString(TOY_AS_STRING(*drivePathLiteral));
|
Toy_RefString* drivePath = Toy_copyRefString(TOY_AS_STRING(*drivePathLiteral));
|
||||||
|
|
||||||
//get the drive and path as a string (can't trust that pesky strtok - custom split) TODO: move this to refstring library
|
//get the drive and path as a string (can't trust that pesky strtok - custom split) TODO: move this to refstring library
|
||||||
int driveLength = 0;
|
size_t driveLength = 0;
|
||||||
while (Toy_toCString(drivePath)[driveLength] != ':') {
|
while (Toy_toCString(drivePath)[driveLength] != ':') {
|
||||||
if (driveLength >= Toy_lengthRefString(drivePath)) {
|
if (driveLength >= Toy_lengthRefString(drivePath)) {
|
||||||
interpreter->errorOutput("Incorrect drive path format given to Toy_getFilePathLiteral\n");
|
interpreter->errorOutput("Incorrect drive path format given to Toy_getFilePathLiteral\n");
|
||||||
|
|||||||
+3
-2
@@ -53,6 +53,7 @@ void repl() {
|
|||||||
Toy_Compiler compiler;
|
Toy_Compiler compiler;
|
||||||
|
|
||||||
Toy_initLexer(&lexer, input);
|
Toy_initLexer(&lexer, input);
|
||||||
|
Toy_private_setComments(&lexer, false); //BUGFIX: disable comments here
|
||||||
Toy_initParser(&parser, &lexer);
|
Toy_initParser(&parser, &lexer);
|
||||||
Toy_initCompiler(&compiler);
|
Toy_initCompiler(&compiler);
|
||||||
|
|
||||||
@@ -151,11 +152,11 @@ int main(int argc, const char* argv[]) {
|
|||||||
//compile source file
|
//compile source file
|
||||||
if (Toy_commandLine.compilefile && Toy_commandLine.outfile) {
|
if (Toy_commandLine.compilefile && Toy_commandLine.outfile) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char* source = Toy_readFile(Toy_commandLine.compilefile, &size);
|
const char* source = Toy_readFile(Toy_commandLine.compilefile, &size);
|
||||||
if (!source) {
|
if (!source) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
unsigned char* tb = Toy_compileString(source, &size);
|
const unsigned char* tb = Toy_compileString(source, &size);
|
||||||
if (!tb) {
|
if (!tb) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -16,7 +16,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
//IO functions
|
//IO functions
|
||||||
char* Toy_readFile(char* path, size_t* fileSize) {
|
const char* Toy_readFile(const char* path, size_t* fileSize) {
|
||||||
FILE* file = fopen(path, "rb");
|
FILE* file = fopen(path, "rb");
|
||||||
|
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
@@ -49,7 +49,7 @@ char* Toy_readFile(char* path, size_t* fileSize) {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Toy_writeFile(char* path, unsigned char* bytes, size_t size) {
|
int Toy_writeFile(const char* path, const unsigned char* bytes, size_t size) {
|
||||||
FILE* file = fopen(path, "wb");
|
FILE* file = fopen(path, "wb");
|
||||||
|
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
@@ -70,7 +70,7 @@ int Toy_writeFile(char* path, unsigned char* bytes, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//repl functions
|
//repl functions
|
||||||
unsigned char* Toy_compileString(char* source, size_t* size) {
|
const unsigned char* Toy_compileString(const char* source, size_t* size) {
|
||||||
Toy_Lexer lexer;
|
Toy_Lexer lexer;
|
||||||
Toy_Parser parser;
|
Toy_Parser parser;
|
||||||
Toy_Compiler compiler;
|
Toy_Compiler compiler;
|
||||||
@@ -96,7 +96,7 @@ unsigned char* Toy_compileString(char* source, size_t* size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//get the bytecode dump
|
//get the bytecode dump
|
||||||
unsigned char* tb = Toy_collateCompiler(&compiler, (int*)(size));
|
const unsigned char* tb = Toy_collateCompiler(&compiler, (int*)(size));
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
Toy_freeCompiler(&compiler);
|
Toy_freeCompiler(&compiler);
|
||||||
@@ -107,7 +107,7 @@ unsigned char* Toy_compileString(char* source, size_t* size) {
|
|||||||
return tb;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_runBinary(unsigned char* tb, size_t size) {
|
void Toy_runBinary(const unsigned char* tb, size_t size) {
|
||||||
Toy_Interpreter interpreter;
|
Toy_Interpreter interpreter;
|
||||||
Toy_initInterpreter(&interpreter);
|
Toy_initInterpreter(&interpreter);
|
||||||
|
|
||||||
@@ -122,9 +122,9 @@ void Toy_runBinary(unsigned char* tb, size_t size) {
|
|||||||
Toy_freeInterpreter(&interpreter);
|
Toy_freeInterpreter(&interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_runBinaryFile(char* fname) {
|
void Toy_runBinaryFile(const char* fname) {
|
||||||
size_t size = 0; //not used
|
size_t size = 0; //not used
|
||||||
unsigned char* tb = (unsigned char*)Toy_readFile(fname, &size);
|
const unsigned char* tb = (const unsigned char*)Toy_readFile(fname, &size);
|
||||||
if (!tb) {
|
if (!tb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -132,9 +132,9 @@ void Toy_runBinaryFile(char* fname) {
|
|||||||
//interpreter takes ownership of the binary data
|
//interpreter takes ownership of the binary data
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_runSource(char* source) {
|
void Toy_runSource(const char* source) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
unsigned char* tb = Toy_compileString(source, &size);
|
const unsigned char* tb = Toy_compileString(source, &size);
|
||||||
if (!tb) {
|
if (!tb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -142,9 +142,9 @@ void Toy_runSource(char* source) {
|
|||||||
Toy_runBinary(tb, size);
|
Toy_runBinary(tb, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_runSourceFile(char* fname) {
|
void Toy_runSourceFile(const char* fname) {
|
||||||
size_t size = 0; //not used
|
size_t size = 0; //not used
|
||||||
char* source = Toy_readFile(fname, &size);
|
const char* source = Toy_readFile(fname, &size);
|
||||||
if (!source) {
|
if (!source) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
#include "toy_common.h"
|
#include "toy_common.h"
|
||||||
|
|
||||||
char* Toy_readFile(char* path, size_t* fileSize);
|
const char* Toy_readFile(const char* path, size_t* fileSize);
|
||||||
int Toy_writeFile(char* path, unsigned char* bytes, size_t size);
|
int Toy_writeFile(const char* path, const unsigned char* bytes, size_t size);
|
||||||
|
|
||||||
unsigned char* Toy_compileString(char* source, size_t* size);
|
const unsigned char* Toy_compileString(const char* source, size_t* size);
|
||||||
|
|
||||||
void Toy_runBinary(unsigned char* tb, size_t size);
|
void Toy_runBinary(const unsigned char* tb, size_t size);
|
||||||
void Toy_runBinaryFile(char* fname);
|
void Toy_runBinaryFile(const char* fname);
|
||||||
void Toy_runSource(char* source);
|
void Toy_runSource(const char* source);
|
||||||
void Toy_runSourceFile(char* fname);
|
void Toy_runSourceFile(const char* fname);
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ fn getY(node: opaque) {
|
|||||||
|
|
||||||
//lifecycle functions
|
//lifecycle functions
|
||||||
fn onInit(node: opaque) {
|
fn onInit(node: opaque) {
|
||||||
print "render.toy:onInit() called";
|
print "render.toy:onInit() called\n";
|
||||||
|
|
||||||
node.loadTexture("sprites:/character.png");
|
node.loadTexture("sprites:/character.png");
|
||||||
parent = node.getNodeParent();
|
parent = node.getNodeParent();
|
||||||
@@ -36,13 +36,13 @@ fn onStep(node: opaque) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn onFree(node: opaque) {
|
fn onFree(node: opaque) {
|
||||||
print "render.toy:onFree() called";
|
print "render.toy:onFree() called\n";
|
||||||
|
|
||||||
node.freeTexture();
|
node.freeTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn onDraw(node: opaque) {
|
fn onDraw(node: opaque) {
|
||||||
// print "render.toy:onDraw() called";
|
// print "render.toy:onDraw() called\n";
|
||||||
|
|
||||||
var px = parent.callNode("getX");
|
var px = parent.callNode("getX");
|
||||||
var py = parent.callNode("getY");
|
var py = parent.callNode("getY");
|
||||||
@@ -104,11 +104,11 @@ fn onKeyUp(node: opaque, event: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn onMouseMotion(node: opaque, x: int, y: int, xrel: int, yrel: int) {
|
fn onMouseMotion(node: opaque, x: int, y: int, xrel: int, yrel: int) {
|
||||||
print "entity.toy:onMouseMotion(" + string x + ", " + string y + ", " + string xrel + ", " + string yrel + ")";
|
// print "entity.toy:onMouseMotion(" + string x + ", " + string y + ", " + string xrel + ", " + string yrel + ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
fn onMouseButtonDown(node: opaque, x: int, y: int, button: string) {
|
fn onMouseButtonDown(node: opaque, x: int, y: int, button: string) {
|
||||||
print "entity.toy:onMouseButtonDown(" + string x + ", " + string y + ", " + button + ")";
|
// print "entity.toy:onMouseButtonDown(" + string x + ", " + string y + ", " + button + ")\n";
|
||||||
|
|
||||||
//jump to pos
|
//jump to pos
|
||||||
posX = x - WIDTH / 2;
|
posX = x - WIDTH / 2;
|
||||||
@@ -116,10 +116,10 @@ fn onMouseButtonDown(node: opaque, x: int, y: int, button: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn onMouseButtonUp(node: opaque, x: int, y: int, button: string) {
|
fn onMouseButtonUp(node: opaque, x: int, y: int, button: string) {
|
||||||
print "entity.toy:onMouseButtonUp(" + string x + ", " + string y + ", " + button + ")";
|
// print "entity.toy:onMouseButtonUp(" + string x + ", " + string y + ", " + button + ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
fn onMouseWheel(node: opaque, xrel: int, yrel: int) {
|
fn onMouseWheel(node: opaque, xrel: int, yrel: int) {
|
||||||
print "entity.toy:onMouseWheel(" + string xrel + ", " + string yrel + ")";
|
// print "entity.toy:onMouseWheel(" + string xrel + ", " + string yrel + ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,5 +17,5 @@ fn fib(n : int) {
|
|||||||
|
|
||||||
for (var i = 0; i < 40; i++) {
|
for (var i = 0; i < 40; i++) {
|
||||||
var res = fib(i);
|
var res = fib(i);
|
||||||
print string i + ": " + string res;
|
print string i + ": " + string res + "\n";
|
||||||
}
|
}
|
||||||
+1
-1
@@ -5,5 +5,5 @@ fn fib(n : int) {
|
|||||||
|
|
||||||
for (var i = 0; i < 20; i++) {
|
for (var i = 0; i < 20; i++) {
|
||||||
var res = fib(i);
|
var res = fib(i);
|
||||||
print string i + ": " + string res;
|
print string i + ": " + string res + "\n";
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
//constants
|
||||||
|
var WIDTH: int const = 10;
|
||||||
|
var HEIGHT: int const = 10;
|
||||||
|
|
||||||
|
//WIDTH * HEIGHT in size
|
||||||
|
var tiles: [[int]] const = [
|
||||||
|
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||||
|
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||||
|
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||||
|
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||||
|
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||||
|
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||||
|
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||||
|
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||||
|
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||||
|
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||||
|
];
|
||||||
|
|
||||||
|
var tileset: [int: string] const = [
|
||||||
|
0: " ",
|
||||||
|
1: " X "
|
||||||
|
];
|
||||||
|
|
||||||
|
//variables
|
||||||
|
var posX: int = 5;
|
||||||
|
var posY: int = 5;
|
||||||
|
|
||||||
|
//functions
|
||||||
|
fn draw() {
|
||||||
|
for (var j: int = 0; j < HEIGHT; j++) {
|
||||||
|
for (var i: int = 0; i < WIDTH; i++) {
|
||||||
|
//draw the player pos
|
||||||
|
if (i == posX && j == posY) {
|
||||||
|
print " O ";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
print tileset[ tiles[i][j] ];
|
||||||
|
}
|
||||||
|
print "\n";
|
||||||
|
}
|
||||||
|
print "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move(xrel: int, yrel: int) {
|
||||||
|
if (xrel > 1 || xrel < -1 || yrel > 1 || yrel < -1 || (xrel != 0 && yrel != 0)) {
|
||||||
|
print "too fast!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tiles[posX + xrel][posY + yrel] > 0) {
|
||||||
|
print "Can't move that way\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
posX += xrel;
|
||||||
|
posY += yrel;
|
||||||
|
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
+2
-2
@@ -29,7 +29,7 @@ for (var i = 0; i < SIZE -1; i++) {
|
|||||||
prev += " ";
|
prev += " ";
|
||||||
}
|
}
|
||||||
prev += "*"; //initial
|
prev += "*"; //initial
|
||||||
print prev;
|
print prev + "\n";
|
||||||
|
|
||||||
//run
|
//run
|
||||||
for (var iteration = 0; iteration < SIZE -1; iteration++) {
|
for (var iteration = 0; iteration < SIZE -1; iteration++) {
|
||||||
@@ -44,6 +44,6 @@ for (var iteration = 0; iteration < SIZE -1; iteration++) {
|
|||||||
//right
|
//right
|
||||||
output += (lookup[prev[SIZE-2]][prev[SIZE-1]][" "]);
|
output += (lookup[prev[SIZE-2]][prev[SIZE-1]][" "]);
|
||||||
|
|
||||||
print output;
|
print output + "\n";
|
||||||
prev = output;
|
prev = output;
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -1,6 +1,10 @@
|
|||||||
import compound;
|
|
||||||
var arr: [int] = [1, 2, 3];
|
|
||||||
fn f(_, v: int): int { return v + 1; }
|
|
||||||
print arr.map(f);
|
|
||||||
|
|
||||||
|
var xrel: int = 0;
|
||||||
|
var yrel: int = 0;
|
||||||
|
|
||||||
|
if (xrel > 1 || xrel < -1 || yrel > 1 || yrel < -1) {
|
||||||
|
print "outside";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "inside";
|
||||||
|
}
|
||||||
@@ -793,7 +793,7 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//handle each error case
|
//handle each error case
|
||||||
if (!TOY_IS_INTEGER(first) || TOY_AS_INTEGER(first) < 0 || TOY_AS_INTEGER(first) >= TOY_AS_STRING(compound)->length) {
|
if (!TOY_IS_INTEGER(first) || TOY_AS_INTEGER(first) < 0 || TOY_AS_INTEGER(first) >= (int)Toy_lengthRefString(TOY_AS_STRING(compound))) {
|
||||||
interpreter->errorOutput("Bad first indexing in string\n");
|
interpreter->errorOutput("Bad first indexing in string\n");
|
||||||
|
|
||||||
//something is weird - skip out
|
//something is weird - skip out
|
||||||
@@ -807,7 +807,7 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!TOY_IS_NULL(second) && !TOY_IS_INTEGER(second)) || TOY_AS_INTEGER(second) < 0 || TOY_AS_INTEGER(second) >= TOY_AS_STRING(compound)->length) {
|
if ((!TOY_IS_NULL(second) && !TOY_IS_INTEGER(second)) || TOY_AS_INTEGER(second) < 0 || TOY_AS_INTEGER(second) >= (int)Toy_lengthRefString(TOY_AS_STRING(compound))) {
|
||||||
interpreter->errorOutput("Bad second indexing in string\n");
|
interpreter->errorOutput("Bad second indexing in string\n");
|
||||||
|
|
||||||
//something is weird - skip out
|
//something is weird - skip out
|
||||||
@@ -838,7 +838,7 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
//simple indexing if second is null
|
//simple indexing if second is null
|
||||||
if (TOY_IS_NULL(second)) {
|
if (TOY_IS_NULL(second)) {
|
||||||
|
|
||||||
char* cstr = Toy_toCString(TOY_AS_STRING(compound));
|
const char* cstr = Toy_toCString(TOY_AS_STRING(compound));
|
||||||
char buf[16];
|
char buf[16];
|
||||||
|
|
||||||
snprintf(buf, 16, "%s", &(cstr[ TOY_AS_INTEGER(first) ]) );
|
snprintf(buf, 16, "%s", &(cstr[ TOY_AS_INTEGER(first) ]) );
|
||||||
@@ -937,7 +937,7 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//handle each error case
|
//handle each error case
|
||||||
if (!TOY_IS_INTEGER(first) || TOY_AS_INTEGER(first) < 0 || TOY_AS_INTEGER(first) >= TOY_AS_STRING(compound)->length) {
|
if (!TOY_IS_INTEGER(first) || TOY_AS_INTEGER(first) < 0 || TOY_AS_INTEGER(first) >= (int)Toy_lengthRefString(TOY_AS_STRING(compound))) {
|
||||||
interpreter->errorOutput("Bad first indexing in string assignment\n");
|
interpreter->errorOutput("Bad first indexing in string assignment\n");
|
||||||
|
|
||||||
//something is weird - skip out
|
//something is weird - skip out
|
||||||
@@ -951,7 +951,7 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!TOY_IS_NULL(second) && !TOY_IS_INTEGER(second)) || TOY_AS_INTEGER(second) < 0 || TOY_AS_INTEGER(second) >= TOY_AS_STRING(compound)->length) {
|
if ((!TOY_IS_NULL(second) && !TOY_IS_INTEGER(second)) || TOY_AS_INTEGER(second) < 0 || TOY_AS_INTEGER(second) >= (int)Toy_lengthRefString(TOY_AS_STRING(compound))) {
|
||||||
interpreter->errorOutput("Bad second indexing in string assignment\n");
|
interpreter->errorOutput("Bad second indexing in string assignment\n");
|
||||||
|
|
||||||
//something is weird - skip out
|
//something is weird - skip out
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#define TOY_VERSION_MAJOR 0
|
#define TOY_VERSION_MAJOR 0
|
||||||
#define TOY_VERSION_MINOR 8
|
#define TOY_VERSION_MINOR 8
|
||||||
#define TOY_VERSION_PATCH 1
|
#define TOY_VERSION_PATCH 2
|
||||||
#define TOY_VERSION_BUILD __DATE__ " " __TIME__
|
#define TOY_VERSION_BUILD __DATE__ " " __TIME__
|
||||||
|
|
||||||
//platform-specific specifications
|
//platform-specific specifications
|
||||||
|
|||||||
@@ -1096,7 +1096,7 @@ static unsigned char* collateCompilerHeaderOpt(Toy_Compiler* compiler, int* size
|
|||||||
|
|
||||||
Toy_Literal str = compiler->literalCache.literals[i];
|
Toy_Literal str = compiler->literalCache.literals[i];
|
||||||
|
|
||||||
for (int c = 0; c < TOY_AS_STRING(str)->length; c++) {
|
for (int c = 0; c < (int)Toy_lengthRefString(TOY_AS_STRING(str)); c++) {
|
||||||
emitByte(&collation, &capacity, &count, Toy_toCString(TOY_AS_STRING(str))[c]);
|
emitByte(&collation, &capacity, &count, Toy_toCString(TOY_AS_STRING(str))[c]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1198,7 +1198,7 @@ static unsigned char* collateCompilerHeaderOpt(Toy_Compiler* compiler, int* size
|
|||||||
|
|
||||||
Toy_Literal identifier = compiler->literalCache.literals[i];
|
Toy_Literal identifier = compiler->literalCache.literals[i];
|
||||||
|
|
||||||
for (int c = 0; c < TOY_AS_IDENTIFIER(identifier)->length; c++) {
|
for (int c = 0; c < (int)Toy_lengthRefString(TOY_AS_IDENTIFIER(identifier)); c++) {
|
||||||
emitByte(&collation, &capacity, &count, Toy_toCString(TOY_AS_IDENTIFIER(identifier))[c]);
|
emitByte(&collation, &capacity, &count, Toy_toCString(TOY_AS_IDENTIFIER(identifier))[c]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1284,6 +1284,7 @@ static unsigned char* collateCompilerHeaderOpt(Toy_Compiler* compiler, int* size
|
|||||||
return collation;
|
return collation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//the whole point of the compiler is to alter bytecode, so leave it as non-const
|
||||||
unsigned char* Toy_collateCompiler(Toy_Compiler* compiler, int* size) {
|
unsigned char* Toy_collateCompiler(Toy_Compiler* compiler, int* size) {
|
||||||
return collateCompilerHeaderOpt(compiler, size, true);
|
return collateCompilerHeaderOpt(compiler, size, true);
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-16
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
static void printWrapper(const char* output) {
|
static void printWrapper(const char* output) {
|
||||||
printf("%s", output);
|
printf("%s", output);
|
||||||
printf("\n"); //default new line
|
// printf("\n"); //default new line
|
||||||
}
|
}
|
||||||
|
|
||||||
static void assertWrapper(const char* output) {
|
static void assertWrapper(const char* output) {
|
||||||
@@ -26,7 +26,7 @@ static void errorWrapper(const char* output) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "%s" TOY_CC_RESET, output); //no newline
|
fprintf(stderr, TOY_CC_ERROR "%s" TOY_CC_RESET, output); //no newline
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Toy_injectNativeFn(Toy_Interpreter* interpreter, char* name, Toy_NativeFn func) {
|
bool Toy_injectNativeFn(Toy_Interpreter* interpreter, const char* name, Toy_NativeFn func) {
|
||||||
//reject reserved words
|
//reject reserved words
|
||||||
if (Toy_findTypeByKeyword(name) != TOY_TOKEN_EOF) {
|
if (Toy_findTypeByKeyword(name) != TOY_TOKEN_EOF) {
|
||||||
interpreter->errorOutput("Can't override an existing keyword\n");
|
interpreter->errorOutput("Can't override an existing keyword\n");
|
||||||
@@ -54,7 +54,7 @@ bool Toy_injectNativeFn(Toy_Interpreter* interpreter, char* name, Toy_NativeFn f
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Toy_injectNativeHook(Toy_Interpreter* interpreter, char* name, Toy_HookFn hook) {
|
bool Toy_injectNativeHook(Toy_Interpreter* interpreter, const char* name, Toy_HookFn hook) {
|
||||||
//reject reserved words
|
//reject reserved words
|
||||||
if (Toy_findTypeByKeyword(name) != TOY_TOKEN_EOF) {
|
if (Toy_findTypeByKeyword(name) != TOY_TOKEN_EOF) {
|
||||||
interpreter->errorOutput("Can't inject a hook on an existing keyword\n");
|
interpreter->errorOutput("Can't inject a hook on an existing keyword\n");
|
||||||
@@ -169,40 +169,40 @@ void Toy_setInterpreterError(Toy_Interpreter* interpreter, Toy_PrintFn errorOutp
|
|||||||
}
|
}
|
||||||
|
|
||||||
//utils
|
//utils
|
||||||
static unsigned char readByte(unsigned char* tb, int* count) {
|
static unsigned char readByte(const unsigned char* tb, int* count) {
|
||||||
unsigned char ret = *(unsigned char*)(tb + *count);
|
unsigned char ret = *(unsigned char*)(tb + *count);
|
||||||
*count += 1;
|
*count += 1;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned short readShort(unsigned char* tb, int* count) {
|
static unsigned short readShort(const unsigned char* tb, int* count) {
|
||||||
unsigned short ret = 0;
|
unsigned short ret = 0;
|
||||||
memcpy(&ret, tb + *count, 2);
|
memcpy(&ret, tb + *count, 2);
|
||||||
*count += 2;
|
*count += 2;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int readInt(unsigned char* tb, int* count) {
|
static int readInt(const unsigned char* tb, int* count) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
memcpy(&ret, tb + *count, 4);
|
memcpy(&ret, tb + *count, 4);
|
||||||
*count += 4;
|
*count += 4;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static float readFloat(unsigned char* tb, int* count) {
|
static float readFloat(const unsigned char* tb, int* count) {
|
||||||
float ret = 0;
|
float ret = 0;
|
||||||
memcpy(&ret, tb + *count, 4);
|
memcpy(&ret, tb + *count, 4);
|
||||||
*count += 4;
|
*count += 4;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* readString(unsigned char* tb, int* count) {
|
static const char* readString(const unsigned char* tb, int* count) {
|
||||||
unsigned char* ret = tb + *count;
|
const unsigned char* ret = tb + *count;
|
||||||
*count += strlen((char*)ret) + 1; //+1 for null character
|
*count += strlen((char*)ret) + 1; //+1 for null character
|
||||||
return (char*)ret;
|
return (const char*)ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void consumeByte(Toy_Interpreter* interpreter, unsigned char byte, unsigned char* tb, int* count) {
|
static void consumeByte(Toy_Interpreter* interpreter, unsigned char byte, const unsigned char* tb, int* count) {
|
||||||
if (byte != tb[*count]) {
|
if (byte != tb[*count]) {
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
snprintf(buffer, 512, "[internal] Failed to consume the correct byte (expected %u, found %u)\n", byte, tb[*count]);
|
snprintf(buffer, 512, "[internal] Failed to consume the correct byte (expected %u, found %u)\n", byte, tb[*count]);
|
||||||
@@ -211,7 +211,7 @@ static void consumeByte(Toy_Interpreter* interpreter, unsigned char byte, unsign
|
|||||||
*count += 1;
|
*count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void consumeShort(Toy_Interpreter* interpreter, unsigned short bytes, unsigned char* tb, int* count) {
|
static void consumeShort(Toy_Interpreter* interpreter, unsigned short bytes, const unsigned char* tb, int* count) {
|
||||||
if (bytes != *(unsigned short*)(tb + *count)) {
|
if (bytes != *(unsigned short*)(tb + *count)) {
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
snprintf(buffer, 512, "[internal] Failed to consume the correct bytes (expected %u, found %u)\n", bytes, *(unsigned short*)(tb + *count));
|
snprintf(buffer, 512, "[internal] Failed to consume the correct bytes (expected %u, found %u)\n", bytes, *(unsigned short*)(tb + *count));
|
||||||
@@ -1446,7 +1446,7 @@ bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_Liter
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Toy_callFn(Toy_Interpreter* interpreter, char* name, Toy_LiteralArray* arguments, Toy_LiteralArray* returns) {
|
bool Toy_callFn(Toy_Interpreter* interpreter, const char* name, Toy_LiteralArray* arguments, Toy_LiteralArray* returns) {
|
||||||
Toy_Literal key = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefStringLength(name, strlen(name)));
|
Toy_Literal key = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefStringLength(name, strlen(name)));
|
||||||
Toy_Literal val = TOY_TO_NULL_LITERAL;
|
Toy_Literal val = TOY_TO_NULL_LITERAL;
|
||||||
|
|
||||||
@@ -2125,7 +2125,7 @@ static void readInterpreterSections(Toy_Interpreter* interpreter) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_LITERAL_STRING: {
|
case TOY_LITERAL_STRING: {
|
||||||
char* s = readString(interpreter->bytecode, &interpreter->count);
|
const char* s = readString(interpreter->bytecode, &interpreter->count);
|
||||||
int length = strlen(s);
|
int length = strlen(s);
|
||||||
Toy_Literal literal = TOY_TO_STRING_LITERAL(Toy_createRefStringLength(s, length));
|
Toy_Literal literal = TOY_TO_STRING_LITERAL(Toy_createRefStringLength(s, length));
|
||||||
Toy_pushLiteralArray(&interpreter->literalCache, literal);
|
Toy_pushLiteralArray(&interpreter->literalCache, literal);
|
||||||
@@ -2222,7 +2222,7 @@ static void readInterpreterSections(Toy_Interpreter* interpreter) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_LITERAL_IDENTIFIER: {
|
case TOY_LITERAL_IDENTIFIER: {
|
||||||
char* str = readString(interpreter->bytecode, &interpreter->count);
|
const char* str = readString(interpreter->bytecode, &interpreter->count);
|
||||||
|
|
||||||
int length = strlen(str);
|
int length = strlen(str);
|
||||||
Toy_Literal identifier = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefStringLength(str, length));
|
Toy_Literal identifier = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefStringLength(str, length));
|
||||||
@@ -2356,7 +2356,7 @@ void Toy_initInterpreter(Toy_Interpreter* interpreter) {
|
|||||||
Toy_resetInterpreter(interpreter);
|
Toy_resetInterpreter(interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_runInterpreter(Toy_Interpreter* interpreter, unsigned char* bytecode, int length) {
|
void Toy_runInterpreter(Toy_Interpreter* interpreter, const unsigned char* bytecode, int length) {
|
||||||
//initialize here instead of initInterpreter()
|
//initialize here instead of initInterpreter()
|
||||||
Toy_initLiteralArray(&interpreter->literalCache);
|
Toy_initLiteralArray(&interpreter->literalCache);
|
||||||
interpreter->bytecode = NULL;
|
interpreter->bytecode = NULL;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ typedef void (*Toy_PrintFn)(const char*);
|
|||||||
//the interpreter acts depending on the bytecode instructions
|
//the interpreter acts depending on the bytecode instructions
|
||||||
typedef struct Toy_Interpreter {
|
typedef struct Toy_Interpreter {
|
||||||
//input
|
//input
|
||||||
unsigned char* bytecode;
|
const unsigned char* bytecode;
|
||||||
int length;
|
int length;
|
||||||
int count;
|
int count;
|
||||||
int codeStart; //BUGFIX: for jumps, must be initialized to -1
|
int codeStart; //BUGFIX: for jumps, must be initialized to -1
|
||||||
@@ -34,11 +34,11 @@ typedef struct Toy_Interpreter {
|
|||||||
} Toy_Interpreter;
|
} Toy_Interpreter;
|
||||||
|
|
||||||
//native API
|
//native API
|
||||||
TOY_API bool Toy_injectNativeFn(Toy_Interpreter* interpreter, char* name, Toy_NativeFn func);
|
TOY_API bool Toy_injectNativeFn(Toy_Interpreter* interpreter, const char* name, Toy_NativeFn func);
|
||||||
TOY_API bool Toy_injectNativeHook(Toy_Interpreter* interpreter, char* name, Toy_HookFn hook);
|
TOY_API bool Toy_injectNativeHook(Toy_Interpreter* interpreter, const char* name, Toy_HookFn hook);
|
||||||
|
|
||||||
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, const char* name, Toy_LiteralArray* arguments, Toy_LiteralArray* returns);
|
||||||
|
|
||||||
//utilities for the host program
|
//utilities for the host program
|
||||||
TOY_API bool Toy_parseIdentifierToValue(Toy_Interpreter* interpreter, Toy_Literal* literalPtr);
|
TOY_API bool Toy_parseIdentifierToValue(Toy_Interpreter* interpreter, Toy_Literal* literalPtr);
|
||||||
@@ -48,6 +48,6 @@ TOY_API void Toy_setInterpreterError(Toy_Interpreter* interpreter, Toy_PrintFn e
|
|||||||
|
|
||||||
//main access
|
//main access
|
||||||
TOY_API void Toy_initInterpreter(Toy_Interpreter* interpreter); //start of program
|
TOY_API void Toy_initInterpreter(Toy_Interpreter* interpreter); //start of program
|
||||||
TOY_API void Toy_runInterpreter(Toy_Interpreter* interpreter, unsigned char* bytecode, int length); //run the code
|
TOY_API void Toy_runInterpreter(Toy_Interpreter* interpreter, const unsigned char* bytecode, int length); //run the code
|
||||||
TOY_API void Toy_resetInterpreter(Toy_Interpreter* interpreter); //use this to reset the interpreter's environment between runs
|
TOY_API void Toy_resetInterpreter(Toy_Interpreter* interpreter); //use this to reset the interpreter's environment between runs
|
||||||
TOY_API void Toy_freeInterpreter(Toy_Interpreter* interpreter); //end of program
|
TOY_API void Toy_freeInterpreter(Toy_Interpreter* interpreter); //end of program
|
||||||
|
|||||||
+13
-4
@@ -12,6 +12,7 @@ static void cleanLexer(Toy_Lexer* lexer) {
|
|||||||
lexer->start = 0;
|
lexer->start = 0;
|
||||||
lexer->current = 0;
|
lexer->current = 0;
|
||||||
lexer->line = 1;
|
lexer->line = 1;
|
||||||
|
lexer->commentsEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isAtEnd(Toy_Lexer* lexer) {
|
static bool isAtEnd(Toy_Lexer* lexer) {
|
||||||
@@ -54,9 +55,13 @@ static void eatWhitespace(Toy_Lexer* lexer) {
|
|||||||
|
|
||||||
//comments
|
//comments
|
||||||
case '/':
|
case '/':
|
||||||
|
if (!lexer->commentsEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//eat the line
|
//eat the line
|
||||||
if (peekNext(lexer) == '/') {
|
if (peekNext(lexer) == '/') {
|
||||||
while (advance(lexer) != '\n' && !isAtEnd(lexer));
|
while (!isAtEnd(lexer) && advance(lexer) != '\n');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +69,7 @@ static void eatWhitespace(Toy_Lexer* lexer) {
|
|||||||
if (peekNext(lexer) == '*') {
|
if (peekNext(lexer) == '*') {
|
||||||
advance(lexer);
|
advance(lexer);
|
||||||
advance(lexer);
|
advance(lexer);
|
||||||
while(!(peek(lexer) == '*' && peekNext(lexer) == '/')) advance(lexer);
|
while(!isAtEnd(lexer) && !(peek(lexer) == '*' && peekNext(lexer) == '/')) advance(lexer);
|
||||||
advance(lexer);
|
advance(lexer);
|
||||||
advance(lexer);
|
advance(lexer);
|
||||||
break;
|
break;
|
||||||
@@ -270,7 +275,7 @@ static Toy_Token makeKeywordOrIdentifier(Toy_Lexer* lexer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//exposed functions
|
//exposed functions
|
||||||
void Toy_initLexer(Toy_Lexer* lexer, char* source) {
|
void Toy_initLexer(Toy_Lexer* lexer, const char* source) {
|
||||||
cleanLexer(lexer);
|
cleanLexer(lexer);
|
||||||
|
|
||||||
lexer->source = source;
|
lexer->source = source;
|
||||||
@@ -363,7 +368,7 @@ void Toy_printToken(Toy_Token* token) {
|
|||||||
if (keyword != NULL) {
|
if (keyword != NULL) {
|
||||||
printf("%s", keyword);
|
printf("%s", keyword);
|
||||||
} else {
|
} else {
|
||||||
char* str = token->lexeme;
|
char* str = (char*)token->lexeme; //strip const-ness for trimming
|
||||||
int length = token->length;
|
int length = token->length;
|
||||||
trim(&str, &length);
|
trim(&str, &length);
|
||||||
printf("%.*s", length, str);
|
printf("%.*s", length, str);
|
||||||
@@ -372,3 +377,7 @@ void Toy_printToken(Toy_Token* token) {
|
|||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Toy_private_setComments(Toy_Lexer* lexer, bool enabled) {
|
||||||
|
lexer->commentsEnabled = enabled;
|
||||||
|
}
|
||||||
+6
-3
@@ -5,22 +5,25 @@
|
|||||||
|
|
||||||
//lexers are bound to a string of code, and return a single token every time scan is called
|
//lexers are bound to a string of code, and return a single token every time scan is called
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* source;
|
const char* source;
|
||||||
int start; //start of the token
|
int start; //start of the token
|
||||||
int current; //current position of the lexer
|
int current; //current position of the lexer
|
||||||
int line; //track this for error handling
|
int line; //track this for error handling
|
||||||
|
bool commentsEnabled; //BUGFIX: enable comments (disabled in repl)
|
||||||
} Toy_Lexer;
|
} Toy_Lexer;
|
||||||
|
|
||||||
//tokens are intermediaries between lexers and parsers
|
//tokens are intermediaries between lexers and parsers
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Toy_TokenType type;
|
Toy_TokenType type;
|
||||||
char* lexeme;
|
const char* lexeme;
|
||||||
int length;
|
int length;
|
||||||
int line;
|
int line;
|
||||||
} Toy_Token;
|
} Toy_Token;
|
||||||
|
|
||||||
TOY_API void Toy_initLexer(Toy_Lexer* lexer, char* source);
|
TOY_API void Toy_initLexer(Toy_Lexer* lexer, const char* source);
|
||||||
Toy_Token Toy_scanLexer(Toy_Lexer* lexer);
|
Toy_Token Toy_scanLexer(Toy_Lexer* lexer);
|
||||||
|
|
||||||
//for debugging
|
//for debugging
|
||||||
void Toy_printToken(Toy_Token* token);
|
void Toy_printToken(Toy_Token* token);
|
||||||
|
|
||||||
|
void Toy_private_setComments(Toy_Lexer* lexer, bool enabled);
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ void Toy_freeLiteral(Toy_Literal literal) {
|
|||||||
|
|
||||||
bool Toy_private_isTruthy(Toy_Literal x) {
|
bool Toy_private_isTruthy(Toy_Literal x) {
|
||||||
if (TOY_IS_NULL(x)) {
|
if (TOY_IS_NULL(x)) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "TOY_CC_ERROR: Null is neither true nor false\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "Null is neither true nor false\n" TOY_CC_RESET);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ Toy_Literal Toy_copyLiteral(Toy_Literal original) {
|
|||||||
return original;
|
return original;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, TOY_CC_ERROR "TOY_CC_ERROR: Can't copy that literal type: %d\n" TOY_CC_RESET, original.type);
|
fprintf(stderr, TOY_CC_ERROR "Can't copy that literal type: %d\n" TOY_CC_RESET, original.type);
|
||||||
return TOY_TO_NULL_LITERAL;
|
return TOY_TO_NULL_LITERAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -487,10 +487,10 @@ void Toy_printLiteralCustom(Toy_Literal literal, void (printFn)(const char*)) {
|
|||||||
case TOY_LITERAL_STRING: {
|
case TOY_LITERAL_STRING: {
|
||||||
char buffer[TOY_MAX_STRING_LENGTH];
|
char buffer[TOY_MAX_STRING_LENGTH];
|
||||||
if (!quotes) {
|
if (!quotes) {
|
||||||
snprintf(buffer, TOY_MAX_STRING_LENGTH, "%.*s", Toy_lengthRefString(TOY_AS_STRING(literal)), Toy_toCString(TOY_AS_STRING(literal)));
|
snprintf(buffer, TOY_MAX_STRING_LENGTH, "%.*s", (int)Toy_lengthRefString(TOY_AS_STRING(literal)), Toy_toCString(TOY_AS_STRING(literal)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
snprintf(buffer, TOY_MAX_STRING_LENGTH, "%c%.*s%c", quotes, Toy_lengthRefString(TOY_AS_STRING(literal)), Toy_toCString(TOY_AS_STRING(literal)), quotes);
|
snprintf(buffer, TOY_MAX_STRING_LENGTH, "%c%.*s%c", quotes, (int)Toy_lengthRefString(TOY_AS_STRING(literal)), Toy_toCString(TOY_AS_STRING(literal)), quotes);
|
||||||
}
|
}
|
||||||
printFn(buffer);
|
printFn(buffer);
|
||||||
}
|
}
|
||||||
@@ -596,7 +596,7 @@ void Toy_printLiteralCustom(Toy_Literal literal, void (printFn)(const char*)) {
|
|||||||
|
|
||||||
case TOY_LITERAL_IDENTIFIER: {
|
case TOY_LITERAL_IDENTIFIER: {
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
snprintf(buffer, 256, "%.*s", Toy_lengthRefString(TOY_AS_IDENTIFIER(literal)), Toy_toCString(TOY_AS_IDENTIFIER(literal)));
|
snprintf(buffer, 256, "%.*s", (int)Toy_lengthRefString(TOY_AS_IDENTIFIER(literal)), Toy_toCString(TOY_AS_IDENTIFIER(literal)));
|
||||||
printFn(buffer);
|
printFn(buffer);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
+23
-7
@@ -428,12 +428,12 @@ static Toy_Opcode binary(Toy_Parser* parser, Toy_ASTNode** nodeHandle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case TOY_TOKEN_AND: {
|
case TOY_TOKEN_AND: {
|
||||||
parsePrecedence(parser, nodeHandle, PREC_COMPARISON);
|
parsePrecedence(parser, nodeHandle, PREC_AND);
|
||||||
return TOY_OP_AND;
|
return TOY_OP_AND;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOY_TOKEN_OR: {
|
case TOY_TOKEN_OR: {
|
||||||
parsePrecedence(parser, nodeHandle, PREC_COMPARISON);
|
parsePrecedence(parser, nodeHandle, PREC_OR);
|
||||||
return TOY_OP_OR;
|
return TOY_OP_OR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,7 +448,7 @@ static Toy_Opcode unary(Toy_Parser* parser, Toy_ASTNode** nodeHandle) {
|
|||||||
|
|
||||||
if (parser->previous.type == TOY_TOKEN_MINUS) {
|
if (parser->previous.type == TOY_TOKEN_MINUS) {
|
||||||
//temp handle to potentially negate values
|
//temp handle to potentially negate values
|
||||||
parsePrecedence(parser, &tmpNode, PREC_TERNARY); //can be a literal
|
parsePrecedence(parser, &tmpNode, PREC_TERM); //can be a literal
|
||||||
|
|
||||||
//optimisation: check for negative literals
|
//optimisation: check for negative literals
|
||||||
if (tmpNode != NULL && tmpNode->type == TOY_AST_NODE_LITERAL && (TOY_IS_INTEGER(tmpNode->atomic.literal) || TOY_IS_FLOAT(tmpNode->atomic.literal))) {
|
if (tmpNode != NULL && tmpNode->type == TOY_AST_NODE_LITERAL && (TOY_IS_INTEGER(tmpNode->atomic.literal) || TOY_IS_FLOAT(tmpNode->atomic.literal))) {
|
||||||
@@ -508,7 +508,7 @@ static Toy_Opcode unary(Toy_Parser* parser, Toy_ASTNode** nodeHandle) {
|
|||||||
return TOY_OP_EOF;
|
return TOY_OP_EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* removeChar(char* lexeme, int length, char c) {
|
static char* removeChar(const char* lexeme, int length, char c) {
|
||||||
int resPos = 0;
|
int resPos = 0;
|
||||||
char* result = TOY_ALLOCATE(char, length + 1);
|
char* result = TOY_ALLOCATE(char, length + 1);
|
||||||
|
|
||||||
@@ -540,7 +540,7 @@ static Toy_Opcode atomic(Toy_Parser* parser, Toy_ASTNode** nodeHandle) {
|
|||||||
|
|
||||||
case TOY_TOKEN_LITERAL_INTEGER: {
|
case TOY_TOKEN_LITERAL_INTEGER: {
|
||||||
int value = 0;
|
int value = 0;
|
||||||
char* lexeme = removeChar(parser->previous.lexeme, parser->previous.length, '_');
|
const char* lexeme = removeChar(parser->previous.lexeme, parser->previous.length, '_');
|
||||||
sscanf(lexeme, "%d", &value);
|
sscanf(lexeme, "%d", &value);
|
||||||
TOY_FREE_ARRAY(char, lexeme, parser->previous.length + 1);
|
TOY_FREE_ARRAY(char, lexeme, parser->previous.length + 1);
|
||||||
Toy_emitASTNodeLiteral(nodeHandle, TOY_TO_INTEGER_LITERAL(value));
|
Toy_emitASTNodeLiteral(nodeHandle, TOY_TO_INTEGER_LITERAL(value));
|
||||||
@@ -549,7 +549,7 @@ static Toy_Opcode atomic(Toy_Parser* parser, Toy_ASTNode** nodeHandle) {
|
|||||||
|
|
||||||
case TOY_TOKEN_LITERAL_FLOAT: {
|
case TOY_TOKEN_LITERAL_FLOAT: {
|
||||||
float value = 0;
|
float value = 0;
|
||||||
char* lexeme = removeChar(parser->previous.lexeme, parser->previous.length, '_');
|
const char* lexeme = removeChar(parser->previous.lexeme, parser->previous.length, '_');
|
||||||
sscanf(lexeme, "%f", &value);
|
sscanf(lexeme, "%f", &value);
|
||||||
TOY_FREE_ARRAY(char, lexeme, parser->previous.length + 1);
|
TOY_FREE_ARRAY(char, lexeme, parser->previous.length + 1);
|
||||||
Toy_emitASTNodeLiteral(nodeHandle, TOY_TO_FLOAT_LITERAL(value));
|
Toy_emitASTNodeLiteral(nodeHandle, TOY_TO_FLOAT_LITERAL(value));
|
||||||
@@ -676,6 +676,10 @@ static Toy_Opcode incrementPrefix(Toy_Parser* parser, Toy_ASTNode** nodeHandle)
|
|||||||
Toy_ASTNode* tmpNode = NULL;
|
Toy_ASTNode* tmpNode = NULL;
|
||||||
identifier(parser, &tmpNode);
|
identifier(parser, &tmpNode);
|
||||||
|
|
||||||
|
if (!tmpNode) {
|
||||||
|
return TOY_OP_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
Toy_emitASTNodePrefixIncrement(nodeHandle, tmpNode->atomic.literal);
|
Toy_emitASTNodePrefixIncrement(nodeHandle, tmpNode->atomic.literal);
|
||||||
|
|
||||||
Toy_freeASTNode(tmpNode);
|
Toy_freeASTNode(tmpNode);
|
||||||
@@ -689,6 +693,10 @@ static Toy_Opcode incrementInfix(Toy_Parser* parser, Toy_ASTNode** nodeHandle) {
|
|||||||
|
|
||||||
advance(parser);
|
advance(parser);
|
||||||
|
|
||||||
|
if (!tmpNode) {
|
||||||
|
return TOY_OP_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
Toy_emitASTNodePostfixIncrement(nodeHandle, tmpNode->atomic.literal);
|
Toy_emitASTNodePostfixIncrement(nodeHandle, tmpNode->atomic.literal);
|
||||||
|
|
||||||
Toy_freeASTNode(tmpNode);
|
Toy_freeASTNode(tmpNode);
|
||||||
@@ -700,7 +708,11 @@ static Toy_Opcode decrementPrefix(Toy_Parser* parser, Toy_ASTNode** nodeHandle)
|
|||||||
advance(parser);
|
advance(parser);
|
||||||
|
|
||||||
Toy_ASTNode* tmpNode = NULL;
|
Toy_ASTNode* tmpNode = NULL;
|
||||||
identifier(parser, &tmpNode); //weird
|
identifier(parser, &tmpNode);
|
||||||
|
|
||||||
|
if (!tmpNode) {
|
||||||
|
return TOY_OP_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
Toy_emitASTNodePrefixDecrement(nodeHandle, tmpNode->atomic.literal);
|
Toy_emitASTNodePrefixDecrement(nodeHandle, tmpNode->atomic.literal);
|
||||||
|
|
||||||
@@ -715,6 +727,10 @@ static Toy_Opcode decrementInfix(Toy_Parser* parser, Toy_ASTNode** nodeHandle) {
|
|||||||
|
|
||||||
advance(parser);
|
advance(parser);
|
||||||
|
|
||||||
|
if (!tmpNode) {
|
||||||
|
return TOY_OP_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
Toy_emitASTNodePostfixDecrement(nodeHandle, tmpNode->atomic.literal);
|
Toy_emitASTNodePostfixDecrement(nodeHandle, tmpNode->atomic.literal);
|
||||||
|
|
||||||
Toy_freeASTNode(tmpNode);
|
Toy_freeASTNode(tmpNode);
|
||||||
|
|||||||
+18
-22
@@ -1,14 +1,6 @@
|
|||||||
#include "toy_refstring.h"
|
#include "toy_refstring.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
//test variable sizes based on platform (safety)
|
|
||||||
#define STATIC_ASSERT(test_for_true) static_assert((test_for_true), "(" #test_for_true ") failed")
|
|
||||||
|
|
||||||
STATIC_ASSERT(sizeof(Toy_RefString) == 12);
|
|
||||||
STATIC_ASSERT(sizeof(int) == 4);
|
|
||||||
STATIC_ASSERT(sizeof(char) == 1);
|
|
||||||
|
|
||||||
//memory allocation
|
//memory allocation
|
||||||
extern void* Toy_private_defaultMemoryAllocator(void* pointer, size_t oldSize, size_t newSize);
|
extern void* Toy_private_defaultMemoryAllocator(void* pointer, size_t oldSize, size_t newSize);
|
||||||
@@ -19,18 +11,22 @@ void Toy_setRefStringAllocatorFn(Toy_RefStringAllocatorFn allocator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//API
|
//API
|
||||||
Toy_RefString* Toy_createRefString(char* cstring) {
|
Toy_RefString* Toy_createRefString(const char* cstring) {
|
||||||
int length = strlen(cstring);
|
size_t length = strlen(cstring);
|
||||||
|
|
||||||
return Toy_createRefStringLength(cstring, length);
|
return Toy_createRefStringLength(cstring, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_RefString* Toy_createRefStringLength(char* cstring, int length) {
|
Toy_RefString* Toy_createRefStringLength(const char* cstring, size_t length) {
|
||||||
//allocate the memory area (including metadata space)
|
//allocate the memory area (including metadata space)
|
||||||
Toy_RefString* refString = (Toy_RefString*)allocate(NULL, 0, sizeof(int) * 2 + sizeof(char) * length + 1);
|
Toy_RefString* refString = allocate(NULL, 0, sizeof(size_t) + sizeof(int) + sizeof(char) * (length + 1));
|
||||||
|
|
||||||
|
if (refString == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//set the data
|
//set the data
|
||||||
refString->refcount = 1;
|
refString->refCount = 1;
|
||||||
refString->length = length;
|
refString->length = length;
|
||||||
strncpy(refString->data, cstring, refString->length);
|
strncpy(refString->data, cstring, refString->length);
|
||||||
|
|
||||||
@@ -41,32 +37,32 @@ Toy_RefString* Toy_createRefStringLength(char* cstring, int length) {
|
|||||||
|
|
||||||
void Toy_deleteRefString(Toy_RefString* refString) {
|
void Toy_deleteRefString(Toy_RefString* refString) {
|
||||||
//decrement, then check
|
//decrement, then check
|
||||||
refString->refcount--;
|
refString->refCount--;
|
||||||
if (refString->refcount <= 0) {
|
if (refString->refCount <= 0) {
|
||||||
allocate(refString, sizeof(int) * 2 + sizeof(char) * refString->length + 1, 0);
|
allocate(refString, sizeof(size_t) + sizeof(int) + sizeof(char) * (refString->length + 1), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Toy_countRefString(Toy_RefString* refString) {
|
int Toy_countRefString(Toy_RefString* refString) {
|
||||||
return refString->refcount;
|
return refString->refCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Toy_lengthRefString(Toy_RefString* refString) {
|
size_t Toy_lengthRefString(Toy_RefString* refString) {
|
||||||
return refString->length;
|
return refString->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_RefString* Toy_copyRefString(Toy_RefString* refString) {
|
Toy_RefString* Toy_copyRefString(Toy_RefString* refString) {
|
||||||
//Cheaty McCheater Face
|
//Cheaty McCheater Face
|
||||||
refString->refcount++;
|
refString->refCount++;
|
||||||
return refString;
|
return refString;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_RefString* Toy_deepCopyRefString(Toy_RefString* refString) {
|
Toy_RefString* Toy_deepCopyRefString(Toy_RefString* refString) {
|
||||||
//create a new string, with a new refcount
|
//create a new string, with a new refCount
|
||||||
return Toy_createRefStringLength(refString->data, refString->length);
|
return Toy_createRefStringLength(refString->data, refString->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* Toy_toCString(Toy_RefString* refString) {
|
const char* Toy_toCString(Toy_RefString* refString) {
|
||||||
return refString->data;
|
return refString->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +83,7 @@ bool Toy_equalsRefString(Toy_RefString* lhs, Toy_RefString* rhs) {
|
|||||||
|
|
||||||
bool Toy_equalsRefStringCString(Toy_RefString* lhs, char* cstring) {
|
bool Toy_equalsRefStringCString(Toy_RefString* lhs, char* cstring) {
|
||||||
//get the rhs length
|
//get the rhs length
|
||||||
int length = strlen(cstring);
|
size_t length = strlen(cstring);
|
||||||
|
|
||||||
//different length
|
//different length
|
||||||
if (lhs->length != length) {
|
if (lhs->length != length) {
|
||||||
|
|||||||
@@ -9,19 +9,19 @@ void Toy_setRefStringAllocatorFn(Toy_RefStringAllocatorFn);
|
|||||||
|
|
||||||
//the RefString structure
|
//the RefString structure
|
||||||
typedef struct Toy_RefString {
|
typedef struct Toy_RefString {
|
||||||
int refcount;
|
size_t length;
|
||||||
int length;
|
int refCount;
|
||||||
char data[1];
|
char data[];
|
||||||
} Toy_RefString;
|
} Toy_RefString;
|
||||||
|
|
||||||
//API
|
//API
|
||||||
Toy_RefString* Toy_createRefString(char* cstring);
|
Toy_RefString* Toy_createRefString(const char* cstring);
|
||||||
Toy_RefString* Toy_createRefStringLength(char* cstring, int length);
|
Toy_RefString* Toy_createRefStringLength(const char* cstring, size_t length);
|
||||||
void Toy_deleteRefString(Toy_RefString* refString);
|
void Toy_deleteRefString(Toy_RefString* refString);
|
||||||
int Toy_countRefString(Toy_RefString* refString);
|
int Toy_countRefString(Toy_RefString* refString);
|
||||||
int Toy_lengthRefString(Toy_RefString* refString);
|
size_t Toy_lengthRefString(Toy_RefString* refString);
|
||||||
Toy_RefString* Toy_copyRefString(Toy_RefString* refString);
|
Toy_RefString* Toy_copyRefString(Toy_RefString* refString);
|
||||||
Toy_RefString* Toy_deepCopyRefString(Toy_RefString* refString);
|
Toy_RefString* Toy_deepCopyRefString(Toy_RefString* refString);
|
||||||
char* Toy_toCString(Toy_RefString* refString);
|
const char* Toy_toCString(Toy_RefString* refString);
|
||||||
bool Toy_equalsRefString(Toy_RefString* lhs, Toy_RefString* rhs);
|
bool Toy_equalsRefString(Toy_RefString* lhs, Toy_RefString* rhs);
|
||||||
bool Toy_equalsRefStringCString(Toy_RefString* lhs, char* cstring);
|
bool Toy_equalsRefStringCString(Toy_RefString* lhs, char* cstring);
|
||||||
|
|||||||
@@ -45,6 +45,69 @@ import compound;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test containsKey
|
||||||
|
{
|
||||||
|
var d = ["one": 1, "two": 2];
|
||||||
|
|
||||||
|
assert d.containsKey("one") == true, "dictionary.containsKey() == true failed";
|
||||||
|
assert d.containsKey("three") == false, "dictionary.containsKey() == false failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test containsValue
|
||||||
|
{
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
var d = ["one": 1, "two": 2];
|
||||||
|
|
||||||
|
assert a.containsValue(1) == true, "array.containsValue() == true failed";
|
||||||
|
assert a.containsValue(5) == false, "array.containsValue() == false failed";
|
||||||
|
assert d.containsValue(1) == true, "dictionary.containsValue() == true failed";
|
||||||
|
assert d.containsValue(3) == false, "dictionary.containsValue() == false failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test every
|
||||||
|
{
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
var d = ["one": 1, "two": 2];
|
||||||
|
|
||||||
|
var counter = 0;
|
||||||
|
fn f(k, v) {
|
||||||
|
counter++;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert a.every(f) == true, "array.every() == true failed";
|
||||||
|
assert d.every(f) == true, "dictionary.every() == true failed";
|
||||||
|
|
||||||
|
assert counter == 5, "Unexpected number of calls for _every() == true";
|
||||||
|
|
||||||
|
counter = 0;
|
||||||
|
a[1] = false;
|
||||||
|
d["two"] = false;
|
||||||
|
|
||||||
|
assert a.every(f) == false, "array.every() == false failed";
|
||||||
|
assert d.every(f) == false, "dictionary.every() == false failed";
|
||||||
|
|
||||||
|
assert counter == 4, "Unexpected number of calls for _every() == false";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test filter
|
||||||
|
{
|
||||||
|
var a = [1, 2, 3, 4];
|
||||||
|
var d = ["one": 1, "two": 2, "three": 3, "four": 4];
|
||||||
|
|
||||||
|
fn f(k, v) {
|
||||||
|
return v % 2 == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert a.filter(f) == [2, 4], "array.filter() failed";
|
||||||
|
assert d.filter(f) == ["two": 2, "four": 4], "dictionary.filter() failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//test forEach
|
//test forEach
|
||||||
{
|
{
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
@@ -65,6 +128,7 @@ import compound;
|
|||||||
assert counter == 4, "forEach ran an unusual number of times";
|
assert counter == 4, "forEach ran an unusual number of times";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//test getKeys
|
//test getKeys
|
||||||
{
|
{
|
||||||
var d = ["foo": 1, "bar": 2];
|
var d = ["foo": 1, "bar": 2];
|
||||||
@@ -127,6 +191,33 @@ import compound;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test some
|
||||||
|
{
|
||||||
|
var a = [false, false, false];
|
||||||
|
var d = ["one": false, "two": false];
|
||||||
|
|
||||||
|
var counter = 0;
|
||||||
|
fn f(k, v) {
|
||||||
|
counter++;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert a.some(f) == false, "array.some() == false failed";
|
||||||
|
assert d.some(f) == false, "dictionary.some() == false failed";
|
||||||
|
|
||||||
|
assert counter == 5, "Unexpected number of calls for _some() == false";
|
||||||
|
|
||||||
|
counter = 0;
|
||||||
|
a[1] = true;
|
||||||
|
d["two"] = true;
|
||||||
|
|
||||||
|
assert a.some(f) == true, "array.some() == true failed";
|
||||||
|
assert d.some(f) == true, "dictionary.some() == true failed";
|
||||||
|
|
||||||
|
assert counter == 4, "Unexpected number of calls for _some() == true";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//test toLower
|
//test toLower
|
||||||
{
|
{
|
||||||
assert "Hello World".toLower() == "hello world", "_toLower() failed";
|
assert "Hello World".toLower() == "hello world", "_toLower() failed";
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
//This is just a check to ensure that unary minus doesn't screw up the AST
|
||||||
|
|
||||||
|
var xrel: int = 0;
|
||||||
|
var yrel: int = 0;
|
||||||
|
|
||||||
|
assert (xrel > 1 || xrel < -1 || yrel > 1 || yrel < -1) == false, "or-chaining bugfix failed";
|
||||||
|
|
||||||
@@ -27,8 +27,8 @@ void error(char* msg) {
|
|||||||
int main() {
|
int main() {
|
||||||
{
|
{
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char* source = Toy_readFile("scripts/call-from-host.toy", &size);
|
const char* source = Toy_readFile("scripts/call-from-host.toy", &size);
|
||||||
unsigned char* tb = Toy_compileString(source, &size);
|
const unsigned char* tb = Toy_compileString(source, &size);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
|
|
||||||
if (!tb) {
|
if (!tb) {
|
||||||
@@ -41,7 +41,7 @@ int main() {
|
|||||||
|
|
||||||
//test answer
|
//test answer
|
||||||
{
|
{
|
||||||
interpreter.printOutput("Testing answer");
|
interpreter.printOutput("Testing answer\n");
|
||||||
|
|
||||||
Toy_LiteralArray arguments;
|
Toy_LiteralArray arguments;
|
||||||
Toy_initLiteralArray(&arguments);
|
Toy_initLiteralArray(&arguments);
|
||||||
@@ -69,7 +69,7 @@ int main() {
|
|||||||
|
|
||||||
//test identity
|
//test identity
|
||||||
{
|
{
|
||||||
interpreter.printOutput("Testing identity");
|
interpreter.printOutput("Testing identity\n");
|
||||||
|
|
||||||
Toy_LiteralArray arguments;
|
Toy_LiteralArray arguments;
|
||||||
Toy_initLiteralArray(&arguments);
|
Toy_initLiteralArray(&arguments);
|
||||||
@@ -104,7 +104,7 @@ int main() {
|
|||||||
|
|
||||||
//test makeCounter (closures)
|
//test makeCounter (closures)
|
||||||
{
|
{
|
||||||
interpreter.printOutput("Testing makeCounter (closures)");
|
interpreter.printOutput("Testing makeCounter (closures)\n");
|
||||||
|
|
||||||
Toy_LiteralArray arguments;
|
Toy_LiteralArray arguments;
|
||||||
Toy_initLiteralArray(&arguments);
|
Toy_initLiteralArray(&arguments);
|
||||||
@@ -209,7 +209,7 @@ int main() {
|
|||||||
|
|
||||||
//test assertion failure
|
//test assertion failure
|
||||||
{
|
{
|
||||||
interpreter.printOutput("Testing assertion failure");
|
interpreter.printOutput("Testing assertion failure\n");
|
||||||
|
|
||||||
Toy_setInterpreterAssert(&interpreter, noPrintFn);
|
Toy_setInterpreterAssert(&interpreter, noPrintFn);
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ int main() {
|
|||||||
{
|
{
|
||||||
//source
|
//source
|
||||||
size_t sourceLength = 0;
|
size_t sourceLength = 0;
|
||||||
char* source = Toy_readFile("scripts/compiler_sample_code.toy", &sourceLength);
|
const char* source = Toy_readFile("scripts/compiler_sample_code.toy", &sourceLength);
|
||||||
|
|
||||||
//test basic compilation & collation
|
//test basic compilation & collation
|
||||||
Toy_Lexer lexer;
|
Toy_Lexer lexer;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ static void noAssertFn(const char* output) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void runBinaryCustom(unsigned char* tb, size_t size) {
|
void runBinaryCustom(const unsigned char* tb, size_t size) {
|
||||||
Toy_Interpreter interpreter;
|
Toy_Interpreter interpreter;
|
||||||
Toy_initInterpreter(&interpreter);
|
Toy_initInterpreter(&interpreter);
|
||||||
|
|
||||||
@@ -42,18 +42,18 @@ void runBinaryCustom(unsigned char* tb, size_t size) {
|
|||||||
Toy_freeInterpreter(&interpreter);
|
Toy_freeInterpreter(&interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runSourceCustom(char* source) {
|
void runSourceCustom(const char* source) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
unsigned char* tb = Toy_compileString(source, &size);
|
const unsigned char* tb = Toy_compileString(source, &size);
|
||||||
if (!tb) {
|
if (!tb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runBinaryCustom(tb, size);
|
runBinaryCustom(tb, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runSourceFileCustom(char* fname) {
|
void runSourceFileCustom(const char* fname) {
|
||||||
size_t size = 0; //not used
|
size_t size = 0; //not used
|
||||||
char* source = Toy_readFile(fname, &size);
|
const char* source = Toy_readFile(fname, &size);
|
||||||
runSourceCustom(source);
|
runSourceCustom(source);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ int main() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
//source
|
//source
|
||||||
char* source = "print null;";
|
const char* source = "print null;";
|
||||||
|
|
||||||
//test basic compilation & collation
|
//test basic compilation & collation
|
||||||
Toy_Lexer lexer;
|
Toy_Lexer lexer;
|
||||||
@@ -88,7 +88,7 @@ int main() {
|
|||||||
|
|
||||||
//collate
|
//collate
|
||||||
int size = 0;
|
int size = 0;
|
||||||
unsigned char* bytecode = Toy_collateCompiler(&compiler, &size);
|
const unsigned char* bytecode = Toy_collateCompiler(&compiler, &size);
|
||||||
|
|
||||||
//NOTE: suppress print output for testing
|
//NOTE: suppress print output for testing
|
||||||
Toy_setInterpreterPrint(&interpreter, noPrintFn);
|
Toy_setInterpreterPrint(&interpreter, noPrintFn);
|
||||||
@@ -106,7 +106,7 @@ int main() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
//run each file in tests/scripts/
|
//run each file in tests/scripts/
|
||||||
char* filenames[] = {
|
const char* filenames[] = {
|
||||||
"arithmetic.toy",
|
"arithmetic.toy",
|
||||||
"casting.toy",
|
"casting.toy",
|
||||||
"coercions.toy",
|
"coercions.toy",
|
||||||
@@ -126,6 +126,7 @@ int main() {
|
|||||||
"long-dictionary.toy",
|
"long-dictionary.toy",
|
||||||
"long-literals.toy",
|
"long-literals.toy",
|
||||||
"native-functions.toy",
|
"native-functions.toy",
|
||||||
|
"or-chaining-bugfix.toy",
|
||||||
"panic-within-functions.toy",
|
"panic-within-functions.toy",
|
||||||
"ternary-expressions.toy",
|
"ternary-expressions.toy",
|
||||||
"types.toy",
|
"types.toy",
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ static void errorWrapper(const char* output) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "%s" TOY_CC_RESET, output);
|
fprintf(stderr, TOY_CC_ERROR "%s" TOY_CC_RESET, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runBinaryWithLibrary(unsigned char* tb, size_t size, char* library, Toy_HookFn hook) {
|
void runBinaryWithLibrary(const unsigned char* tb, size_t size, const char* library, Toy_HookFn hook) {
|
||||||
Toy_Interpreter interpreter;
|
Toy_Interpreter interpreter;
|
||||||
Toy_initInterpreter(&interpreter);
|
Toy_initInterpreter(&interpreter);
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ void runBinaryWithLibrary(unsigned char* tb, size_t size, char* library, Toy_Hoo
|
|||||||
Toy_freeInterpreter(&interpreter);
|
Toy_freeInterpreter(&interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runBinaryQuietly(unsigned char* tb, size_t size) {
|
void runBinaryQuietly(const unsigned char* tb, size_t size) {
|
||||||
Toy_Interpreter interpreter;
|
Toy_Interpreter interpreter;
|
||||||
Toy_initInterpreter(&interpreter);
|
Toy_initInterpreter(&interpreter);
|
||||||
|
|
||||||
@@ -111,14 +111,14 @@ int main() {
|
|||||||
|
|
||||||
//compile the source
|
//compile the source
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char* source = Toy_readFile(fname, &size);
|
const char* source = Toy_readFile(fname, &size);
|
||||||
if (!source) {
|
if (!source) {
|
||||||
printf(TOY_CC_ERROR "Failed to load file: %s\n" TOY_CC_RESET, fname);
|
printf(TOY_CC_ERROR "Failed to load file: %s\n" TOY_CC_RESET, fname);
|
||||||
failedAsserts++;
|
failedAsserts++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* tb = Toy_compileString(source, &size);
|
const unsigned char* tb = Toy_compileString(source, &size);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
|
|
||||||
if (!tb) {
|
if (!tb) {
|
||||||
@@ -146,14 +146,14 @@ int main() {
|
|||||||
|
|
||||||
//compile the source
|
//compile the source
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char* source = Toy_readFile(fname, &size);
|
const char* source = Toy_readFile(fname, &size);
|
||||||
if (!source) {
|
if (!source) {
|
||||||
printf(TOY_CC_ERROR "Failed to load file: %s\n" TOY_CC_RESET, fname);
|
printf(TOY_CC_ERROR "Failed to load file: %s\n" TOY_CC_RESET, fname);
|
||||||
failedAsserts++;
|
failedAsserts++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* tb = Toy_compileString(source, &size);
|
const unsigned char* tb = Toy_compileString(source, &size);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
|
|
||||||
if (!tb) {
|
if (!tb) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ static void noErrorFn(const char* output) {
|
|||||||
errorsTriggered++;
|
errorsTriggered++;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* compileStringCustom(char* source, size_t* size) {
|
const unsigned char* compileStringCustom(const char* source, size_t* size) {
|
||||||
Toy_Lexer lexer;
|
Toy_Lexer lexer;
|
||||||
Toy_Parser parser;
|
Toy_Parser parser;
|
||||||
Toy_Compiler compiler;
|
Toy_Compiler compiler;
|
||||||
@@ -50,7 +50,7 @@ unsigned char* compileStringCustom(char* source, size_t* size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//get the bytecode dump
|
//get the bytecode dump
|
||||||
unsigned char* tb = Toy_collateCompiler(&compiler, (int*)(size));
|
const unsigned char* tb = Toy_collateCompiler(&compiler, (int*)(size));
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
Toy_freeCompiler(&compiler);
|
Toy_freeCompiler(&compiler);
|
||||||
@@ -61,7 +61,7 @@ unsigned char* compileStringCustom(char* source, size_t* size) {
|
|||||||
return tb;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void runBinaryCustom(unsigned char* tb, size_t size) {
|
void runBinaryCustom(const unsigned char* tb, size_t size) {
|
||||||
Toy_Interpreter interpreter;
|
Toy_Interpreter interpreter;
|
||||||
Toy_initInterpreter(&interpreter);
|
Toy_initInterpreter(&interpreter);
|
||||||
|
|
||||||
@@ -73,18 +73,18 @@ void runBinaryCustom(unsigned char* tb, size_t size) {
|
|||||||
Toy_freeInterpreter(&interpreter);
|
Toy_freeInterpreter(&interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runSourceCustom(char* source) {
|
void runSourceCustom(const char* source) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
unsigned char* tb = compileStringCustom(source, &size);
|
const unsigned char* tb = compileStringCustom(source, &size);
|
||||||
if (!tb) {
|
if (!tb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runBinaryCustom(tb, size);
|
runBinaryCustom(tb, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runSourceFileCustom(char* fname) {
|
void runSourceFileCustom(const char* fname) {
|
||||||
size_t size = 0; //not used
|
size_t size = 0; //not used
|
||||||
char* source = Toy_readFile(fname, &size);
|
const char* source = Toy_readFile(fname, &size);
|
||||||
runSourceCustom(source);
|
runSourceCustom(source);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ static int consume(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
|||||||
int main() {
|
int main() {
|
||||||
{
|
{
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char* source = Toy_readFile("scripts/opaque-data-type.toy", &size);
|
const char* source = Toy_readFile("scripts/opaque-data-type.toy", &size);
|
||||||
unsigned char* tb = Toy_compileString(source, &size);
|
const unsigned char* tb = Toy_compileString(source, &size);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
|
|
||||||
if (!tb) {
|
if (!tb) {
|
||||||
|
|||||||
+5
-5
@@ -11,7 +11,7 @@
|
|||||||
int main() {
|
int main() {
|
||||||
{
|
{
|
||||||
//source
|
//source
|
||||||
char* source = "print null;";
|
const char* source = "print null;";
|
||||||
|
|
||||||
//test init & quit
|
//test init & quit
|
||||||
Toy_Lexer lexer;
|
Toy_Lexer lexer;
|
||||||
@@ -24,7 +24,7 @@ int main() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
//source
|
//source
|
||||||
char* source = "print null;";
|
const char* source = "print null;";
|
||||||
|
|
||||||
//test parsing
|
//test parsing
|
||||||
Toy_Lexer lexer;
|
Toy_Lexer lexer;
|
||||||
@@ -58,7 +58,7 @@ int main() {
|
|||||||
{
|
{
|
||||||
//get the source file
|
//get the source file
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char* source = Toy_readFile("scripts/parser_sample_code.toy", &size);
|
const char* source = Toy_readFile("scripts/parser_sample_code.toy", &size);
|
||||||
|
|
||||||
//test parsing a chunk of junk (valgrind will find leaks)
|
//test parsing a chunk of junk (valgrind will find leaks)
|
||||||
Toy_Lexer lexer;
|
Toy_Lexer lexer;
|
||||||
@@ -85,7 +85,7 @@ int main() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
//test parsing of escaped characters
|
//test parsing of escaped characters
|
||||||
char* source = "print \"\\\"\";"; //NOTE: this string goes through two layers of escaping
|
const char* source = "print \"\\\"\";"; //NOTE: this string goes through two layers of escaping
|
||||||
|
|
||||||
//test parsing
|
//test parsing
|
||||||
Toy_Lexer lexer;
|
Toy_Lexer lexer;
|
||||||
@@ -123,7 +123,7 @@ int main() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
//test parsing of underscored numbers
|
//test parsing of underscored numbers
|
||||||
char* source = "print 1_000_000;";
|
const char* source = "print 1_000_000;";
|
||||||
|
|
||||||
//test parsing
|
//test parsing
|
||||||
Toy_Lexer lexer;
|
Toy_Lexer lexer;
|
||||||
|
|||||||
Reference in New Issue
Block a user