Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1064b69d04 | |||
| e9b347acb6 | |||
| 071c8da2aa | |||
| d6538812bf | |||
| 3aeddff736 | |||
| c88c1b125d | |||
| 1513ba9878 | |||
| bc0289c3f4 | |||
| 92c71a374d | |||
| e0547474b8 | |||
| 3e6d21afbb | |||
| d3df01c1c4 | |||
| cdca6fa45c | |||
| 1dde9d8f29 | |||
| 7f0f17b6e0 | |||
| 3507104121 |
@@ -19,6 +19,8 @@ bin/
|
||||
*.db
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
*.dll
|
||||
*.exe
|
||||
*.meta
|
||||
*.log
|
||||
|
||||
+11
-6
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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(;;) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
+152
-34
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
@@ -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
@@ -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();
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user