Compare commits

..

16 Commits

Author SHA1 Message Date
Ratstail91 1064b69d04 BUGFIX: Integer and float comparisons always return true 2023-02-26 01:27:21 +11:00
Ratstail91 e9b347acb6 MSVC + Box Engine are dumber than a bag of rocks 2023-02-25 04:40:12 +11:00
Ratstail91 071c8da2aa Visual Studio broke itself - fixed 2023-02-25 04:28:07 +11:00
Ratstail91 d6538812bf Merge branch 'main' of https://github.com/Ratstail91/Toy 2023-02-25 04:18:03 +11:00
Ratstail91 3aeddff736 Tweaks to dictionary for performance 2023-02-24 22:13:50 +11:00
Ratstail91 c88c1b125d Merge remote-tracking branch 'refs/remotes/origin/main' 2023-02-24 21:53:42 +11:00
Kayne Ruse 1513ba9878 tweaked scripts folder 2023-02-23 22:45:38 +11:00
Kayne Ruse bc0289c3f4 tweaked scripts folder 2023-02-23 20:23:10 +11:00
Kayne Ruse 92c71a374d Implemented a basic random library 2023-02-23 19:19:17 +11:00
Kayne Ruse e0547474b8 Merge remote-tracking branch 'refs/remotes/origin/main' 2023-02-23 18:37:11 +11:00
Kayne Ruse 3e6d21afbb Added abs(), hash() to libstandard 2023-02-23 18:36:12 +11:00
Kayne Ruse d3df01c1c4 Updated .gitignore 2023-02-23 03:33:52 +11:00
Ratstail91 cdca6fa45c Fixed directory in solution file 2023-02-22 20:06:48 +11:00
Kayne Ruse 1dde9d8f29 Improved error message in set() and push()
The actual issue was that the type check wasn't catching the issue, so
it reached the scope before it was caught. Fixed it, anyway.
2023-02-20 13:04:35 +00:00
Kayne Ruse 7f0f17b6e0 Patched up failures from Toy_parseIdentifierToValue
I really don't like that function - it needs to be replaced.
2023-02-20 06:11:30 +00:00
Kayne Ruse 3507104121 Fixed indexAccess potentially going awry with bad inputs
There's always one or two that slip through
2023-02-20 05:28:25 +00:00
28 changed files with 897 additions and 328 deletions
+2
View File
@@ -19,6 +19,8 @@ bin/
*.db
*.o
*.a
*.so
*.dll
*.exe
*.meta
*.log
+11 -6
View File
@@ -113,18 +113,16 @@
<AdditionalLibraryDirectories>$(SolutionDir)out\$(Configuration)</AdditionalLibraryDirectories>
</Link>
<ClCompile>
<AdditionalIncludeDirectories>C:\Users\kayne\Desktop\Toy\source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)/source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<PreprocessorDefinitions>
</PreprocessorDefinitions>
<PreprocessorDefinitions>LIB_RUNNER_EXPORT</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<PreprocessorDefinitions>
</PreprocessorDefinitions>
<AdditionalIncludeDirectories>C:\Users\kayne\Desktop\Toy\source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>LIB_RUNNER_EXPORT</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)/source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(SolutionDir)out\$(Configuration)</AdditionalLibraryDirectories>
@@ -133,6 +131,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="repl\lib_about.c" />
<ClCompile Include="repl\lib_random.c" />
<ClCompile Include="repl\lib_runner.c" />
<ClCompile Include="repl\lib_standard.c" />
<ClCompile Include="repl\repl_main.c" />
@@ -140,10 +139,16 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="repl\lib_about.h" />
<ClInclude Include="repl\lib_random.h" />
<ClInclude Include="repl\lib_runner.h" />
<ClInclude Include="repl\lib_standard.h" />
<ClInclude Include="repl\repl_tools.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="Toy.vcxproj">
<Project>{26360002-cc2a-469a-9b28-ba0c1af41657}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
+196
View File
@@ -0,0 +1,196 @@
#include "lib_random.h"
#include "toy_memory.h"
static int hashInt(int x) {
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = (x >> 16) ^ x;
return x;
}
typedef struct Toy_RandomGenerator {
int seed; //mutated with each call
} Toy_RandomGenerator;
//Toy native functions
static int nativeCreateRandomGenerator(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//arguments
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to createRandomGenerator\n");
return -1;
}
//get the seed argument
Toy_Literal seedLiteral = Toy_popLiteralArray(arguments);
Toy_Literal seedLiteralIdn = seedLiteral;
if (TOY_IS_IDENTIFIER(seedLiteral) && Toy_parseIdentifierToValue(interpreter, &seedLiteral)) {
Toy_freeLiteral(seedLiteralIdn);
}
if (TOY_IS_IDENTIFIER(seedLiteral)) {
Toy_freeLiteral(seedLiteral);
return -1;
}
if (!TOY_IS_INTEGER(seedLiteral)) {
interpreter->errorOutput("Incorrect literal type passed to createRandomGenerator");
Toy_freeLiteral(seedLiteral);
return -1;
}
//generate the generator object
Toy_RandomGenerator* generator = TOY_ALLOCATE(Toy_RandomGenerator, 1);
generator->seed = TOY_AS_INTEGER(seedLiteral);
Toy_Literal generatorLiteral = TOY_TO_OPAQUE_LITERAL(generator, TOY_OPAQUE_TAG_RANDOM);
//return and cleanup
Toy_pushLiteralArray(&interpreter->stack, generatorLiteral);
Toy_freeLiteral(seedLiteral);
Toy_freeLiteral(generatorLiteral);
return 1;
}
static int nativeGenerateRandomNumber(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to generateRandomNumber\n");
return -1;
}
//get the runner object
Toy_Literal generatorLiteral = Toy_popLiteralArray(arguments);
Toy_Literal generatorLiteralIdn = generatorLiteral;
if (TOY_IS_IDENTIFIER(generatorLiteral) && Toy_parseIdentifierToValue(interpreter, &generatorLiteral)) {
Toy_freeLiteral(generatorLiteralIdn);
}
if (TOY_IS_IDENTIFIER(generatorLiteral)) {
Toy_freeLiteral(generatorLiteral);
return -1;
}
if (TOY_GET_OPAQUE_TAG(generatorLiteral) != TOY_OPAQUE_TAG_RANDOM) {
interpreter->errorOutput("Unrecognized opaque literal in generateRandomNumber\n");
return -1;
}
Toy_RandomGenerator* generator = TOY_AS_OPAQUE(generatorLiteral);
//generate the new value and package up the return
generator->seed = hashInt(generator->seed);
Toy_Literal resultLiteral = TOY_TO_INTEGER_LITERAL(generator->seed);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
//cleanup
Toy_freeLiteral(generatorLiteral);
Toy_freeLiteral(resultLiteral);
return 0;
}
static int nativeFreeRandomGenerator(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to freeRandomGenerator\n");
return -1;
}
//get the runner object
Toy_Literal generatorLiteral = Toy_popLiteralArray(arguments);
Toy_Literal generatorLiteralIdn = generatorLiteral;
if (TOY_IS_IDENTIFIER(generatorLiteral) && Toy_parseIdentifierToValue(interpreter, &generatorLiteral)) {
Toy_freeLiteral(generatorLiteralIdn);
}
if (TOY_IS_IDENTIFIER(generatorLiteral)) {
Toy_freeLiteral(generatorLiteral);
return -1;
}
if (TOY_GET_OPAQUE_TAG(generatorLiteral) != TOY_OPAQUE_TAG_RANDOM) {
interpreter->errorOutput("Unrecognized opaque literal in freeRandomGenerator\n");
return -1;
}
Toy_RandomGenerator* generator = TOY_AS_OPAQUE(generatorLiteral);
//clear out the runner object
TOY_FREE(Toy_RandomGenerator, generator);
Toy_freeLiteral(generatorLiteral);
return 0;
}
//call the hook
typedef struct Natives {
const char* name;
Toy_NativeFn fn;
} Natives;
int Toy_hookRandom(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
//build the natives list
Natives natives[] = {
{"createRandomGenerator", nativeCreateRandomGenerator},
{"generateRandomNumber", nativeGenerateRandomNumber},
{"freeRandomGenerator", nativeFreeRandomGenerator},
{NULL, NULL}
};
//store the library in an aliased dictionary
if (!TOY_IS_NULL(alias)) {
//make sure the name isn't taken
if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) {
interpreter->errorOutput("Can't override an existing variable\n");
Toy_freeLiteral(alias);
return -1;
}
//create the dictionary to load up with functions
Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
Toy_initLiteralDictionary(dictionary);
//load the dict with functions
for (int i = 0; natives[i].name; i++) {
Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name));
Toy_Literal func = TOY_TO_FUNCTION_NATIVE_LITERAL(natives[i].fn);
Toy_setLiteralDictionary(dictionary, name, func);
Toy_freeLiteral(name);
Toy_freeLiteral(func);
}
//build the type
Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true);
Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true);
Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true);
TOY_TYPE_PUSH_SUBTYPE(&type, strType);
TOY_TYPE_PUSH_SUBTYPE(&type, fnType);
//set scope
Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary);
Toy_declareScopeVariable(interpreter->scope, alias, type);
Toy_setScopeVariable(interpreter->scope, alias, dict, false);
//cleanup
Toy_freeLiteral(dict);
Toy_freeLiteral(type);
return 0;
}
//default
for (int i = 0; natives[i].name; i++) {
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
}
return 0;
}
+7
View File
@@ -0,0 +1,7 @@
#pragma once
#include "toy_interpreter.h"
int Toy_hookRandom(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
#define TOY_OPAQUE_TAG_RANDOM 200
+42
View File
@@ -33,6 +33,11 @@ static int nativeLoadScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argu
Toy_freeLiteral(drivePathLiteralIdn);
}
if (TOY_IS_IDENTIFIER(drivePathLiteral)) {
Toy_freeLiteral(drivePathLiteral);
return -1;
}
Toy_Literal filePathLiteral = Toy_getFilePathLiteral(interpreter, &drivePathLiteral);
if (TOY_IS_NULL(filePathLiteral)) {
@@ -103,6 +108,11 @@ static int nativeLoadScriptBytecode(Toy_Interpreter* interpreter, Toy_LiteralArr
Toy_freeLiteral(drivePathLiteralIdn);
}
if (TOY_IS_IDENTIFIER(drivePathLiteral)) {
Toy_freeLiteral(drivePathLiteral);
return -1;
}
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
@@ -213,6 +223,11 @@ static int nativeRunScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
Toy_freeLiteral(runnerIdn);
}
if (TOY_IS_IDENTIFIER(runnerLiteral)) {
Toy_freeLiteral(runnerLiteral);
return -1;
}
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
interpreter->errorOutput("Unrecognized opaque literal in runScript\n");
return -1;
@@ -260,6 +275,12 @@ static int nativeGetScriptVar(Toy_Interpreter* interpreter, Toy_LiteralArray* ar
Toy_freeLiteral(runnerIdn);
}
if (TOY_IS_IDENTIFIER(varName) || TOY_IS_IDENTIFIER(runnerLiteral)) {
Toy_freeLiteral(varName);
Toy_freeLiteral(runnerLiteral);
return -1;
}
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
interpreter->errorOutput("Unrecognized opaque literal in getScriptVar\n");
return -1;
@@ -332,6 +353,12 @@ static int nativeCallScriptFn(Toy_Interpreter* interpreter, Toy_LiteralArray* ar
Toy_freeLiteral(runnerIdn);
}
if (TOY_IS_IDENTIFIER(varName) || TOY_IS_IDENTIFIER(runnerLiteral)) {
Toy_freeLiteral(varName);
Toy_freeLiteral(runnerLiteral);
return -1;
}
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
interpreter->errorOutput("Unrecognized opaque literal in callScriptFn\n");
return -1;
@@ -401,6 +428,11 @@ static int nativeResetScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arg
Toy_freeLiteral(runnerIdn);
}
if (TOY_IS_IDENTIFIER(runnerLiteral)) {
Toy_freeLiteral(runnerLiteral);
return -1;
}
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
interpreter->errorOutput("Unrecognized opaque literal in resetScript\n");
return -1;
@@ -437,6 +469,11 @@ static int nativeFreeScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argu
Toy_freeLiteral(runnerIdn);
}
if (TOY_IS_IDENTIFIER(runnerLiteral)) {
Toy_freeLiteral(runnerLiteral);
return -1;
}
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
interpreter->errorOutput("Unrecognized opaque literal in freeScript\n");
return -1;
@@ -471,6 +508,11 @@ static int nativeCheckScriptDirty(Toy_Interpreter* interpreter, Toy_LiteralArray
Toy_freeLiteral(runnerIdn);
}
if (TOY_IS_IDENTIFIER(runnerLiteral)) {
Toy_freeLiteral(runnerLiteral);
return -1;
}
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
interpreter->errorOutput("Unrecognized opaque literal in checkScriptDirty\n");
return -1;
+25 -6
View File
@@ -5,12 +5,31 @@
int Toy_hookRunner(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
//file system API - these need to be set by the host
TOY_API void Toy_initDriveDictionary();
TOY_API void Toy_freeDriveDictionary();
TOY_API Toy_LiteralDictionary* Toy_getDriveDictionary();
#define TOY_OPAQUE_TAG_RUNNER 100
//platform/compiler-specific instructions - because MSVC + Box Engine are dumber than a bag of rocks
#if defined(__linux__) || defined(__MINGW32__) || defined(__GNUC__)
#define LIB_RUNNER_API extern
#elif defined(_MSC_VER)
#ifndef LIB_RUNNER_EXPORT
#define LIB_RUNNER_API __declspec(dllimport)
#else
#define LIB_RUNNER_API __declspec(dllexport)
#endif
#else
#define LIB_RUNNER_API extern
#endif
//file system API - these need to be set by the host
LIB_RUNNER_API void Toy_initDriveDictionary();
LIB_RUNNER_API void Toy_freeDriveDictionary();
LIB_RUNNER_API Toy_LiteralDictionary* Toy_getDriveDictionary();
//file system API - for use with other libs
Toy_Literal Toy_getFilePathLiteral(Toy_Interpreter* interpreter, Toy_Literal* drivePathLiteral);
LIB_RUNNER_API Toy_Literal Toy_getFilePathLiteral(Toy_Interpreter* interpreter, Toy_Literal* drivePathLiteral);
+188 -3
View File
@@ -7,6 +7,49 @@
#include <time.h>
#include <ctype.h>
static int nativeAbs(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to abs\n");
return -1;
}
//get the self
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);
}
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
return -1;
}
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
interpreter->errorOutput("Incorrect argument type passed to abs\n");
Toy_freeLiteral(selfLiteral);
return -1;
}
Toy_Literal result;
if (TOY_IS_INTEGER(selfLiteral)) {
result = TOY_TO_INTEGER_LITERAL( TOY_AS_INTEGER(selfLiteral) > 0 ? TOY_AS_INTEGER(selfLiteral) : -TOY_AS_INTEGER(selfLiteral) );
}
if (TOY_IS_FLOAT(selfLiteral)) {
result = TOY_TO_FLOAT_LITERAL( TOY_AS_FLOAT(selfLiteral) > 0 ? TOY_AS_FLOAT(selfLiteral) : -TOY_AS_FLOAT(selfLiteral) );
}
Toy_pushLiteralArray(&interpreter->stack, result);
Toy_freeLiteral(result);
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativeClock(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 0) {
@@ -54,6 +97,12 @@ static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
Toy_freeLiteral(otherLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(otherLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(otherLiteral);
return -1;
}
//for each self type
if (TOY_IS_ARRAY(selfLiteral)) {
if (!TOY_IS_ARRAY(otherLiteral)) {
@@ -164,6 +213,12 @@ static int nativeContainsKey(Toy_Interpreter* interpreter, Toy_LiteralArray* arg
Toy_freeLiteral(keyLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(keyLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(keyLiteral);
return -1;
}
//check type
if (!(/* TOY_IS_ARRAY(selfLiteral) || */ TOY_IS_DICTIONARY(selfLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to containsKey\n");
@@ -209,6 +264,12 @@ static int nativeContainsValue(Toy_Interpreter* interpreter, Toy_LiteralArray* a
Toy_freeLiteral(valueLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(valueLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(valueLiteral);
return -1;
}
//check type
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to containsValue\n");
@@ -279,6 +340,12 @@ static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
Toy_freeLiteral(fnLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//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");
@@ -395,6 +462,12 @@ static int nativeFilter(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
Toy_freeLiteral(fnLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//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");
@@ -509,6 +582,12 @@ static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_freeLiteral(fnLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//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 forEach\n");
@@ -581,6 +660,11 @@ static int nativeGetKeys(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_freeLiteral(selfLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
return -1;
}
//check type
if (!TOY_IS_DICTIONARY(selfLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to getKeys\n");
@@ -626,6 +710,11 @@ static int nativeGetValues(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
Toy_freeLiteral(selfLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
return -1;
}
//check type
if (!TOY_IS_DICTIONARY(selfLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to getValues\n");
@@ -656,6 +745,36 @@ static int nativeGetValues(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
return 1;
}
static int nativeHash(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to hash\n");
return -1;
}
//get the self
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);
}
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
return -1;
}
Toy_Literal result = TOY_TO_INTEGER_LITERAL(Toy_hashLiteral(selfLiteral));
Toy_pushLiteralArray(&interpreter->stack, result);
Toy_freeLiteral(result);
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativeIndexOf(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 2) {
@@ -678,6 +797,12 @@ static int nativeIndexOf(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_freeLiteral(valueLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(valueLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(valueLiteral);
return -1;
}
//check type
if (!TOY_IS_ARRAY(selfLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to indexOf\n");
@@ -725,6 +850,12 @@ static int nativeMap(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(fnLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//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 map\n");
@@ -834,6 +965,13 @@ static int nativeReduce(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
Toy_freeLiteral(fnLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(defaultLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(defaultLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//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 reduce\n");
@@ -929,6 +1067,12 @@ static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(fnLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//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");
@@ -1093,6 +1237,12 @@ static int nativeSort(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(fnLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//check type
if (!TOY_IS_ARRAY(selfLiteral) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to sort\n");
@@ -1129,6 +1279,11 @@ static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_freeLiteral(selfLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
return -1;
}
if (!TOY_IS_STRING(selfLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to toLower\n");
Toy_freeLiteral(selfLiteral);
@@ -1190,6 +1345,11 @@ static int nativeToString(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
Toy_freeLiteral(selfLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
return -1;
}
//BUGFIX: probably an undefined variable
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
@@ -1229,6 +1389,11 @@ static int nativeToUpper(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_freeLiteral(selfLiteralIdn);
}
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
return -1;
}
if (!TOY_IS_STRING(selfLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to toUpper\n");
Toy_freeLiteral(selfLiteral);
@@ -1289,7 +1454,13 @@ static int nativeTrim(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(selfLiteralIdn);
}
if (!TOY_IS_STRING(selfLiteral)) {
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(trimCharsLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(trimCharsLiteral);
return -1;
}
if (!TOY_IS_STRING(selfLiteral) || !TOY_IS_STRING(trimCharsLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to trim\n");
Toy_freeLiteral(trimCharsLiteral);
Toy_freeLiteral(selfLiteral);
@@ -1400,7 +1571,13 @@ static int nativeTrimBegin(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
Toy_freeLiteral(selfLiteralIdn);
}
if (!TOY_IS_STRING(selfLiteral)) {
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(trimCharsLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(trimCharsLiteral);
return -1;
}
if (!TOY_IS_STRING(selfLiteral) || !TOY_IS_STRING(trimCharsLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to trimBegin\n");
Toy_freeLiteral(trimCharsLiteral);
Toy_freeLiteral(selfLiteral);
@@ -1488,7 +1665,13 @@ static int nativeTrimEnd(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_freeLiteral(selfLiteralIdn);
}
if (!TOY_IS_STRING(selfLiteral)) {
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(trimCharsLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(trimCharsLiteral);
return -1;
}
if (!TOY_IS_STRING(selfLiteral) || !TOY_IS_STRING(trimCharsLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to trimEnd\n");
Toy_freeLiteral(trimCharsLiteral);
Toy_freeLiteral(selfLiteral);
@@ -1557,6 +1740,7 @@ typedef struct Natives {
int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
//build the natives list
Natives natives[] = {
{"abs", nativeAbs},
{"clock", nativeClock},
{"concat", nativeConcat}, //array, dictionary, string
{"containsKey", nativeContainsKey}, //dictionary
@@ -1566,6 +1750,7 @@ int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L
{"forEach", nativeForEach}, //array, dictionary
{"getKeys", nativeGetKeys}, //dictionary
{"getValues", nativeGetValues}, //dictionary
{"hash", nativeHash},
{"indexOf", nativeIndexOf}, //array
{"map", nativeMap}, //array, dictionary
{"reduce", nativeReduce}, //array, dictionary
+2
View File
@@ -1,6 +1,7 @@
#include "repl_tools.h"
#include "lib_about.h"
#include "lib_standard.h"
#include "lib_random.h"
#include "lib_runner.h"
#include "toy_console_colors.h"
@@ -29,6 +30,7 @@ void repl(const char* initialInput) {
//inject the libs
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom);
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
for(;;) {
+2
View File
@@ -1,6 +1,7 @@
#include "repl_tools.h"
#include "lib_about.h"
#include "lib_standard.h"
#include "lib_random.h"
#include "lib_runner.h"
#include "toy_console_colors.h"
@@ -112,6 +113,7 @@ void Toy_runBinary(const unsigned char* tb, size_t size) {
//inject the libs
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom);
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
Toy_runInterpreter(&interpreter, tb, (int)size);
-125
View File
@@ -1,125 +0,0 @@
import node;
//constants
var SPEED: int const = 10;
//variables
var parent: opaque = null;
var posX: int = 50;
var posY: int = 50;
var WIDTH: int const = 100;
var HEIGHT: int const = 100;
var xspeed: int = 0;
var yspeed: int = 0;
//accessors - variables are private, functions are public
fn getX(node: opaque) {
return posX;
}
fn getY(node: opaque) {
return posY;
}
//lifecycle functions
fn onInit(node: opaque) {
print "render.toy:onInit() called\n";
node.loadTexture("sprites:/character.png");
parent = node.getNodeParent();
}
fn onStep(node: opaque) {
posX += xspeed;
posY += yspeed;
}
fn onFree(node: opaque) {
print "render.toy:onFree() called\n";
node.freeTexture();
}
fn onDraw(node: opaque) {
// print "render.toy:onDraw() called\n";
var px = parent.callNode("getX");
var py = parent.callNode("getY");
if (px == null) {
px = 0;
}
if (py == null) {
py = 0;
}
node.drawNode(posX + px, posY + py, WIDTH, HEIGHT);
}
//event functions
fn onKeyDown(node: opaque, event: string) {
if (event == "character_up") {
yspeed -= SPEED;
return;
}
if (event == "character_down") {
yspeed += SPEED;
return;
}
if (event == "character_left") {
xspeed -= SPEED;
return;
}
if (event == "character_right") {
xspeed += SPEED;
return;
}
}
fn onKeyUp(node: opaque, event: string) {
if (event == "character_up" && yspeed < 0) {
yspeed = 0;
return;
}
if (event == "character_down" && yspeed > 0) {
yspeed = 0;
return;
}
if (event == "character_left" && xspeed < 0) {
xspeed = 0;
return;
}
if (event == "character_right" && xspeed > 0) {
xspeed = 0;
return;
}
}
fn onMouseMotion(node: opaque, x: int, y: int, xrel: int, yrel: int) {
// print "entity.toy:onMouseMotion(" + string x + ", " + string y + ", " + string xrel + ", " + string yrel + ")\n";
}
fn onMouseButtonDown(node: opaque, x: int, y: int, button: string) {
// print "entity.toy:onMouseButtonDown(" + string x + ", " + string y + ", " + button + ")\n";
//jump to pos
posX = x - WIDTH / 2;
posY = y - HEIGHT / 2;
}
fn onMouseButtonUp(node: opaque, x: int, y: int, button: string) {
// print "entity.toy:onMouseButtonUp(" + string x + ", " + string y + ", " + button + ")\n";
}
fn onMouseWheel(node: opaque, xrel: int, yrel: int) {
// print "entity.toy:onMouseWheel(" + string xrel + ", " + string yrel + ")\n";
}
-89
View File
@@ -1,89 +0,0 @@
//single line comment
/*
multi line comment
*/
//test primitive literals
print "hello world";
print null;
print true;
print false;
print 42;
print 3.14;
print -69;
print -4.20;
print 2 + (3 * 3);
//test operators (integers)
print 1 + 1;
print 1 - 1;
print 2 * 2;
print 1 / 2;
print 4 % 2;
//test operators (floats)
print 1.0 + 1.0;
print 1.0 - 1.0;
print 2.0 * 2.0;
print 1.0 / 2.0;
//test scopes
{
print "This statement is within a scope.";
{
print "This is a deeper scope.";
}
}
print "Back to the outer scope.";
//test scope will delegate to higher scope
var a = 1;
{
a = 2;
print a;
}
print a;
//test scope will shadow higher scope on redefine
var b: int = 3;
{
var b = 4;
print b;
}
print b;
//test compounds, repeatedly
print [1, 2, 3];
print [4, 5];
print ["key":"value"];
print [1, 2, 3];
print [4, 5];
print ["key":"value"];
//test empties
print [];
print [:];
//test nested compounds
print [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
//var declarations
var x = 31;
var y : int = 42;
var arr : [int] = [1, 2, 3, 42];
var dict : [string:int] = ["hello": 1, "world":2];
//printing expressions
print x;
print x + y;
print arr;
print dict;
//test asserts at the end of the file
assert x, "This won't be seen";
assert true, "This won't be seen";
assert false, "This is a failed assert, and will end execution";
print "This will not be printed because of the above assert";
+3 -3
View File
@@ -34,8 +34,8 @@ var tiles: [[int]] const = [
];
var tileset: [int: string] const = [
0: " ",
1: " X "
0: " ",
1: "X "
];
//variables
@@ -48,7 +48,7 @@ fn draw() {
for (var i: int = 0; i < WIDTH; i++) {
//draw the player pos
if (i == posX && j == posY) {
print " O ";
print "O ";
continue;
}
+36
View File
@@ -0,0 +1,36 @@
/*
Since this is a pseudo-random generator, and there's no internal state to the algorithm other
than the generator opaque, there needs to be a "call counter" (current depth) to shuffle the
initial seeds, otherwise generators created from other generators will resemble their parents,
but one call greater.
*/
import standard;
import random;
var DEPTH: int const = 20;
var levels = [];
//generate the level seeds
var generator: opaque = createRandomGenerator(clock().hash());
for (var i: int = 0; i < DEPTH; i++) {
levels.push(generator.generateRandomNumber());
}
generator.freeRandomGenerator();
//generate "levels" of a roguelike
for (var i = 0; i < DEPTH; i++) {
var rng: opaque = createRandomGenerator(levels[i] + i);
print "---";
print levels[i];
print rng.generateRandomNumber();
print rng.generateRandomNumber();
print rng.generateRandomNumber();
rng.freeRandomGenerator();
}
View File
+152 -34
View File
@@ -279,6 +279,17 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(idn);
}
if (TOY_IS_IDENTIFIER(first) || TOY_IS_IDENTIFIER(second) || TOY_IS_IDENTIFIER(third)) {
Toy_freeLiteral(op);
Toy_freeLiteral(assign);
Toy_freeLiteral(third);
Toy_freeLiteral(second);
Toy_freeLiteral(first);
Toy_freeLiteral(compound);
return -1;
}
//second and third are bad args to dictionaries
if (!TOY_IS_NULL(second) || !TOY_IS_NULL(third)) {
interpreter->errorOutput("Index slicing not allowed for dictionaries\n");
@@ -401,6 +412,17 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(idn);
}
if (TOY_IS_IDENTIFIER(first) || TOY_IS_IDENTIFIER(second) || TOY_IS_IDENTIFIER(third)) {
Toy_freeLiteral(op);
Toy_freeLiteral(assign);
Toy_freeLiteral(third);
Toy_freeLiteral(second);
Toy_freeLiteral(first);
Toy_freeLiteral(compound);
return -1;
}
//handle each error case
if (!TOY_IS_INTEGER(first) || TOY_AS_INTEGER(first) < 0 || TOY_AS_INTEGER(first) >= TOY_AS_ARRAY(compound)->count) {
interpreter->errorOutput("Bad first indexing\n");
@@ -543,6 +565,17 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(idn);
}
if (TOY_IS_IDENTIFIER(first) || TOY_IS_IDENTIFIER(second) || TOY_IS_IDENTIFIER(third)) {
Toy_freeLiteral(op);
Toy_freeLiteral(assign);
Toy_freeLiteral(third);
Toy_freeLiteral(second);
Toy_freeLiteral(first);
Toy_freeLiteral(compound);
return -1;
}
//handle each error case
if (!TOY_IS_INTEGER(first) || TOY_AS_INTEGER(first) < 0 || TOY_AS_INTEGER(first) >= TOY_AS_ARRAY(compound)->count) {
interpreter->errorOutput("Bad first indexing assignment\n");
@@ -705,6 +738,17 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(idn);
}
if (TOY_IS_IDENTIFIER(first)) {
Toy_freeLiteral(op);
Toy_freeLiteral(assign);
Toy_freeLiteral(third);
Toy_freeLiteral(second);
Toy_freeLiteral(first);
Toy_freeLiteral(compound);
return -1;
}
Toy_Literal value = Toy_getLiteralArray(TOY_AS_ARRAY(compound), first);
if (TOY_IS_STRING(op) && Toy_equalsRefStringCString(TOY_AS_STRING(op), "+=")) {
@@ -793,6 +837,17 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(idn);
}
if (TOY_IS_IDENTIFIER(first) || TOY_IS_IDENTIFIER(second) || TOY_IS_IDENTIFIER(third)) {
Toy_freeLiteral(op);
Toy_freeLiteral(assign);
Toy_freeLiteral(third);
Toy_freeLiteral(second);
Toy_freeLiteral(first);
Toy_freeLiteral(compound);
return -1;
}
//handle each error case
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");
@@ -937,6 +992,17 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(idn);
}
if (TOY_IS_IDENTIFIER(first) || TOY_IS_IDENTIFIER(second) || TOY_IS_IDENTIFIER(third)) {
Toy_freeLiteral(op);
Toy_freeLiteral(assign);
Toy_freeLiteral(third);
Toy_freeLiteral(second);
Toy_freeLiteral(first);
Toy_freeLiteral(compound);
return -1;
}
//handle each error case
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");
@@ -1064,7 +1130,7 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//if wrong number of arguments, fail
if (arguments->count != 3) {
interpreter->errorOutput("Incorrect number of arguments to _set\n");
interpreter->errorOutput("Incorrect number of arguments to set\n");
return -1;
}
@@ -1074,12 +1140,16 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
Toy_Literal val = arguments->literals[2];
if (!TOY_IS_IDENTIFIER(idn)) {
interpreter->errorOutput("Expected identifier in _set\n");
interpreter->errorOutput("Expected identifier in set\n");
return -1;
}
Toy_parseIdentifierToValue(interpreter, &obj);
if (TOY_IS_IDENTIFIER(obj)) {
return -1;
}
bool freeKey = false;
if (TOY_IS_IDENTIFIER(key)) {
Toy_parseIdentifierToValue(interpreter, &key);
@@ -1092,26 +1162,40 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
freeVal = true;
}
if (TOY_IS_IDENTIFIER(key) || TOY_IS_IDENTIFIER(val)) {
if (freeKey) {
Toy_freeLiteral(key);
}
if (freeVal) {
Toy_freeLiteral(val);
}
return -1;
}
switch(obj.type) {
case TOY_LITERAL_ARRAY: {
Toy_Literal typeLiteral = Toy_getScopeType(interpreter->scope, key);
//check the subtype of the array, if there is one, against the given argument
Toy_Literal typeLiteral = Toy_getScopeType(interpreter->scope, idn);
if (TOY_AS_TYPE(typeLiteral).typeOf == TOY_LITERAL_ARRAY) {
Toy_Literal subtypeLiteral = ((Toy_Literal*)(TOY_AS_TYPE(typeLiteral).subtypes))[0];
if (TOY_AS_TYPE(subtypeLiteral).typeOf != TOY_LITERAL_ANY && TOY_AS_TYPE(subtypeLiteral).typeOf != val.type) {
interpreter->errorOutput("Bad argument type in _set\n");
interpreter->errorOutput("Bad argument type in set\n");
Toy_freeLiteral(typeLiteral);
return -1;
}
}
Toy_freeLiteral(typeLiteral);
if (!TOY_IS_INTEGER(key)) {
interpreter->errorOutput("Expected integer index in _set\n");
interpreter->errorOutput("Expected integer index in set\n");
return -1;
}
if (TOY_AS_ARRAY(obj)->count <= TOY_AS_INTEGER(key) || TOY_AS_INTEGER(key) < 0) {
interpreter->errorOutput("Index out of bounds in _set\n");
if (TOY_AS_INTEGER(key) >= TOY_AS_ARRAY(obj)->count || TOY_AS_INTEGER(key) < 0) {
interpreter->errorOutput("Index out of bounds in set\n");
return -1;
}
@@ -1120,7 +1204,7 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
TOY_AS_ARRAY(obj)->literals[TOY_AS_INTEGER(key)] = Toy_copyLiteral(val);
if (!Toy_setScopeVariable(interpreter->scope, idn, obj, true)) {
interpreter->errorOutput("Incorrect type assigned to array in _set: \"");
interpreter->errorOutput("Incorrect type assigned to array in set: \"");
Toy_printLiteralCustom(val, interpreter->errorOutput);
interpreter->errorOutput("\"\n");
return -1;
@@ -1137,12 +1221,12 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
Toy_Literal valSubtypeLiteral = ((Toy_Literal*)(TOY_AS_TYPE(typeLiteral).subtypes))[1];
if (TOY_AS_TYPE(keySubtypeLiteral).typeOf != TOY_LITERAL_ANY && TOY_AS_TYPE(keySubtypeLiteral).typeOf != key.type) {
interpreter->printOutput("bad argument type in _set\n");
interpreter->printOutput("bad argument type in set\n");
return -1;
}
if (TOY_AS_TYPE(valSubtypeLiteral).typeOf != TOY_LITERAL_ANY && TOY_AS_TYPE(valSubtypeLiteral).typeOf != val.type) {
interpreter->printOutput("bad argument type in _set\n");
interpreter->printOutput("bad argument type in set\n");
return -1;
}
}
@@ -1150,7 +1234,7 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
Toy_setLiteralDictionary(TOY_AS_DICTIONARY(obj), key, val);
if (!Toy_setScopeVariable(interpreter->scope, idn, obj, true)) {
interpreter->errorOutput("Incorrect type assigned to dictionary in _set: \"");
interpreter->errorOutput("Incorrect type assigned to dictionary in set: \"");
Toy_printLiteralCustom(val, interpreter->errorOutput);
interpreter->errorOutput("\"\n");
return -1;
@@ -1160,7 +1244,7 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
}
default:
interpreter->errorOutput("Incorrect compound type in _set: ");
interpreter->errorOutput("Incorrect compound type in set: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\"\n");
return -1;
@@ -1182,7 +1266,7 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
int Toy_private_get(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//if wrong number of arguments, fail
if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _get");
interpreter->errorOutput("Incorrect number of arguments to get");
return -1;
}
@@ -1201,15 +1285,25 @@ int Toy_private_get(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
freeKey = true;
}
if (TOY_IS_IDENTIFIER(obj) || TOY_IS_IDENTIFIER(key)) {
if (freeObj) {
Toy_freeLiteral(obj);
}
if (freeKey) {
Toy_freeLiteral(key);
}
return -1;
}
switch(obj.type) {
case TOY_LITERAL_ARRAY: {
if (!TOY_IS_INTEGER(key)) {
interpreter->errorOutput("Expected integer index in _get\n");
interpreter->errorOutput("Expected integer index in get\n");
return -1;
}
if (TOY_AS_ARRAY(obj)->count <= TOY_AS_INTEGER(key) || TOY_AS_INTEGER(key) < 0) {
interpreter->errorOutput("Index out of bounds in _get\n");
if (TOY_AS_INTEGER(key) >= TOY_AS_ARRAY(obj)->count || TOY_AS_INTEGER(key) < 0) {
interpreter->errorOutput("Index out of bounds in get\n");
return -1;
}
@@ -1243,7 +1337,7 @@ int Toy_private_get(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
}
default:
interpreter->errorOutput("Incorrect compound type in _get \"");
interpreter->errorOutput("Incorrect compound type in get \"");
Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\"\n");
return -1;
@@ -1253,7 +1347,7 @@ int Toy_private_get(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
int Toy_private_push(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//if wrong number of arguments, fail
if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _push\n");
interpreter->errorOutput("Incorrect number of arguments to push\n");
return -1;
}
@@ -1262,35 +1356,47 @@ int Toy_private_push(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_Literal val = arguments->literals[1];
if (!TOY_IS_IDENTIFIER(idn)) {
interpreter->errorOutput("Expected identifier in _push\n");
interpreter->errorOutput("Expected identifier in push\n");
return -1;
}
Toy_parseIdentifierToValue(interpreter, &obj);
if (TOY_IS_IDENTIFIER(obj)) {
return -1;
}
bool freeVal = false;
if (TOY_IS_IDENTIFIER(val)) {
Toy_parseIdentifierToValue(interpreter, &val);
freeVal = true;
}
if (TOY_IS_IDENTIFIER(val)) {
return -1;
}
switch(obj.type) {
case TOY_LITERAL_ARRAY: {
Toy_Literal typeLiteral = Toy_getScopeType(interpreter->scope, val);
//check the subtype of the array, if there is one, against the given argument
Toy_Literal typeLiteral = Toy_getScopeType(interpreter->scope, idn);
if (TOY_AS_TYPE(typeLiteral).typeOf == TOY_LITERAL_ARRAY) {
Toy_Literal subtypeLiteral = ((Toy_Literal*)(TOY_AS_TYPE(typeLiteral).subtypes))[0];
if (TOY_AS_TYPE(subtypeLiteral).typeOf != TOY_LITERAL_ANY && TOY_AS_TYPE(subtypeLiteral).typeOf != val.type) {
interpreter->errorOutput("Bad argument type in _push");
interpreter->errorOutput("Bad argument type in push");
Toy_freeLiteral(typeLiteral);
return -1;
}
}
Toy_freeLiteral(typeLiteral);
Toy_pushLiteralArray(TOY_AS_ARRAY(obj), val);
if (!Toy_setScopeVariable(interpreter->scope, idn, obj, true)) { //TODO: could definitely be more efficient than overwriting the whole original object
interpreter->errorOutput("Incorrect type assigned to array in _push: \"");
interpreter->errorOutput("Incorrect type assigned to array in push: \"");
Toy_printLiteralCustom(val, interpreter->errorOutput);
interpreter->errorOutput("\"\n");
return -1;
@@ -1306,7 +1412,7 @@ int Toy_private_push(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
}
default:
interpreter->errorOutput("Incorrect compound type in _push: ");
interpreter->errorOutput("Incorrect compound type in push: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n");
return -1;
@@ -1316,7 +1422,7 @@ int Toy_private_push(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
int Toy_private_pop(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//if wrong number of arguments, fail
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _pop\n");
interpreter->errorOutput("Incorrect number of arguments to pop\n");
return -1;
}
@@ -1324,12 +1430,16 @@ int Toy_private_pop(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
Toy_Literal obj = arguments->literals[0];
if (!TOY_IS_IDENTIFIER(idn)) {
interpreter->errorOutput("Expected identifier in _pop\n");
interpreter->errorOutput("Expected identifier in pop\n");
return -1;
}
Toy_parseIdentifierToValue(interpreter, &obj);
if (TOY_IS_IDENTIFIER(obj)) {
return -1;
}
switch(obj.type) {
case TOY_LITERAL_ARRAY: {
Toy_Literal lit = Toy_popLiteralArray(TOY_AS_ARRAY(obj));
@@ -1337,7 +1447,7 @@ int Toy_private_pop(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
Toy_freeLiteral(lit);
if (!Toy_setScopeVariable(interpreter->scope, idn, obj, true)) { //TODO: could definitely be more efficient than overwriting the whole original object
interpreter->errorOutput("Incorrect type assigned to array in _pop: ");
interpreter->errorOutput("Incorrect type assigned to array in pop: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n");
return -1;
@@ -1349,7 +1459,7 @@ int Toy_private_pop(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
}
default:
interpreter->errorOutput("Incorrect compound type in _pop: ");
interpreter->errorOutput("Incorrect compound type in pop: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n");
return -1;
@@ -1359,7 +1469,7 @@ int Toy_private_pop(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
int Toy_private_length(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//if wrong number of arguments, fail
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _length\n");
interpreter->errorOutput("Incorrect number of arguments to length\n");
return -1;
}
@@ -1371,6 +1481,10 @@ int Toy_private_length(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
freeObj = true;
}
if (TOY_IS_IDENTIFIER(obj)) {
return -1;
}
switch(obj.type) {
case TOY_LITERAL_ARRAY: {
Toy_Literal lit = TOY_TO_INTEGER_LITERAL( TOY_AS_ARRAY(obj)->count );
@@ -1394,7 +1508,7 @@ int Toy_private_length(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
}
default:
interpreter->errorOutput("Incorrect compound type in _length: ");
interpreter->errorOutput("Incorrect compound type in length: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n");
return -1;
@@ -1410,7 +1524,7 @@ int Toy_private_length(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
int Toy_private_clear(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//if wrong number of arguments, fail
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _clear\n");
interpreter->errorOutput("Incorrect number of arguments to clear\n");
return -1;
}
@@ -1418,12 +1532,16 @@ int Toy_private_clear(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_Literal obj = arguments->literals[0];
if (!TOY_IS_IDENTIFIER(idn)) {
interpreter->errorOutput("expected identifier in _clear\n");
interpreter->errorOutput("expected identifier in clear\n");
return -1;
}
Toy_parseIdentifierToValue(interpreter, &obj);
if (TOY_IS_IDENTIFIER(obj)) {
return -1;
}
//NOTE: just pass in new compounds
switch(obj.type) {
@@ -1434,7 +1552,7 @@ int Toy_private_clear(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_Literal obj = TOY_TO_ARRAY_LITERAL(array);
if (!Toy_setScopeVariable(interpreter->scope, idn, obj, true)) {
interpreter->errorOutput("Incorrect type assigned to array in _clear: ");
interpreter->errorOutput("Incorrect type assigned to array in clear: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n");
return -1;
@@ -1452,7 +1570,7 @@ int Toy_private_clear(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_Literal obj = TOY_TO_DICTIONARY_LITERAL(dictionary);
if (!Toy_setScopeVariable(interpreter->scope, idn, obj, true)) {
interpreter->errorOutput("Incorrect type assigned to dictionary in _clear: ");
interpreter->errorOutput("Incorrect type assigned to dictionary in clear: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n");
return -1;
@@ -1464,7 +1582,7 @@ int Toy_private_clear(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
}
default:
interpreter->errorOutput("Incorrect compound type in _clear: ");
interpreter->errorOutput("Incorrect compound type in clear: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n");
return -1;
+1 -1
View File
@@ -5,7 +5,7 @@
#include <stdint.h>
#define TOY_VERSION_MAJOR 1
#define TOY_VERSION_MINOR 0
#define TOY_VERSION_MINOR 1
#define TOY_VERSION_PATCH 0
#define TOY_VERSION_BUILD __DATE__ " " __TIME__
+146 -1
View File
@@ -231,6 +231,12 @@ static bool execAssert(Toy_Interpreter* interpreter) {
Toy_freeLiteral(lhsIdn);
}
if (TOY_IS_IDENTIFIER(lhs)) {
Toy_freeLiteral(lhs);
Toy_freeLiteral(rhs);
return false;
}
if (!TOY_IS_STRING(rhs)) {
interpreter->errorOutput("The assert keyword needs a string as the second argument, received: ");
Toy_printLiteralCustom(rhs, interpreter->errorOutput);
@@ -265,6 +271,11 @@ static bool execPrint(Toy_Interpreter* interpreter) {
Toy_freeLiteral(idn);
}
if (TOY_IS_IDENTIFIER(lit)) {
Toy_freeLiteral(lit);
return false;
}
Toy_printLiteralCustom(lit, interpreter->printOutput);
Toy_freeLiteral(lit);
@@ -297,6 +308,11 @@ static bool rawLiteral(Toy_Interpreter* interpreter) {
Toy_freeLiteral(idn);
}
if (TOY_IS_IDENTIFIER(lit)) {
Toy_freeLiteral(lit);
return false;
}
Toy_pushLiteralArray(&interpreter->stack, lit);
Toy_freeLiteral(lit);
@@ -312,6 +328,11 @@ static bool execNegate(Toy_Interpreter* interpreter) {
Toy_freeLiteral(idn);
}
if (TOY_IS_IDENTIFIER(lit)) {
Toy_freeLiteral(lit);
return false;
}
if (TOY_IS_INTEGER(lit)) {
lit = TOY_TO_INTEGER_LITERAL(-TOY_AS_INTEGER(lit));
}
@@ -343,6 +364,11 @@ static bool execInvert(Toy_Interpreter* interpreter) {
Toy_freeLiteral(idn);
}
if (TOY_IS_IDENTIFIER(lit)) {
Toy_freeLiteral(lit);
return false;
}
if (TOY_IS_BOOLEAN(lit)) {
lit = TOY_TO_BOOLEAN_LITERAL(!TOY_AS_BOOLEAN(lit));
}
@@ -376,6 +402,12 @@ static bool execArithmetic(Toy_Interpreter* interpreter, Toy_Opcode opcode) {
Toy_freeLiteral(lhsIdn);
}
if (TOY_IS_IDENTIFIER(lhs) || TOY_IS_IDENTIFIER(rhs)) {
Toy_freeLiteral(lhs);
Toy_freeLiteral(rhs);
return false;
}
//special case for string concatenation ONLY
if (TOY_IS_STRING(lhs) && TOY_IS_STRING(rhs) && (opcode == TOY_OP_ADDITION || opcode == TOY_OP_VAR_ADDITION_ASSIGN)) {
//check for overflow
@@ -508,6 +540,10 @@ static Toy_Literal parseTypeToValue(Toy_Interpreter* interpreter, Toy_Literal ty
Toy_freeLiteral(typeIdn);
}
if (TOY_IS_IDENTIFIER(type)) {
return TOY_TO_NULL_LITERAL;
}
//if this is an array or dictionary, continue to the subtypes
if (TOY_IS_TYPE(type) && (TOY_AS_TYPE(type).typeOf == TOY_LITERAL_ARRAY || TOY_AS_TYPE(type).typeOf == TOY_LITERAL_DICTIONARY)) {
for (int i = 0; i < TOY_AS_TYPE(type).count; i++) {
@@ -548,6 +584,12 @@ static bool execVarDecl(Toy_Interpreter* interpreter, bool lng) {
Toy_freeLiteral(typeIdn);
}
if (TOY_IS_IDENTIFIER(type)) {
Toy_freeLiteral(identifier);
Toy_freeLiteral(type);
return false;
}
//BUGFIX: because identifiers are getting embedded in type definitions
type = parseTypeToValue(interpreter, type);
@@ -565,6 +607,13 @@ static bool execVarDecl(Toy_Interpreter* interpreter, bool lng) {
Toy_freeLiteral(valIdn);
}
if (TOY_IS_IDENTIFIER(val)) {
Toy_freeLiteral(identifier);
Toy_freeLiteral(type);
Toy_freeLiteral(val);
return false;
}
if (TOY_IS_ARRAY(val) || TOY_IS_DICTIONARY(val)) {
Toy_parseCompoundToPureValues(interpreter, &val);
}
@@ -645,6 +694,12 @@ static bool execVarAssign(Toy_Interpreter* interpreter) {
Toy_freeLiteral(rhsIdn);
}
if (TOY_IS_IDENTIFIER(rhs)) {
Toy_freeLiteral(lhs);
Toy_freeLiteral(rhs);
return false;
}
if (TOY_IS_ARRAY(rhs) || TOY_IS_DICTIONARY(rhs)) {
Toy_parseCompoundToPureValues(interpreter, &rhs);
}
@@ -714,6 +769,12 @@ static bool execValCast(Toy_Interpreter* interpreter) {
Toy_freeLiteral(valueIdn);
}
if (TOY_IS_IDENTIFIER(value)) {
Toy_freeLiteral(type);
Toy_freeLiteral(value);
return false;
}
Toy_Literal result = TOY_TO_NULL_LITERAL;
if (TOY_IS_NULL(value)) {
@@ -848,6 +909,12 @@ static bool execCompareEqual(Toy_Interpreter* interpreter, bool invert) {
Toy_freeLiteral(lhsIdn);
}
if (TOY_IS_IDENTIFIER(lhs) || TOY_IS_IDENTIFIER(rhs)) {
Toy_freeLiteral(lhs);
Toy_freeLiteral(rhs);
return false;
}
bool result = Toy_literalsAreEqual(lhs, rhs);
if (invert) {
@@ -876,6 +943,12 @@ static bool execCompareLess(Toy_Interpreter* interpreter, bool invert) {
Toy_freeLiteral(lhsIdn);
}
if (TOY_IS_IDENTIFIER(lhs) || TOY_IS_IDENTIFIER(rhs)) {
Toy_freeLiteral(lhs);
Toy_freeLiteral(rhs);
return false;
}
//not a number, return falure
if (!(TOY_IS_INTEGER(lhs) || TOY_IS_FLOAT(lhs))) {
interpreter->errorOutput("Incorrect type in comparison, value \"");
@@ -936,6 +1009,12 @@ static bool execCompareLessEqual(Toy_Interpreter* interpreter, bool invert) {
Toy_freeLiteral(lhsIdn);
}
if (TOY_IS_IDENTIFIER(lhs) || TOY_IS_IDENTIFIER(rhs)) {
Toy_freeLiteral(lhs);
Toy_freeLiteral(rhs);
return false;
}
//not a number, return falure
if (!(TOY_IS_INTEGER(lhs) || TOY_IS_FLOAT(lhs))) {
interpreter->errorOutput("Incorrect type in comparison, value \"");
@@ -997,6 +1076,12 @@ static bool execAnd(Toy_Interpreter* interpreter) {
Toy_freeLiteral(lhsIdn);
}
if (TOY_IS_IDENTIFIER(lhs) || TOY_IS_IDENTIFIER(rhs)) {
Toy_freeLiteral(lhs);
Toy_freeLiteral(rhs);
return false;
}
if (TOY_IS_TRUTHY(lhs) && TOY_IS_TRUTHY(rhs)) {
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_BOOLEAN_LITERAL(true));
}
@@ -1024,6 +1109,12 @@ static bool execOr(Toy_Interpreter* interpreter) {
Toy_freeLiteral(lhsIdn);
}
if (TOY_IS_IDENTIFIER(lhs) || TOY_IS_IDENTIFIER(rhs)) {
Toy_freeLiteral(lhs);
Toy_freeLiteral(rhs);
return false;
}
if (TOY_IS_TRUTHY(lhs) || TOY_IS_TRUTHY(rhs)) {
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_BOOLEAN_LITERAL(true));
}
@@ -1067,6 +1158,11 @@ static bool execFalseJump(Toy_Interpreter* interpreter) {
Toy_freeLiteral(litIdn);
}
if (TOY_IS_IDENTIFIER(lit)) {
Toy_freeLiteral(lit);
return false;
}
if (TOY_IS_NULL(lit)) {
interpreter->errorOutput("Null detected in comparison\n");
Toy_freeLiteral(lit);
@@ -1183,7 +1279,7 @@ bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_Liter
int returnsCount = TOY_AS_FUNCTION_NATIVE(func)(interpreter, arguments);
if (returnsCount < 0) {
interpreter->errorOutput("Unknown error from native function\n");
// interpreter->errorOutput("Unknown error from native function\n");
return false;
}
@@ -1287,6 +1383,17 @@ bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_Liter
Toy_freeLiteral(argIdn);
}
if (TOY_IS_IDENTIFIER(arg)) {
//free, and skip out
Toy_freeLiteral(arg);
Toy_popScope(inner.scope);
Toy_freeLiteralArray(&inner.stack);
Toy_freeLiteralArray(&inner.literalCache);
return false;
}
if (!Toy_setScopeVariable(inner.scope, paramArray->literals[i], arg, false)) {
interpreter->errorOutput("[internal] Could not define parameter (bad type?)\n");
@@ -1455,6 +1562,12 @@ static bool execFnReturn(Toy_Interpreter* interpreter) {
Toy_freeLiteral(litIdn);
}
if (TOY_IS_IDENTIFIER(lit)) {
Toy_freeLiteralArray(&returns);
Toy_freeLiteral(lit);
return false;
}
if (TOY_IS_ARRAY(lit) || TOY_IS_DICTIONARY(lit)) {
Toy_parseCompoundToPureValues(interpreter, &lit);
}
@@ -1526,6 +1639,17 @@ static bool execIndex(Toy_Interpreter* interpreter, bool assignIntermediate) {
freeIdn = true;
}
if (TOY_IS_IDENTIFIER(compound)) {
Toy_freeLiteral(third);
Toy_freeLiteral(second);
Toy_freeLiteral(first);
Toy_freeLiteral(compound);
if (freeIdn) {
Toy_freeLiteral(compoundIdn);
}
return true;
}
if (!TOY_IS_ARRAY(compound) && !TOY_IS_DICTIONARY(compound) && !TOY_IS_STRING(compound)) {
interpreter->errorOutput("Unknown compound found in indexing notation: ");
Toy_printLiteralCustom(compound, interpreter->errorOutput);
@@ -1610,12 +1734,33 @@ static bool execIndexAssign(Toy_Interpreter* interpreter) {
Toy_freeLiteral(assignIdn);
}
if (TOY_IS_IDENTIFIER(assign)) {
Toy_freeLiteral(compound);
Toy_freeLiteral(first);
Toy_freeLiteral(second);
Toy_freeLiteral(third);
Toy_freeLiteral(assign);
return false;
}
Toy_Literal compoundIdn = compound;
bool freeIdn = false;
if (TOY_IS_IDENTIFIER(compound) && Toy_parseIdentifierToValue(interpreter, &compound)) {
freeIdn = true;
}
if (TOY_IS_IDENTIFIER(compound)) {
Toy_freeLiteral(compound);
Toy_freeLiteral(first);
Toy_freeLiteral(second);
Toy_freeLiteral(third);
Toy_freeLiteral(assign);
if (freeIdn) {
Toy_freeLiteral(compoundIdn);
}
return false;
}
if (!TOY_IS_ARRAY(compound) && !TOY_IS_DICTIONARY(compound) && !TOY_IS_STRING(compound)) {
interpreter->errorOutput("Unknown compound found in index assigning notation\n");
Toy_freeLiteral(assign);
+2 -2
View File
@@ -241,10 +241,10 @@ bool Toy_literalsAreEqual(Toy_Literal lhs, Toy_Literal rhs) {
// ints and floats are compatible
if ((TOY_IS_INTEGER(lhs) || TOY_IS_FLOAT(lhs)) && (TOY_IS_INTEGER(rhs) || TOY_IS_FLOAT(rhs))) {
if (TOY_IS_INTEGER(lhs)) {
return TOY_AS_INTEGER(lhs) + TOY_AS_FLOAT(rhs);
return TOY_AS_INTEGER(lhs) == TOY_AS_FLOAT(rhs);
}
else {
return TOY_AS_FLOAT(lhs) + TOY_AS_INTEGER(rhs);
return TOY_AS_FLOAT(lhs) == TOY_AS_INTEGER(rhs);
}
}
+2 -1
View File
@@ -8,6 +8,7 @@
struct Toy_Literal;
struct Toy_Interpreter;
struct Toy_LiteralArray;
struct Toy_Scope;
typedef int (*Toy_NativeFn)(struct Toy_Interpreter* interpreter, struct Toy_LiteralArray* arguments);
typedef int (*Toy_HookFn)(struct Toy_Interpreter* interpreter, struct Toy_Literal identifier, struct Toy_Literal alias);
typedef void (*Toy_PrintFn)(const char*);
@@ -57,7 +58,7 @@ typedef struct Toy_Literal {
Toy_NativeFn native; //8
Toy_HookFn hook; //8
} inner; //8
void* scope; //8
struct Toy_Scope* scope; //8
} function; //16
struct { //for variable names
+7 -3
View File
@@ -17,6 +17,10 @@ static void setEntryValues(Toy_private_dictionary_entry* entry, Toy_Literal key,
}
static Toy_private_dictionary_entry* getEntryArray(Toy_private_dictionary_entry* array, int capacity, Toy_Literal key, unsigned int hash, bool mustExist) {
if (!capacity) {
return NULL;
}
//find "key", starting at index
unsigned int index = hash % capacity;
unsigned int start = index;
@@ -122,10 +126,10 @@ static void freeEntryArray(Toy_private_dictionary_entry* array, int capacity) {
void Toy_initLiteralDictionary(Toy_LiteralDictionary* dictionary) {
//HACK: because modulo by 0 is undefined, set the capacity to a non-zero value (and allocate the arrays)
dictionary->entries = NULL;
dictionary->capacity = TOY_GROW_CAPACITY(0);
dictionary->capacity = 0;
dictionary->contains = 0;
dictionary->count = 0;
adjustEntryCapacity(&dictionary->entries, 0, dictionary->capacity);
dictionary->capacity = 0;
}
void Toy_freeLiteralDictionary(Toy_LiteralDictionary* dictionary) {
@@ -215,5 +219,5 @@ void Toy_removeLiteralDictionary(Toy_LiteralDictionary* dictionary, Toy_Literal
bool Toy_existsLiteralDictionary(Toy_LiteralDictionary* dictionary, Toy_Literal key) {
//null & not tombstoned
Toy_private_dictionary_entry* entry = getEntryArray(dictionary->entries, dictionary->capacity, key, Toy_hashLiteral(key), false);
return !(TOY_IS_NULL(entry->key) && TOY_IS_NULL(entry->value));
return entry != NULL && !(TOY_IS_NULL(entry->key) && TOY_IS_NULL(entry->value));
}
+25 -1
View File
@@ -810,13 +810,20 @@ static Toy_Opcode indexAccess(Toy_Parser* parser, Toy_ASTNode** nodeHandle) { //
//eat the first
if (!match(parser, TOY_TOKEN_COLON)) {
Toy_freeASTNode(first);
first = NULL;
parsePrecedence(parser, &first, PREC_TERNARY);
match(parser, TOY_TOKEN_COLON);
readFirst = true;
}
if (match(parser, TOY_TOKEN_BRACKET_RIGHT)) {
if (!first) {
Toy_freeASTNode(first);
Toy_freeASTNode(second);
Toy_freeASTNode(third);
return TOY_OP_EOF;
}
if (match(parser, TOY_TOKEN_BRACKET_RIGHT)) {
if (readFirst) {
Toy_freeASTNode(second);
second = NULL;
@@ -832,10 +839,18 @@ static Toy_Opcode indexAccess(Toy_Parser* parser, Toy_ASTNode** nodeHandle) { //
//eat the second
if (!match(parser, TOY_TOKEN_COLON)) {
Toy_freeASTNode(second);
second = NULL;
parsePrecedence(parser, &second, PREC_TERNARY);
match(parser, TOY_TOKEN_COLON);
}
if (!second) {
Toy_freeASTNode(first);
Toy_freeASTNode(second);
Toy_freeASTNode(third);
return TOY_OP_EOF;
}
if (match(parser, TOY_TOKEN_BRACKET_RIGHT)) {
Toy_freeASTNode(third);
third = NULL;
@@ -845,7 +860,16 @@ static Toy_Opcode indexAccess(Toy_Parser* parser, Toy_ASTNode** nodeHandle) { //
//eat the third
Toy_freeASTNode(third);
third = NULL;
parsePrecedence(parser, &third, PREC_TERNARY);
if (!third) {
Toy_freeASTNode(first);
Toy_freeASTNode(second);
Toy_freeASTNode(third);
return TOY_OP_EOF;
}
Toy_emitASTNodeIndex(nodeHandle, first, second, third);
consume(parser, TOY_TOKEN_BRACKET_RIGHT, "Expected ']' in index notation");
+4
View File
@@ -209,6 +209,10 @@ Toy_Scope* Toy_popScope(Toy_Scope* scope) {
}
Toy_Scope* Toy_copyScope(Toy_Scope* original) {
if (original == NULL) {
return NULL;
}
Toy_Scope* scope = TOY_ALLOCATE(Toy_Scope, 1);
scope->ancestor = original->ancestor;
Toy_initLiteralDictionary(&scope->variables);
View File
+17
View File
@@ -0,0 +1,17 @@
import standard;
import random;
var generator: opaque = createRandomGenerator(clock().hash()); //create a new generator object, from a non-determinant source
var a: int = generator.generateRandomNumber();
var b: int = generator.generateRandomNumber();
var c: int = generator.generateRandomNumber();
generator.freeRandomGenerator();
assert a != b, "random a != random b failed";
assert a != c, "random a != random c failed";
assert b != c, "random b != random c failed";
print "All good";
+20
View File
@@ -1,5 +1,18 @@
import standard;
//test abs
{
assert abs(-5) == 5, "abs(-integer) failed";
assert abs(-5.5) == 5.5, "abs(-float) failed";
assert abs(5) == 5, "abs(+integer) failed";
assert abs(5.5) == 5.5, "abs(+float) failed";
var x = -5;
assert x.abs() == 5, "var.abs() failed";
}
//test clock
{
//this depends on external factors, so only check the length
@@ -162,6 +175,13 @@ import standard;
}
//test hash
{
assert typeof "Hello world".hash() == int, "typeof \"Hello world\".hash() failed";
assert "Hello world".hash() == 994097935, "\"Hello world\".hash() failed"; //NOTE: specific value based on algorithm
}
//test indexOf
{
var a = [1, 2, 42, 3];
@@ -0,0 +1 @@
"a"[--];
+5 -53
View File
@@ -14,6 +14,7 @@
#include "../repl/repl_tools.h"
#include "../repl/lib_about.h"
#include "../repl/lib_random.h"
#include "../repl/lib_runner.h"
#include "../repl/lib_standard.h"
@@ -45,30 +46,15 @@ void runBinaryWithLibrary(const unsigned char* tb, size_t size, const char* libr
Toy_setInterpreterError(&interpreter, errorWrapper);
//inject the standard libraries into this interpreter
if (hook != Toy_hookStandard) {
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
}
Toy_injectNativeHook(&interpreter, library, hook);
Toy_runInterpreter(&interpreter, tb, size);
Toy_freeInterpreter(&interpreter);
}
void runBinaryQuietly(const unsigned char* tb, size_t size) {
Toy_Interpreter interpreter;
Toy_initInterpreter(&interpreter);
//NOTE: supress print output for testing
Toy_setInterpreterPrint(&interpreter, noPrintFn);
Toy_setInterpreterAssert(&interpreter, assertWrapper);
Toy_setInterpreterError(&interpreter, errorWrapper);
//inject the libs
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
Toy_runInterpreter(&interpreter, tb, size);
Toy_freeInterpreter(&interpreter);
}
typedef struct Payload {
char* fname;
char* libname;
@@ -94,6 +80,7 @@ int main() {
{"about.toy", "about", Toy_hookAbout},
{"standard.toy", "standard", Toy_hookStandard},
{"runner.toy", "runner", Toy_hookRunner},
{"random.toy", "random", Toy_hookRandom},
{NULL, NULL, NULL}
};
@@ -125,41 +112,6 @@ int main() {
}
}
{
//run whatever, testing stuff together to check for memory leaks
char* whatever[] = {
"random-stuff.toy",
NULL
};
for (int i = 0; whatever[i]; i++) {
printf("Running %s\n", whatever[i]);
char fname[128];
snprintf(fname, 128, "scripts/lib/%s", whatever[i]);
//compile the source
size_t size = 0;
const char* source = (const char*)Toy_readFile(fname, &size);
if (!source) {
printf(TOY_CC_ERROR "Failed to load file: %s\n" TOY_CC_RESET, fname);
failedAsserts++;
continue;
}
const unsigned char* tb = Toy_compileString(source, &size);
free((void*)source);
if (!tb) {
printf(TOY_CC_ERROR "Failed to compile file: %s\n" TOY_CC_RESET, fname);
failedAsserts++;
continue;
}
runBinaryQuietly(tb, size);
}
}
//lib cleanup
Toy_freeDriveDictionary();
+1
View File
@@ -101,6 +101,7 @@ int main() {
"declare-types-array.toy",
"declare-types-dictionary-key.toy",
"declare-types-dictionary-value.toy",
"index-access-bugfix.toy",
"index-arrays-non-integer.toy",
"string-concat.toy",
"unary-inverted-nothing.toy",