Compare commits

..

37 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
Kayne Ruse 87de634e30 Updated version number to 1.0.0 2023-02-20 02:08:42 +00:00
Kayne Ruse 6fa224fa7b Hooks can't be dict keys, tweaked Toy_readFile 2023-02-18 16:47:38 +00:00
Kayne Ruse 8a68d864e6 Opaque type check added 2023-02-18 15:21:49 +00:00
Kayne Ruse 49f240ea07 Minor tweak 2023-02-18 12:15:23 +00:00
Kayne Ruse 3acbd7447a Merge remote-tracking branch 'refs/remotes/origin/main' 2023-02-18 11:57:22 +00:00
Kayne Ruse 6f126e6daa Minor tweaks and renames, as I'm documenting 2023-02-18 11:56:18 +00:00
Kayne Ruse 2adb9d9158 Tweaked lib runner API 2023-02-16 22:04:47 +00:00
Kayne Ruse 1668dca255 Tweaked some APIs, hid some functions I don't want in the API 2023-02-16 13:06:07 +00:00
Kayne Ruse 501ff6fff4 Chased a ghost for a few hours 2023-02-14 18:55:24 +00:00
Kayne Ruse 3845627fe5 Added release build to MSVC 2023-02-14 18:03:04 +00:00
Kayne Ruse cdae03bd54 String and identifier making fixed for MSVC, just in case 2023-02-14 17:38:10 +00:00
Kayne Ruse 7b501b71b5 commandLine now initializes with default values 2023-02-14 17:00:16 +00:00
Kayne Ruse 913738a4d1 Tweaked the runner test, should be orders of magnitude faster 2023-02-14 16:16:48 +00:00
Kayne Ruse 3312a38c7c Updated memusage tool 2023-02-14 16:05:43 +00:00
Kayne Ruse 71b57fd42c Fixed scripts for distribution 2023-02-14 10:35:08 +00:00
Kayne Ruse 453afbab41 Fixed a stupid bug in MSVC 2023-02-14 10:24:43 +00:00
Kayne Ruse 57af5a6d59 Tweaked some scripts 2023-02-14 09:21:22 +00:00
Kayne Ruse 0737b2a483 Dropped underscore functions in favour of UFCS 2023-02-14 08:37:31 +00:00
Kayne Ruse eae96d6403 Corrected the order of arguments to Toy_callLiteralFn() 2023-02-14 08:00:35 +00:00
Kayne Ruse b55b8e879e Added -n option to diable print newline 2023-02-13 15:51:38 +00:00
Kayne Ruse 1ed114b80d Allow for stmt to have empty clauses, resolved #58 2023-02-13 14:45:24 +00:00
66 changed files with 1401 additions and 752 deletions
+2
View File
@@ -19,6 +19,8 @@ bin/
*.db *.db
*.o *.o
*.a *.a
*.so
*.dll
*.exe *.exe
*.meta *.meta
*.log *.log
+25 -3
View File
@@ -74,6 +74,10 @@
<OutDir>$(SolutionDir)out\$(Configuration)\</OutDir> <OutDir>$(SolutionDir)out\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(ProjectName)\$(Configuration)\</IntDir> <IntDir>$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)out\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -109,12 +113,25 @@
<AdditionalLibraryDirectories>$(SolutionDir)out\$(Configuration)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>$(SolutionDir)out\$(Configuration)</AdditionalLibraryDirectories>
</Link> </Link>
<ClCompile> <ClCompile>
<AdditionalIncludeDirectories>C:\Users\kayne\Desktop\Toy\source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir)/source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<PreprocessorDefinitions>LIB_RUNNER_EXPORT</PreprocessorDefinitions>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<PreprocessorDefinitions>LIB_RUNNER_EXPORT</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)/source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(SolutionDir)out\$(Configuration)</AdditionalLibraryDirectories>
<AdditionalDependencies>Toy.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="repl\lib_about.c" /> <ClCompile Include="repl\lib_about.c" />
<ClCompile Include="repl\lib_compound.c" /> <ClCompile Include="repl\lib_random.c" />
<ClCompile Include="repl\lib_runner.c" /> <ClCompile Include="repl\lib_runner.c" />
<ClCompile Include="repl\lib_standard.c" /> <ClCompile Include="repl\lib_standard.c" />
<ClCompile Include="repl\repl_main.c" /> <ClCompile Include="repl\repl_main.c" />
@@ -122,11 +139,16 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="repl\lib_about.h" /> <ClInclude Include="repl\lib_about.h" />
<ClInclude Include="repl\lib_compound.h" /> <ClInclude Include="repl\lib_random.h" />
<ClInclude Include="repl\lib_runner.h" /> <ClInclude Include="repl\lib_runner.h" />
<ClInclude Include="repl\lib_standard.h" /> <ClInclude Include="repl\lib_standard.h" />
<ClInclude Include="repl\repl_tools.h" /> <ClInclude Include="repl\repl_tools.h" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="Toy.vcxproj">
<Project>{26360002-cc2a-469a-9b28-ba0c1af41657}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
+12 -1
View File
@@ -41,7 +41,7 @@
<PlatformToolset>v143</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
@@ -73,6 +73,10 @@
<OutDir>$(SolutionDir)out\$(Configuration)\</OutDir> <OutDir>$(SolutionDir)out\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(ProjectName)\$(Configuration)\</IntDir> <IntDir>$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)out\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TOY_EXPORTS;TOY_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TOY_EXPORTS;TOY_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -105,6 +109,13 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>
<PreprocessorDefinitions>TOY_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>TOY_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<LanguageStandard_C>stdc17</LanguageStandard_C>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<PreprocessorDefinitions>TOY_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
+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
+63 -21
View File
@@ -7,6 +7,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
typedef struct Toy_Runner { typedef struct Toy_Runner {
Toy_Interpreter interpreter; Toy_Interpreter interpreter;
@@ -32,6 +33,11 @@ static int nativeLoadScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argu
Toy_freeLiteral(drivePathLiteralIdn); Toy_freeLiteral(drivePathLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(drivePathLiteral)) {
Toy_freeLiteral(drivePathLiteral);
return -1;
}
Toy_Literal filePathLiteral = Toy_getFilePathLiteral(interpreter, &drivePathLiteral); Toy_Literal filePathLiteral = Toy_getFilePathLiteral(interpreter, &drivePathLiteral);
if (TOY_IS_NULL(filePathLiteral)) { if (TOY_IS_NULL(filePathLiteral)) {
@@ -48,7 +54,7 @@ static int nativeLoadScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argu
//load and compile the bytecode //load and compile the bytecode
size_t fileSize = 0; size_t fileSize = 0;
const char* source = Toy_readFile(filePath, &fileSize); const char* source = (const char*)Toy_readFile(filePath, &fileSize);
if (!source) { if (!source) {
interpreter->errorOutput("Failed to load source file\n"); interpreter->errorOutput("Failed to load source file\n");
@@ -102,6 +108,11 @@ static int nativeLoadScriptBytecode(Toy_Interpreter* interpreter, Toy_LiteralArr
Toy_freeLiteral(drivePathLiteralIdn); Toy_freeLiteral(drivePathLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(drivePathLiteral)) {
Toy_freeLiteral(drivePathLiteral);
return -1;
}
Toy_RefString* drivePath = Toy_copyRefString(TOY_AS_STRING(drivePathLiteral)); Toy_RefString* drivePath = Toy_copyRefString(TOY_AS_STRING(drivePathLiteral));
//get the drive and path as a string (can't trust that pesky strtok - custom split) TODO: move this to refstring library //get the drive and path as a string (can't trust that pesky strtok - custom split) TODO: move this to refstring library
@@ -200,7 +211,7 @@ static int nativeLoadScriptBytecode(Toy_Interpreter* interpreter, Toy_LiteralArr
static int nativeRunScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeRunScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _runScript\n"); interpreter->errorOutput("Incorrect number of arguments to runScript\n");
return -1; return -1;
} }
@@ -212,8 +223,13 @@ static int nativeRunScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
Toy_freeLiteral(runnerIdn); Toy_freeLiteral(runnerIdn);
} }
if (TOY_IS_IDENTIFIER(runnerLiteral)) {
Toy_freeLiteral(runnerLiteral);
return -1;
}
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) { if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
interpreter->errorOutput("Unrecognized opaque literal in _runScript\n"); interpreter->errorOutput("Unrecognized opaque literal in runScript\n");
return -1; return -1;
} }
@@ -241,7 +257,7 @@ static int nativeRunScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
static int nativeGetScriptVar(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeGetScriptVar(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _getScriptVar\n"); interpreter->errorOutput("Incorrect number of arguments to getScriptVar\n");
return -1; return -1;
} }
@@ -259,8 +275,14 @@ static int nativeGetScriptVar(Toy_Interpreter* interpreter, Toy_LiteralArray* ar
Toy_freeLiteral(runnerIdn); 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) { if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
interpreter->errorOutput("Unrecognized opaque literal in _runScript\n"); interpreter->errorOutput("Unrecognized opaque literal in getScriptVar\n");
return -1; return -1;
} }
@@ -292,7 +314,7 @@ static int nativeGetScriptVar(Toy_Interpreter* interpreter, Toy_LiteralArray* ar
static int nativeCallScriptFn(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeCallScriptFn(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count < 2) { if (arguments->count < 2) {
interpreter->errorOutput("Incorrect number of arguments to _callScriptFn\n"); interpreter->errorOutput("Incorrect number of arguments to callScriptFn\n");
return -1; return -1;
} }
@@ -309,7 +331,7 @@ static int nativeCallScriptFn(Toy_Interpreter* interpreter, Toy_LiteralArray* ar
Toy_LiteralArray rest; Toy_LiteralArray rest;
Toy_initLiteralArray(&rest); Toy_initLiteralArray(&rest);
while (tmp.count) { //correct the order of the rest args while (tmp.count > 0) { //correct the order of the rest args
Toy_Literal lit = Toy_popLiteralArray(&tmp); Toy_Literal lit = Toy_popLiteralArray(&tmp);
Toy_pushLiteralArray(&rest, lit); Toy_pushLiteralArray(&rest, lit);
Toy_freeLiteral(lit); Toy_freeLiteral(lit);
@@ -317,7 +339,6 @@ static int nativeCallScriptFn(Toy_Interpreter* interpreter, Toy_LiteralArray* ar
Toy_freeLiteralArray(&tmp); Toy_freeLiteralArray(&tmp);
//get the runner object //get the runner object
Toy_Literal varName = Toy_popLiteralArray(arguments); Toy_Literal varName = Toy_popLiteralArray(arguments);
Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments); Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments);
@@ -332,8 +353,14 @@ static int nativeCallScriptFn(Toy_Interpreter* interpreter, Toy_LiteralArray* ar
Toy_freeLiteral(runnerIdn); 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) { if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
interpreter->errorOutput("Unrecognized opaque literal in _runScript\n"); interpreter->errorOutput("Unrecognized opaque literal in callScriptFn\n");
return -1; return -1;
} }
@@ -389,7 +416,7 @@ static int nativeCallScriptFn(Toy_Interpreter* interpreter, Toy_LiteralArray* ar
static int nativeResetScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeResetScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _resetScript\n"); interpreter->errorOutput("Incorrect number of arguments to resetScript\n");
return -1; return -1;
} }
@@ -401,8 +428,13 @@ static int nativeResetScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arg
Toy_freeLiteral(runnerIdn); Toy_freeLiteral(runnerIdn);
} }
if (TOY_IS_IDENTIFIER(runnerLiteral)) {
Toy_freeLiteral(runnerLiteral);
return -1;
}
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) { if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
interpreter->errorOutput("Unrecognized opaque literal in _runScript\n"); interpreter->errorOutput("Unrecognized opaque literal in resetScript\n");
return -1; return -1;
} }
@@ -425,7 +457,7 @@ static int nativeResetScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arg
static int nativeFreeScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeFreeScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _freeScript\n"); interpreter->errorOutput("Incorrect number of arguments to freeScript\n");
return -1; return -1;
} }
@@ -437,8 +469,13 @@ static int nativeFreeScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argu
Toy_freeLiteral(runnerIdn); Toy_freeLiteral(runnerIdn);
} }
if (TOY_IS_IDENTIFIER(runnerLiteral)) {
Toy_freeLiteral(runnerLiteral);
return -1;
}
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) { if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
interpreter->errorOutput("Unrecognized opaque literal in _freeScript\n"); interpreter->errorOutput("Unrecognized opaque literal in freeScript\n");
return -1; return -1;
} }
@@ -459,7 +496,7 @@ static int nativeFreeScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argu
static int nativeCheckScriptDirty(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeCheckScriptDirty(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _runScript\n"); interpreter->errorOutput("Incorrect number of arguments to checkScriptDirty\n");
return -1; return -1;
} }
@@ -471,8 +508,13 @@ static int nativeCheckScriptDirty(Toy_Interpreter* interpreter, Toy_LiteralArray
Toy_freeLiteral(runnerIdn); Toy_freeLiteral(runnerIdn);
} }
if (TOY_IS_IDENTIFIER(runnerLiteral)) {
Toy_freeLiteral(runnerLiteral);
return -1;
}
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) { if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
interpreter->errorOutput("Unrecognized opaque literal in _runScript\n"); interpreter->errorOutput("Unrecognized opaque literal in checkScriptDirty\n");
return -1; return -1;
} }
@@ -501,12 +543,12 @@ int Toy_hookRunner(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Lit
Natives natives[] = { Natives natives[] = {
{"loadScript", nativeLoadScript}, {"loadScript", nativeLoadScript},
{"loadScriptBytecode", nativeLoadScriptBytecode}, {"loadScriptBytecode", nativeLoadScriptBytecode},
{"_runScript", nativeRunScript}, {"runScript", nativeRunScript},
{"_getScriptVar", nativeGetScriptVar}, {"getScriptVar", nativeGetScriptVar},
{"_callScriptFn", nativeCallScriptFn}, {"callScriptFn", nativeCallScriptFn},
{"_resetScript", nativeResetScript}, {"resetScript", nativeResetScript},
{"_freeScript", nativeFreeScript}, {"freeScript", nativeFreeScript},
{"_checkScriptDirty", nativeCheckScriptDirty}, {"checkScriptDirty", nativeCheckScriptDirty},
{NULL, NULL} {NULL, NULL}
}; };
+26 -6
View File
@@ -1,15 +1,35 @@
#pragma once #pragma once
#include "toy_common.h"
#include "toy_interpreter.h" #include "toy_interpreter.h"
int Toy_hookRunner(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias); int Toy_hookRunner(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
//file system API - these need to be set by the host
void Toy_initDriveDictionary();
void Toy_freeDriveDictionary();
Toy_LiteralDictionary* Toy_getDriveDictionary();
#define TOY_OPAQUE_TAG_RUNNER 100 #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 //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);
+264 -78
View File
@@ -2,9 +2,53 @@
#include "toy_memory.h" #include "toy_memory.h"
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <time.h> #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) { static int nativeClock(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
@@ -34,7 +78,7 @@ static int nativeClock(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _concat\n"); interpreter->errorOutput("Incorrect number of arguments to concat\n");
return -1; return -1;
} }
@@ -53,10 +97,16 @@ static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
Toy_freeLiteral(otherLiteralIdn); Toy_freeLiteral(otherLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(otherLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(otherLiteral);
return -1;
}
//for each self type //for each self type
if (TOY_IS_ARRAY(selfLiteral)) { if (TOY_IS_ARRAY(selfLiteral)) {
if (!TOY_IS_ARRAY(otherLiteral)) { if (!TOY_IS_ARRAY(otherLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _concat (unknown type for other)\n"); interpreter->errorOutput("Incorrect argument type passed to concat (unknown type for other)\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(otherLiteral); Toy_freeLiteral(otherLiteral);
return -1; return -1;
@@ -78,7 +128,7 @@ static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
if (TOY_IS_DICTIONARY(selfLiteral)) { if (TOY_IS_DICTIONARY(selfLiteral)) {
if (!TOY_IS_DICTIONARY(otherLiteral)) { if (!TOY_IS_DICTIONARY(otherLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _concat (unknown type for other)\n"); interpreter->errorOutput("Incorrect argument type passed to concat (unknown type for other)\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(otherLiteral); Toy_freeLiteral(otherLiteral);
return -1; return -1;
@@ -102,7 +152,7 @@ static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
if (TOY_IS_STRING(selfLiteral)) { //a little redundant if (TOY_IS_STRING(selfLiteral)) { //a little redundant
if (!TOY_IS_STRING(otherLiteral)) { if (!TOY_IS_STRING(otherLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _concat (unknown type for other)\n"); interpreter->errorOutput("Incorrect argument type passed to concat (unknown type for other)\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(otherLiteral); Toy_freeLiteral(otherLiteral);
return -1; return -1;
@@ -112,7 +162,7 @@ static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
size_t length = TOY_AS_STRING(selfLiteral)->length + TOY_AS_STRING(otherLiteral)->length + 1; size_t length = TOY_AS_STRING(selfLiteral)->length + TOY_AS_STRING(otherLiteral)->length + 1;
if (length > TOY_MAX_STRING_LENGTH) { if (length > TOY_MAX_STRING_LENGTH) {
interpreter->errorOutput("Can't concatenate these strings, result is too long (error found in _concat)\n"); interpreter->errorOutput("Can't concatenate these strings, result is too long (error found in concat)\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(otherLiteral); Toy_freeLiteral(otherLiteral);
return -1; return -1;
@@ -135,7 +185,7 @@ static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
return 1; return 1;
} }
interpreter->errorOutput("Incorrect argument type passed to _concat (unknown type for self)\n"); interpreter->errorOutput("Incorrect argument type passed to concat (unknown type for self)\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(otherLiteral); Toy_freeLiteral(otherLiteral);
return -1; return -1;
@@ -144,7 +194,7 @@ static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
static int nativeContainsKey(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeContainsKey(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _containsKey\n"); interpreter->errorOutput("Incorrect number of arguments to containsKey\n");
return -1; return -1;
} }
@@ -163,9 +213,15 @@ static int nativeContainsKey(Toy_Interpreter* interpreter, Toy_LiteralArray* arg
Toy_freeLiteral(keyLiteralIdn); Toy_freeLiteral(keyLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(keyLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(keyLiteral);
return -1;
}
//check type //check type
if (!(/* TOY_IS_ARRAY(selfLiteral) || */ TOY_IS_DICTIONARY(selfLiteral) )) { if (!(/* TOY_IS_ARRAY(selfLiteral) || */ TOY_IS_DICTIONARY(selfLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to _containsKey\n"); interpreter->errorOutput("Incorrect argument type passed to containsKey\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(keyLiteral); Toy_freeLiteral(keyLiteral);
return -1; return -1;
@@ -189,7 +245,7 @@ static int nativeContainsKey(Toy_Interpreter* interpreter, Toy_LiteralArray* arg
static int nativeContainsValue(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeContainsValue(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _containsValue\n"); interpreter->errorOutput("Incorrect number of arguments to containsValue\n");
return -1; return -1;
} }
@@ -208,9 +264,15 @@ static int nativeContainsValue(Toy_Interpreter* interpreter, Toy_LiteralArray* a
Toy_freeLiteral(valueLiteralIdn); Toy_freeLiteral(valueLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(valueLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(valueLiteral);
return -1;
}
//check type //check type
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) )) { if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to _containsValue\n"); interpreter->errorOutput("Incorrect argument type passed to containsValue\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(valueLiteral); Toy_freeLiteral(valueLiteral);
return -1; return -1;
@@ -259,7 +321,7 @@ static int nativeContainsValue(Toy_Interpreter* interpreter, Toy_LiteralArray* a
static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _every\n"); interpreter->errorOutput("Incorrect number of arguments to every\n");
return -1; return -1;
} }
@@ -278,9 +340,15 @@ static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
Toy_freeLiteral(fnLiteralIdn); Toy_freeLiteral(fnLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//check type //check type
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to _every\n"); interpreter->errorOutput("Incorrect argument type passed to every\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral); Toy_freeLiteral(fnLiteral);
return -1; return -1;
@@ -296,8 +364,8 @@ static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
Toy_pushLiteralArray(&arguments, indexLiteral); Toy_pushLiteralArray(&arguments, indexLiteral);
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
Toy_LiteralArray returns; Toy_LiteralArray returns;
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
@@ -337,8 +405,8 @@ static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key); Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
Toy_LiteralArray returns; Toy_LiteralArray returns;
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
@@ -375,7 +443,7 @@ static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
static int nativeFilter(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeFilter(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _filter\n"); interpreter->errorOutput("Incorrect number of arguments to filter\n");
return -1; return -1;
} }
@@ -394,9 +462,15 @@ static int nativeFilter(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
Toy_freeLiteral(fnLiteralIdn); Toy_freeLiteral(fnLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//check type //check type
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to _filter\n"); interpreter->errorOutput("Incorrect argument type passed to filter\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral); Toy_freeLiteral(fnLiteral);
return -1; return -1;
@@ -413,8 +487,8 @@ static int nativeFilter(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
Toy_pushLiteralArray(&arguments, indexLiteral); Toy_pushLiteralArray(&arguments, indexLiteral);
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
Toy_LiteralArray returns; Toy_LiteralArray returns;
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
@@ -453,8 +527,8 @@ static int nativeFilter(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key); Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
Toy_LiteralArray returns; Toy_LiteralArray returns;
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
@@ -489,7 +563,7 @@ static int nativeFilter(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _forEach\n"); interpreter->errorOutput("Incorrect number of arguments to forEach\n");
return -1; return -1;
} }
@@ -508,9 +582,15 @@ static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_freeLiteral(fnLiteralIdn); Toy_freeLiteral(fnLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//check type //check type
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to _forEach\n"); interpreter->errorOutput("Incorrect argument type passed to forEach\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral); Toy_freeLiteral(fnLiteral);
return -1; return -1;
@@ -523,8 +603,8 @@ static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
Toy_pushLiteralArray(&arguments, indexLiteral); Toy_pushLiteralArray(&arguments, indexLiteral);
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
Toy_LiteralArray returns; Toy_LiteralArray returns;
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
@@ -546,8 +626,8 @@ static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key); Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
Toy_LiteralArray returns; Toy_LiteralArray returns;
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
@@ -567,7 +647,7 @@ static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
static int nativeGetKeys(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeGetKeys(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _getKeys\n"); interpreter->errorOutput("Incorrect number of arguments to getKeys\n");
return -1; return -1;
} }
@@ -580,9 +660,14 @@ static int nativeGetKeys(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_freeLiteral(selfLiteralIdn); Toy_freeLiteral(selfLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
return -1;
}
//check type //check type
if (!TOY_IS_DICTIONARY(selfLiteral)) { if (!TOY_IS_DICTIONARY(selfLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _getKeys\n"); interpreter->errorOutput("Incorrect argument type passed to getKeys\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
return -1; return -1;
} }
@@ -612,7 +697,7 @@ static int nativeGetKeys(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
static int nativeGetValues(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeGetValues(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _getValues\n"); interpreter->errorOutput("Incorrect number of arguments to getValues\n");
return -1; return -1;
} }
@@ -625,9 +710,14 @@ static int nativeGetValues(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
Toy_freeLiteral(selfLiteralIdn); Toy_freeLiteral(selfLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
return -1;
}
//check type //check type
if (!TOY_IS_DICTIONARY(selfLiteral)) { if (!TOY_IS_DICTIONARY(selfLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _getValues\n"); interpreter->errorOutput("Incorrect argument type passed to getValues\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
return -1; return -1;
} }
@@ -655,10 +745,40 @@ static int nativeGetValues(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
return 1; 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) { static int nativeIndexOf(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _indexOf\n"); interpreter->errorOutput("Incorrect number of arguments to indexOf\n");
return -1; return -1;
} }
@@ -677,6 +797,12 @@ static int nativeIndexOf(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_freeLiteral(valueLiteralIdn); Toy_freeLiteral(valueLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(valueLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(valueLiteral);
return -1;
}
//check type //check type
if (!TOY_IS_ARRAY(selfLiteral)) { if (!TOY_IS_ARRAY(selfLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to indexOf\n"); interpreter->errorOutput("Incorrect argument type passed to indexOf\n");
@@ -705,7 +831,7 @@ static int nativeIndexOf(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
static int nativeMap(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeMap(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _map\n"); interpreter->errorOutput("Incorrect number of arguments to map\n");
return -1; return -1;
} }
@@ -724,9 +850,15 @@ static int nativeMap(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(fnLiteralIdn); Toy_freeLiteral(fnLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//check type //check type
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to _map\n"); interpreter->errorOutput("Incorrect argument type passed to map\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral); Toy_freeLiteral(fnLiteral);
return -1; return -1;
@@ -742,8 +874,8 @@ static int nativeMap(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
Toy_pushLiteralArray(&arguments, indexLiteral); Toy_pushLiteralArray(&arguments, indexLiteral);
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
Toy_LiteralArray returns; Toy_LiteralArray returns;
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
@@ -777,8 +909,8 @@ static int nativeMap(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key); Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
Toy_LiteralArray returns; Toy_LiteralArray returns;
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
@@ -808,7 +940,7 @@ static int nativeMap(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
static int nativeReduce(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeReduce(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 3) { if (arguments->count != 3) {
interpreter->errorOutput("Incorrect number of arguments to _reduce\n"); interpreter->errorOutput("Incorrect number of arguments to reduce\n");
return -1; return -1;
} }
@@ -833,9 +965,16 @@ static int nativeReduce(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
Toy_freeLiteral(fnLiteralIdn); 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 //check type
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to _reduce\n"); interpreter->errorOutput("Incorrect argument type passed to reduce\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(defaultLiteral); Toy_freeLiteral(defaultLiteral);
Toy_freeLiteral(fnLiteral); Toy_freeLiteral(fnLiteral);
@@ -849,9 +988,9 @@ static int nativeReduce(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
Toy_pushLiteralArray(&arguments, indexLiteral);
Toy_pushLiteralArray(&arguments, defaultLiteral); Toy_pushLiteralArray(&arguments, defaultLiteral);
Toy_pushLiteralArray(&arguments, indexLiteral);
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
Toy_LiteralArray returns; Toy_LiteralArray returns;
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
@@ -879,9 +1018,9 @@ static int nativeReduce(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key);
Toy_pushLiteralArray(&arguments, defaultLiteral); Toy_pushLiteralArray(&arguments, defaultLiteral);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
Toy_LiteralArray returns; Toy_LiteralArray returns;
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
@@ -909,7 +1048,7 @@ static int nativeReduce(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _some\n"); interpreter->errorOutput("Incorrect number of arguments to some\n");
return -1; return -1;
} }
@@ -928,9 +1067,15 @@ static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(fnLiteralIdn); Toy_freeLiteral(fnLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//check type //check type
if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to _some\n"); interpreter->errorOutput("Incorrect argument type passed to some\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral); Toy_freeLiteral(fnLiteral);
return -1; return -1;
@@ -946,8 +1091,8 @@ static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
Toy_pushLiteralArray(&arguments, indexLiteral); Toy_pushLiteralArray(&arguments, indexLiteral);
Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]);
Toy_LiteralArray returns; Toy_LiteralArray returns;
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
@@ -987,8 +1132,8 @@ static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key); Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key);
Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value);
Toy_LiteralArray returns; Toy_LiteralArray returns;
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
@@ -1045,8 +1190,8 @@ static void recursiveLiteralQuicksortUtil(Toy_Interpreter* interpreter, Toy_Lite
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
Toy_initLiteralArray(&returns); Toy_initLiteralArray(&returns);
Toy_pushLiteralArray(&arguments, ptr[literalCount - 1]); //backwards
Toy_pushLiteralArray(&arguments, ptr[checker]); Toy_pushLiteralArray(&arguments, ptr[checker]);
Toy_pushLiteralArray(&arguments, ptr[literalCount - 1]);
Toy_callLiteralFn(interpreter, fnCompareLiteral, &arguments, &returns); Toy_callLiteralFn(interpreter, fnCompareLiteral, &arguments, &returns);
@@ -1073,7 +1218,7 @@ static void recursiveLiteralQuicksortUtil(Toy_Interpreter* interpreter, Toy_Lite
static int nativeSort(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeSort(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _sort\n"); interpreter->errorOutput("Incorrect number of arguments to sort\n");
return -1; return -1;
} }
@@ -1092,9 +1237,15 @@ static int nativeSort(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(fnLiteralIdn); Toy_freeLiteral(fnLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) {
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//check type //check type
if (!TOY_IS_ARRAY(selfLiteral) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { if (!TOY_IS_ARRAY(selfLiteral) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to _sort\n"); interpreter->errorOutput("Incorrect argument type passed to sort\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral); Toy_freeLiteral(fnLiteral);
return -1; return -1;
@@ -1116,7 +1267,7 @@ static int nativeSort(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _toLower\n"); interpreter->errorOutput("Incorrect number of arguments to toLower\n");
return -1; return -1;
} }
@@ -1128,8 +1279,13 @@ static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_freeLiteral(selfLiteralIdn); Toy_freeLiteral(selfLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
return -1;
}
if (!TOY_IS_STRING(selfLiteral)) { if (!TOY_IS_STRING(selfLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _toLower\n"); interpreter->errorOutput("Incorrect argument type passed to toLower\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
return -1; return -1;
} }
@@ -1176,7 +1332,7 @@ static void toStringUtil(const char* input) {
static int nativeToString(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeToString(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _toString\n"); interpreter->errorOutput("Incorrect number of arguments to toString\n");
return -1; return -1;
} }
@@ -1189,6 +1345,11 @@ static int nativeToString(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
Toy_freeLiteral(selfLiteralIdn); Toy_freeLiteral(selfLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
return -1;
}
//BUGFIX: probably an undefined variable //BUGFIX: probably an undefined variable
if (TOY_IS_IDENTIFIER(selfLiteral)) { if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
@@ -1216,7 +1377,7 @@ static int nativeToString(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
static int nativeToUpper(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeToUpper(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _toUpper\n"); interpreter->errorOutput("Incorrect number of arguments to toUpper\n");
return -1; return -1;
} }
@@ -1228,8 +1389,13 @@ static int nativeToUpper(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_freeLiteral(selfLiteralIdn); Toy_freeLiteral(selfLiteralIdn);
} }
if (TOY_IS_IDENTIFIER(selfLiteral)) {
Toy_freeLiteral(selfLiteral);
return -1;
}
if (!TOY_IS_STRING(selfLiteral)) { if (!TOY_IS_STRING(selfLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _toUpper\n"); interpreter->errorOutput("Incorrect argument type passed to toUpper\n");
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
return -1; return -1;
} }
@@ -1262,7 +1428,7 @@ static int nativeToUpper(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
static int nativeTrim(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeTrim(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count < 1 || arguments->count > 2) { if (arguments->count < 1 || arguments->count > 2) {
interpreter->errorOutput("Incorrect number of arguments to _trim\n"); interpreter->errorOutput("Incorrect number of arguments to trim\n");
return -1; return -1;
} }
@@ -1288,8 +1454,14 @@ static int nativeTrim(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(selfLiteralIdn); Toy_freeLiteral(selfLiteralIdn);
} }
if (!TOY_IS_STRING(selfLiteral)) { if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(trimCharsLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _trim\n"); 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(trimCharsLiteral);
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
return -1; return -1;
@@ -1373,7 +1545,7 @@ static int nativeTrim(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
static int nativeTrimBegin(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeTrimBegin(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count < 1 || arguments->count > 2) { if (arguments->count < 1 || arguments->count > 2) {
interpreter->errorOutput("Incorrect number of arguments to _trimBegin\n"); interpreter->errorOutput("Incorrect number of arguments to trimBegin\n");
return -1; return -1;
} }
@@ -1399,8 +1571,14 @@ static int nativeTrimBegin(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
Toy_freeLiteral(selfLiteralIdn); Toy_freeLiteral(selfLiteralIdn);
} }
if (!TOY_IS_STRING(selfLiteral)) { if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(trimCharsLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _trimBegin\n"); 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(trimCharsLiteral);
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
return -1; return -1;
@@ -1461,7 +1639,7 @@ static int nativeTrimBegin(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
static int nativeTrimEnd(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeTrimEnd(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count < 1 || arguments->count > 2) { if (arguments->count < 1 || arguments->count > 2) {
interpreter->errorOutput("Incorrect number of arguments to _trimEnd\n"); interpreter->errorOutput("Incorrect number of arguments to trimEnd\n");
return -1; return -1;
} }
@@ -1487,8 +1665,14 @@ static int nativeTrimEnd(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen
Toy_freeLiteral(selfLiteralIdn); Toy_freeLiteral(selfLiteralIdn);
} }
if (!TOY_IS_STRING(selfLiteral)) { if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(trimCharsLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _trimEnd\n"); 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(trimCharsLiteral);
Toy_freeLiteral(selfLiteral); Toy_freeLiteral(selfLiteral);
return -1; return -1;
@@ -1556,26 +1740,28 @@ typedef struct Natives {
int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) { int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
//build the natives list //build the natives list
Natives natives[] = { Natives natives[] = {
{"abs", nativeAbs},
{"clock", nativeClock}, {"clock", nativeClock},
{"_concat", nativeConcat}, //array, dictionary, string {"concat", nativeConcat}, //array, dictionary, string
{"_containsKey", nativeContainsKey}, //dictionary {"containsKey", nativeContainsKey}, //dictionary
{"_containsValue", nativeContainsValue}, //array, dictionary {"containsValue", nativeContainsValue}, //array, dictionary
{"_every", nativeEvery}, //array, dictionary {"every", nativeEvery}, //array, dictionary
{"_filter", nativeFilter}, //array, dictionary {"filter", nativeFilter}, //array, dictionary
{"_forEach", nativeForEach}, //array, dictionary {"forEach", nativeForEach}, //array, dictionary
{"_getKeys", nativeGetKeys}, //dictionary {"getKeys", nativeGetKeys}, //dictionary
{"_getValues", nativeGetValues}, //dictionary {"getValues", nativeGetValues}, //dictionary
{"_indexOf", nativeIndexOf}, //array {"hash", nativeHash},
{"_map", nativeMap}, //array, dictionary {"indexOf", nativeIndexOf}, //array
{"_reduce", nativeReduce}, //array, dictionary {"map", nativeMap}, //array, dictionary
{"_some", nativeSome}, //array, dictionary {"reduce", nativeReduce}, //array, dictionary
{"_sort", nativeSort}, //array {"some", nativeSome}, //array, dictionary
{"_toLower", nativeToLower}, //string {"sort", nativeSort}, //array
{"_toString", nativeToString}, //array, dictionary {"toLower", nativeToLower}, //string
{"_toUpper", nativeToUpper}, //string {"toString", nativeToString}, //array, dictionary
{"_trim", nativeTrim}, //string {"toUpper", nativeToUpper}, //string
{"_trimBegin", nativeTrimBegin}, //string {"trim", nativeTrim}, //string
{"_trimEnd", nativeTrimEnd}, //string {"trimBegin", nativeTrimBegin}, //string
{"trimEnd", nativeTrimEnd}, //string
{NULL, NULL} {NULL, NULL}
}; };
+5 -3
View File
@@ -1,6 +1,7 @@
#include "repl_tools.h" #include "repl_tools.h"
#include "lib_about.h" #include "lib_about.h"
#include "lib_standard.h" #include "lib_standard.h"
#include "lib_random.h"
#include "lib_runner.h" #include "lib_runner.h"
#include "toy_console_colors.h" #include "toy_console_colors.h"
@@ -29,6 +30,7 @@ void repl(const char* initialInput) {
//inject the libs //inject the libs
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout); Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard); Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom);
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner); Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
for(;;) { for(;;) {
@@ -75,7 +77,7 @@ void repl(const char* initialInput) {
if (!error) { if (!error) {
//get the bytecode dump //get the bytecode dump
int size = 0; size_t size = 0;
unsigned char* tb = Toy_collateCompiler(&compiler, &size); unsigned char* tb = Toy_collateCompiler(&compiler, &size);
//run the bytecode //run the bytecode
@@ -180,7 +182,7 @@ int main(int argc, const char* argv[]) {
//compile and save //compile and save
size_t size = 0; size_t size = 0;
const char* source = Toy_readFile(Toy_commandLine.compilefile, &size); const char* source = (const char*)Toy_readFile(Toy_commandLine.compilefile, &size);
if (!source) { if (!source) {
return 1; return 1;
} }
@@ -220,7 +222,7 @@ int main(int argc, const char* argv[]) {
} }
size_t size; size_t size;
initialSource = Toy_readFile(Toy_commandLine.initialfile, &size); initialSource = (const char*)Toy_readFile(Toy_commandLine.initialfile, &size);
} }
repl(initialSource); repl(initialSource);
+8 -6
View File
@@ -1,6 +1,7 @@
#include "repl_tools.h" #include "repl_tools.h"
#include "lib_about.h" #include "lib_about.h"
#include "lib_standard.h" #include "lib_standard.h"
#include "lib_random.h"
#include "lib_runner.h" #include "lib_runner.h"
#include "toy_console_colors.h" #include "toy_console_colors.h"
@@ -14,7 +15,7 @@
#include <stdlib.h> #include <stdlib.h>
//IO functions //IO functions
const char* Toy_readFile(const char* path, size_t* fileSize) { const unsigned char* Toy_readFile(const char* path, size_t* fileSize) {
FILE* file = fopen(path, "rb"); FILE* file = fopen(path, "rb");
if (file == NULL) { if (file == NULL) {
@@ -26,14 +27,14 @@ const char* Toy_readFile(const char* path, size_t* fileSize) {
*fileSize = ftell(file); *fileSize = ftell(file);
rewind(file); rewind(file);
char* buffer = (char*)malloc(*fileSize + 1); unsigned char* buffer = (unsigned char*)malloc(*fileSize + 1);
if (buffer == NULL) { if (buffer == NULL) {
fprintf(stderr, TOY_CC_ERROR "Not enough memory to read \"%s\"\n" TOY_CC_RESET, path); fprintf(stderr, TOY_CC_ERROR "Not enough memory to read \"%s\"\n" TOY_CC_RESET, path);
return NULL; return NULL;
} }
size_t bytesRead = fread(buffer, sizeof(char), *fileSize, file); size_t bytesRead = fread(buffer, sizeof(unsigned char), *fileSize, file);
buffer[*fileSize] = '\0'; //NOTE: fread doesn't append this buffer[*fileSize] = '\0'; //NOTE: fread doesn't append this
@@ -94,7 +95,7 @@ const unsigned char* Toy_compileString(const char* source, size_t* size) {
} }
//get the bytecode dump //get the bytecode dump
const unsigned char* tb = Toy_collateCompiler(&compiler, (int*)(size)); const unsigned char* tb = Toy_collateCompiler(&compiler, size);
//cleanup //cleanup
Toy_freeCompiler(&compiler); Toy_freeCompiler(&compiler);
@@ -112,6 +113,7 @@ void Toy_runBinary(const unsigned char* tb, size_t size) {
//inject the libs //inject the libs
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout); Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard); Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom);
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner); Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
Toy_runInterpreter(&interpreter, tb, (int)size); Toy_runInterpreter(&interpreter, tb, (int)size);
@@ -120,7 +122,7 @@ void Toy_runBinary(const unsigned char* tb, size_t size) {
void Toy_runBinaryFile(const char* fname) { void Toy_runBinaryFile(const char* fname) {
size_t size = 0; //not used size_t size = 0; //not used
const unsigned char* tb = (const unsigned char*)Toy_readFile(fname, &size); const unsigned char* tb = Toy_readFile(fname, &size);
if (!tb) { if (!tb) {
return; return;
} }
@@ -140,7 +142,7 @@ void Toy_runSource(const char* source) {
void Toy_runSourceFile(const char* fname) { void Toy_runSourceFile(const char* fname) {
size_t size = 0; //not used size_t size = 0; //not used
const char* source = Toy_readFile(fname, &size); const char* source = (const char*)Toy_readFile(fname, &size);
if (!source) { if (!source) {
return; return;
} }
+1 -1
View File
@@ -2,7 +2,7 @@
#include "toy_common.h" #include "toy_common.h"
const char* Toy_readFile(const char* path, size_t* fileSize); const unsigned char* Toy_readFile(const char* path, size_t* fileSize);
int Toy_writeFile(const char* path, const unsigned char* bytes, size_t size); int Toy_writeFile(const char* path, const unsigned char* bytes, size_t size);
const unsigned char* Toy_compileString(const char* source, size_t* size); const unsigned char* Toy_compileString(const char* source, size_t* 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";
+1 -1
View File
@@ -17,5 +17,5 @@ fn fib(n : int) {
for (var i = 0; i < 40; i++) { for (var i = 0; i < 40; i++) {
var res = fib(i); var res = fib(i);
print string i + ": " + string res + "\n"; print string i + ": " + string res;
} }
+2 -1
View File
@@ -1,3 +1,4 @@
//WARNING: please think twice before using this in a test
fn fib(n : int) { fn fib(n : int) {
if (n < 2) return n; if (n < 2) return n;
return fib(n-1) + fib(n-2); return fib(n-1) + fib(n-2);
@@ -5,5 +6,5 @@ fn fib(n : int) {
for (var i = 0; i < 20; i++) { for (var i = 0; i < 20; i++) {
var res = fib(i); var res = fib(i);
print string i + ": " + string res + "\n"; print string i + ": " + string res;
} }
+18 -3
View File
@@ -1,3 +1,18 @@
/*
How to run this program:
toyrepl -n -t scripts/level.toy
How to move around:
move(up);
move(down);
move(left);
move(right);
*/
//constants //constants
var WIDTH: int const = 12; var WIDTH: int const = 12;
var HEIGHT: int const = 12; var HEIGHT: int const = 12;
@@ -19,8 +34,8 @@ var tiles: [[int]] const = [
]; ];
var tileset: [int: string] const = [ var tileset: [int: string] const = [
0: " ", 0: " ",
1: " X " 1: "X "
]; ];
//variables //variables
@@ -33,7 +48,7 @@ fn draw() {
for (var i: int = 0; i < WIDTH; i++) { for (var i: int = 0; i < WIDTH; i++) {
//draw the player pos //draw the player pos
if (i == posX && j == posY) { if (i == posX && j == posY) {
print " O "; print "O ";
continue; 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();
}
+3 -3
View File
@@ -1,5 +1,5 @@
//number of iterations //number of iterations
var SIZE: int const = 260; var SIZE: int const = 100;
//lookup table //lookup table
var lookup = [ var lookup = [
@@ -29,7 +29,7 @@ for (var i = 0; i < SIZE -1; i++) {
prev += " "; prev += " ";
} }
prev += "*"; //initial prev += "*"; //initial
print prev + "\n"; print prev;
//run //run
for (var iteration = 0; iteration < SIZE -1; iteration++) { for (var iteration = 0; iteration < SIZE -1; iteration++) {
@@ -44,6 +44,6 @@ for (var iteration = 0; iteration < SIZE -1; iteration++) {
//right //right
output += (lookup[prev[SIZE-2]][prev[SIZE-1]][" "]); output += (lookup[prev[SIZE-2]][prev[SIZE-1]][" "]);
print output + "\n"; print output;
prev = output; prev = output;
} }
-27
View File
@@ -1,27 +0,0 @@
import compound;
fn less(a, b) {
return a < b;
}
fn greater(a, b) {
return a > b;
}
var a = [7, 2, 1, 8, 6, 3, 5, 4];
var b = [7, 2, 1, 4, 6, 3, 5, 8];
var c = [1, 2, 3, 4, 5, 6, 7, 8];
var d = [7, 2, 1, 8, 6, 3, 5, 4];
a = a.sort(less);
b = b.sort(less);
c = c.sort(less);
d = d.sort(greater);
assert a == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) failed";
assert b == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) with pivot high failed";
assert c == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) pre-sorted array failed";
assert d == [8, 7, 6, 5, 4, 3, 2, 1], "array.sort(greater) failed";
print "All good";
+12
View File
@@ -135,6 +135,10 @@ static void freeASTNodeCustom(Toy_ASTNode* node, bool freeSelf) {
Toy_freeLiteral(node->import.identifier); Toy_freeLiteral(node->import.identifier);
Toy_freeLiteral(node->import.alias); Toy_freeLiteral(node->import.alias);
break; break;
case TOY_AST_NODE_PASS:
//EMPTY
break;
} }
if (freeSelf) { if (freeSelf) {
@@ -383,3 +387,11 @@ void Toy_emitASTNodeImport(Toy_ASTNode** nodeHandle, Toy_Literal identifier, Toy
*nodeHandle = tmp; *nodeHandle = tmp;
} }
void Toy_emitASTNodePass(Toy_ASTNode** nodeHandle) {
Toy_ASTNode* tmp = TOY_ALLOCATE(Toy_ASTNode, 1);
tmp->type = TOY_AST_NODE_PASS;
*nodeHandle = tmp;
}
+4
View File
@@ -34,6 +34,7 @@ typedef enum Toy_ASTNodeType {
TOY_AST_NODE_PREFIX_DECREMENT, //decrement a variable TOY_AST_NODE_PREFIX_DECREMENT, //decrement a variable
TOY_AST_NODE_POSTFIX_DECREMENT, //decrement a variable TOY_AST_NODE_POSTFIX_DECREMENT, //decrement a variable
TOY_AST_NODE_IMPORT, //import a library TOY_AST_NODE_IMPORT, //import a library
TOY_AST_NODE_PASS, //for doing nothing
} Toy_ASTNodeType; } Toy_ASTNodeType;
//literals //literals
@@ -238,6 +239,9 @@ typedef struct Toy_NodeImport {
Toy_Literal alias; Toy_Literal alias;
} Toy_NodeImport; } Toy_NodeImport;
//for doing nothing
void Toy_emitASTNodePass(Toy_ASTNode** nodeHandle);
union Toy_private_node { union Toy_private_node {
Toy_ASTNodeType type; Toy_ASTNodeType type;
Toy_NodeLiteral atomic; Toy_NodeLiteral atomic;
+153 -34
View File
@@ -4,6 +4,7 @@
#include "toy_literal.h" #include "toy_literal.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
//static math utils, copied from the interpreter //static math utils, copied from the interpreter
static Toy_Literal addition(Toy_Interpreter* interpreter, Toy_Literal lhs, Toy_Literal rhs) { static Toy_Literal addition(Toy_Interpreter* interpreter, Toy_Literal lhs, Toy_Literal rhs) {
@@ -278,6 +279,17 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(idn); 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 //second and third are bad args to dictionaries
if (!TOY_IS_NULL(second) || !TOY_IS_NULL(third)) { if (!TOY_IS_NULL(second) || !TOY_IS_NULL(third)) {
interpreter->errorOutput("Index slicing not allowed for dictionaries\n"); interpreter->errorOutput("Index slicing not allowed for dictionaries\n");
@@ -400,6 +412,17 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(idn); 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 //handle each error case
if (!TOY_IS_INTEGER(first) || TOY_AS_INTEGER(first) < 0 || TOY_AS_INTEGER(first) >= TOY_AS_ARRAY(compound)->count) { 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"); interpreter->errorOutput("Bad first indexing\n");
@@ -542,6 +565,17 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(idn); 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 //handle each error case
if (!TOY_IS_INTEGER(first) || TOY_AS_INTEGER(first) < 0 || TOY_AS_INTEGER(first) >= TOY_AS_ARRAY(compound)->count) { 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"); interpreter->errorOutput("Bad first indexing assignment\n");
@@ -704,6 +738,17 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(idn); 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); Toy_Literal value = Toy_getLiteralArray(TOY_AS_ARRAY(compound), first);
if (TOY_IS_STRING(op) && Toy_equalsRefStringCString(TOY_AS_STRING(op), "+=")) { if (TOY_IS_STRING(op) && Toy_equalsRefStringCString(TOY_AS_STRING(op), "+=")) {
@@ -792,6 +837,17 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(idn); 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 //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))) { if (!TOY_IS_INTEGER(first) || TOY_AS_INTEGER(first) < 0 || TOY_AS_INTEGER(first) >= (int)Toy_lengthRefString(TOY_AS_STRING(compound))) {
interpreter->errorOutput("Bad first indexing in string\n"); interpreter->errorOutput("Bad first indexing in string\n");
@@ -936,6 +992,17 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_freeLiteral(idn); 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 //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))) { if (!TOY_IS_INTEGER(first) || TOY_AS_INTEGER(first) < 0 || TOY_AS_INTEGER(first) >= (int)Toy_lengthRefString(TOY_AS_STRING(compound))) {
interpreter->errorOutput("Bad first indexing in string assignment\n"); interpreter->errorOutput("Bad first indexing in string assignment\n");
@@ -1063,7 +1130,7 @@ int Toy_private_index(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//if wrong number of arguments, fail //if wrong number of arguments, fail
if (arguments->count != 3) { if (arguments->count != 3) {
interpreter->errorOutput("Incorrect number of arguments to _set\n"); interpreter->errorOutput("Incorrect number of arguments to set\n");
return -1; return -1;
} }
@@ -1073,12 +1140,16 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
Toy_Literal val = arguments->literals[2]; Toy_Literal val = arguments->literals[2];
if (!TOY_IS_IDENTIFIER(idn)) { if (!TOY_IS_IDENTIFIER(idn)) {
interpreter->errorOutput("Expected identifier in _set\n"); interpreter->errorOutput("Expected identifier in set\n");
return -1; return -1;
} }
Toy_parseIdentifierToValue(interpreter, &obj); Toy_parseIdentifierToValue(interpreter, &obj);
if (TOY_IS_IDENTIFIER(obj)) {
return -1;
}
bool freeKey = false; bool freeKey = false;
if (TOY_IS_IDENTIFIER(key)) { if (TOY_IS_IDENTIFIER(key)) {
Toy_parseIdentifierToValue(interpreter, &key); Toy_parseIdentifierToValue(interpreter, &key);
@@ -1091,26 +1162,40 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
freeVal = true; 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) { switch(obj.type) {
case TOY_LITERAL_ARRAY: { 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) { if (TOY_AS_TYPE(typeLiteral).typeOf == TOY_LITERAL_ARRAY) {
Toy_Literal subtypeLiteral = ((Toy_Literal*)(TOY_AS_TYPE(typeLiteral).subtypes))[0]; 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) { 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; return -1;
} }
} }
Toy_freeLiteral(typeLiteral);
if (!TOY_IS_INTEGER(key)) { if (!TOY_IS_INTEGER(key)) {
interpreter->errorOutput("Expected integer index in _set\n"); interpreter->errorOutput("Expected integer index in set\n");
return -1; return -1;
} }
if (TOY_AS_ARRAY(obj)->count <= TOY_AS_INTEGER(key) || TOY_AS_INTEGER(key) < 0) { if (TOY_AS_INTEGER(key) >= TOY_AS_ARRAY(obj)->count || TOY_AS_INTEGER(key) < 0) {
interpreter->errorOutput("Index out of bounds in _set\n"); interpreter->errorOutput("Index out of bounds in set\n");
return -1; return -1;
} }
@@ -1119,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); TOY_AS_ARRAY(obj)->literals[TOY_AS_INTEGER(key)] = Toy_copyLiteral(val);
if (!Toy_setScopeVariable(interpreter->scope, idn, obj, true)) { 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); Toy_printLiteralCustom(val, interpreter->errorOutput);
interpreter->errorOutput("\"\n"); interpreter->errorOutput("\"\n");
return -1; return -1;
@@ -1136,12 +1221,12 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
Toy_Literal valSubtypeLiteral = ((Toy_Literal*)(TOY_AS_TYPE(typeLiteral).subtypes))[1]; 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) { 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; return -1;
} }
if (TOY_AS_TYPE(valSubtypeLiteral).typeOf != TOY_LITERAL_ANY && TOY_AS_TYPE(valSubtypeLiteral).typeOf != val.type) { 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; return -1;
} }
} }
@@ -1149,7 +1234,7 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
Toy_setLiteralDictionary(TOY_AS_DICTIONARY(obj), key, val); Toy_setLiteralDictionary(TOY_AS_DICTIONARY(obj), key, val);
if (!Toy_setScopeVariable(interpreter->scope, idn, obj, true)) { 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); Toy_printLiteralCustom(val, interpreter->errorOutput);
interpreter->errorOutput("\"\n"); interpreter->errorOutput("\"\n");
return -1; return -1;
@@ -1159,7 +1244,7 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
} }
default: default:
interpreter->errorOutput("Incorrect compound type in _set: "); interpreter->errorOutput("Incorrect compound type in set: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput); Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\"\n"); interpreter->errorOutput("\"\n");
return -1; return -1;
@@ -1181,7 +1266,7 @@ int Toy_private_set(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
int Toy_private_get(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { int Toy_private_get(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//if wrong number of arguments, fail //if wrong number of arguments, fail
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _get"); interpreter->errorOutput("Incorrect number of arguments to get");
return -1; return -1;
} }
@@ -1200,15 +1285,25 @@ int Toy_private_get(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
freeKey = true; 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) { switch(obj.type) {
case TOY_LITERAL_ARRAY: { case TOY_LITERAL_ARRAY: {
if (!TOY_IS_INTEGER(key)) { if (!TOY_IS_INTEGER(key)) {
interpreter->errorOutput("Expected integer index in _get\n"); interpreter->errorOutput("Expected integer index in get\n");
return -1; return -1;
} }
if (TOY_AS_ARRAY(obj)->count <= TOY_AS_INTEGER(key) || TOY_AS_INTEGER(key) < 0) { if (TOY_AS_INTEGER(key) >= TOY_AS_ARRAY(obj)->count || TOY_AS_INTEGER(key) < 0) {
interpreter->errorOutput("Index out of bounds in _get\n"); interpreter->errorOutput("Index out of bounds in get\n");
return -1; return -1;
} }
@@ -1242,7 +1337,7 @@ int Toy_private_get(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
} }
default: default:
interpreter->errorOutput("Incorrect compound type in _get \""); interpreter->errorOutput("Incorrect compound type in get \"");
Toy_printLiteralCustom(obj, interpreter->errorOutput); Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\"\n"); interpreter->errorOutput("\"\n");
return -1; return -1;
@@ -1252,7 +1347,7 @@ int Toy_private_get(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
int Toy_private_push(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { int Toy_private_push(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//if wrong number of arguments, fail //if wrong number of arguments, fail
if (arguments->count != 2) { if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _push\n"); interpreter->errorOutput("Incorrect number of arguments to push\n");
return -1; return -1;
} }
@@ -1261,35 +1356,47 @@ int Toy_private_push(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_Literal val = arguments->literals[1]; Toy_Literal val = arguments->literals[1];
if (!TOY_IS_IDENTIFIER(idn)) { if (!TOY_IS_IDENTIFIER(idn)) {
interpreter->errorOutput("Expected identifier in _push\n"); interpreter->errorOutput("Expected identifier in push\n");
return -1; return -1;
} }
Toy_parseIdentifierToValue(interpreter, &obj); Toy_parseIdentifierToValue(interpreter, &obj);
if (TOY_IS_IDENTIFIER(obj)) {
return -1;
}
bool freeVal = false; bool freeVal = false;
if (TOY_IS_IDENTIFIER(val)) { if (TOY_IS_IDENTIFIER(val)) {
Toy_parseIdentifierToValue(interpreter, &val); Toy_parseIdentifierToValue(interpreter, &val);
freeVal = true; freeVal = true;
} }
if (TOY_IS_IDENTIFIER(val)) {
return -1;
}
switch(obj.type) { switch(obj.type) {
case TOY_LITERAL_ARRAY: { 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) { if (TOY_AS_TYPE(typeLiteral).typeOf == TOY_LITERAL_ARRAY) {
Toy_Literal subtypeLiteral = ((Toy_Literal*)(TOY_AS_TYPE(typeLiteral).subtypes))[0]; 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) { 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; return -1;
} }
} }
Toy_freeLiteral(typeLiteral);
Toy_pushLiteralArray(TOY_AS_ARRAY(obj), val); 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 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); Toy_printLiteralCustom(val, interpreter->errorOutput);
interpreter->errorOutput("\"\n"); interpreter->errorOutput("\"\n");
return -1; return -1;
@@ -1305,7 +1412,7 @@ int Toy_private_push(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
} }
default: default:
interpreter->errorOutput("Incorrect compound type in _push: "); interpreter->errorOutput("Incorrect compound type in push: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput); Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n"); interpreter->errorOutput("\n");
return -1; return -1;
@@ -1315,7 +1422,7 @@ int Toy_private_push(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
int Toy_private_pop(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { int Toy_private_pop(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//if wrong number of arguments, fail //if wrong number of arguments, fail
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _pop\n"); interpreter->errorOutput("Incorrect number of arguments to pop\n");
return -1; return -1;
} }
@@ -1323,12 +1430,16 @@ int Toy_private_pop(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
Toy_Literal obj = arguments->literals[0]; Toy_Literal obj = arguments->literals[0];
if (!TOY_IS_IDENTIFIER(idn)) { if (!TOY_IS_IDENTIFIER(idn)) {
interpreter->errorOutput("Expected identifier in _pop\n"); interpreter->errorOutput("Expected identifier in pop\n");
return -1; return -1;
} }
Toy_parseIdentifierToValue(interpreter, &obj); Toy_parseIdentifierToValue(interpreter, &obj);
if (TOY_IS_IDENTIFIER(obj)) {
return -1;
}
switch(obj.type) { switch(obj.type) {
case TOY_LITERAL_ARRAY: { case TOY_LITERAL_ARRAY: {
Toy_Literal lit = Toy_popLiteralArray(TOY_AS_ARRAY(obj)); Toy_Literal lit = Toy_popLiteralArray(TOY_AS_ARRAY(obj));
@@ -1336,7 +1447,7 @@ int Toy_private_pop(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
Toy_freeLiteral(lit); Toy_freeLiteral(lit);
if (!Toy_setScopeVariable(interpreter->scope, idn, obj, true)) { //TODO: could definitely be more efficient than overwriting the whole original object 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); Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n"); interpreter->errorOutput("\n");
return -1; return -1;
@@ -1348,7 +1459,7 @@ int Toy_private_pop(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
} }
default: default:
interpreter->errorOutput("Incorrect compound type in _pop: "); interpreter->errorOutput("Incorrect compound type in pop: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput); Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n"); interpreter->errorOutput("\n");
return -1; return -1;
@@ -1358,7 +1469,7 @@ int Toy_private_pop(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
int Toy_private_length(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { int Toy_private_length(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//if wrong number of arguments, fail //if wrong number of arguments, fail
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _length\n"); interpreter->errorOutput("Incorrect number of arguments to length\n");
return -1; return -1;
} }
@@ -1370,6 +1481,10 @@ int Toy_private_length(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
freeObj = true; freeObj = true;
} }
if (TOY_IS_IDENTIFIER(obj)) {
return -1;
}
switch(obj.type) { switch(obj.type) {
case TOY_LITERAL_ARRAY: { case TOY_LITERAL_ARRAY: {
Toy_Literal lit = TOY_TO_INTEGER_LITERAL( TOY_AS_ARRAY(obj)->count ); Toy_Literal lit = TOY_TO_INTEGER_LITERAL( TOY_AS_ARRAY(obj)->count );
@@ -1393,7 +1508,7 @@ int Toy_private_length(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
} }
default: default:
interpreter->errorOutput("Incorrect compound type in _length: "); interpreter->errorOutput("Incorrect compound type in length: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput); Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n"); interpreter->errorOutput("\n");
return -1; return -1;
@@ -1409,7 +1524,7 @@ int Toy_private_length(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
int Toy_private_clear(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { int Toy_private_clear(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//if wrong number of arguments, fail //if wrong number of arguments, fail
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _clear\n"); interpreter->errorOutput("Incorrect number of arguments to clear\n");
return -1; return -1;
} }
@@ -1417,12 +1532,16 @@ int Toy_private_clear(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_Literal obj = arguments->literals[0]; Toy_Literal obj = arguments->literals[0];
if (!TOY_IS_IDENTIFIER(idn)) { if (!TOY_IS_IDENTIFIER(idn)) {
interpreter->errorOutput("expected identifier in _clear\n"); interpreter->errorOutput("expected identifier in clear\n");
return -1; return -1;
} }
Toy_parseIdentifierToValue(interpreter, &obj); Toy_parseIdentifierToValue(interpreter, &obj);
if (TOY_IS_IDENTIFIER(obj)) {
return -1;
}
//NOTE: just pass in new compounds //NOTE: just pass in new compounds
switch(obj.type) { switch(obj.type) {
@@ -1433,7 +1552,7 @@ int Toy_private_clear(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_Literal obj = TOY_TO_ARRAY_LITERAL(array); Toy_Literal obj = TOY_TO_ARRAY_LITERAL(array);
if (!Toy_setScopeVariable(interpreter->scope, idn, obj, true)) { 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); Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n"); interpreter->errorOutput("\n");
return -1; return -1;
@@ -1451,7 +1570,7 @@ int Toy_private_clear(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
Toy_Literal obj = TOY_TO_DICTIONARY_LITERAL(dictionary); Toy_Literal obj = TOY_TO_DICTIONARY_LITERAL(dictionary);
if (!Toy_setScopeVariable(interpreter->scope, idn, obj, true)) { 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); Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n"); interpreter->errorOutput("\n");
return -1; return -1;
@@ -1463,7 +1582,7 @@ int Toy_private_clear(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
} }
default: default:
interpreter->errorOutput("Incorrect compound type in _clear: "); interpreter->errorOutput("Incorrect compound type in clear: ");
Toy_printLiteralCustom(obj, interpreter->errorOutput); Toy_printLiteralCustom(obj, interpreter->errorOutput);
interpreter->errorOutput("\n"); interpreter->errorOutput("\n");
return -1; return -1;
+29 -23
View File
@@ -15,22 +15,22 @@ STATIC_ASSERT(sizeof(unsigned char) == 1);
STATIC_ASSERT(sizeof(unsigned short) == 2); STATIC_ASSERT(sizeof(unsigned short) == 2);
STATIC_ASSERT(sizeof(unsigned int) == 4); STATIC_ASSERT(sizeof(unsigned int) == 4);
//declare the singleton //declare the singleton with default values
Toy_CommandLine Toy_commandLine; Toy_CommandLine Toy_commandLine = {
.error = false,
.help = false,
.version = false,
.binaryfile = NULL,
.sourcefile = NULL,
.compilefile = NULL,
.outfile = "out.tb",
.source = NULL,
.initialfile = NULL,
.enablePrintNewline = true,
.verbose = false
};
void Toy_initCommandLine(int argc, const char* argv[]) { void Toy_initCommandLine(int argc, const char* argv[]) {
//default values
Toy_commandLine.error = false;
Toy_commandLine.help = false;
Toy_commandLine.version = false;
Toy_commandLine.binaryfile = NULL;
Toy_commandLine.sourcefile = NULL;
Toy_commandLine.compilefile = NULL;
Toy_commandLine.outfile = "out.tb";
Toy_commandLine.source = NULL;
Toy_commandLine.initialfile = NULL;
Toy_commandLine.verbose = false;
for (int i = 1; i < argc; i++) { //start at 1 to skip the program name for (int i = 1; i < argc; i++) { //start at 1 to skip the program name
Toy_commandLine.error = true; //error state by default, set to false by successful flags Toy_commandLine.error = true; //error state by default, set to false by successful flags
@@ -87,6 +87,12 @@ void Toy_initCommandLine(int argc, const char* argv[]) {
continue; continue;
} }
if (!strcmp(argv[i], "-n")) {
Toy_commandLine.enablePrintNewline = false;
Toy_commandLine.error = false;
continue;
}
//option without a flag + ending in .tb = binary input //option without a flag + ending in .tb = binary input
if (i < argc) { if (i < argc) {
if (strncmp(&(argv[i][strlen(argv[i]) - 3]), ".tb", 3) == 0) { if (strncmp(&(argv[i][strlen(argv[i]) - 3]), ".tb", 3) == 0) {
@@ -108,15 +114,15 @@ void Toy_usageCommandLine(int argc, const char* argv[]) {
void Toy_helpCommandLine(int argc, const char* argv[]) { void Toy_helpCommandLine(int argc, const char* argv[]) {
Toy_usageCommandLine(argc, argv); Toy_usageCommandLine(argc, argv);
printf("<file.tb>\t\t\tBinary input file in tb format, must be version %d.%d.%d.\n\n", TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH); printf(" -h, --help\t\t\tShow this help then exit.\n");
printf("-h\t| --help\t\tShow this help then exit.\n\n"); printf(" -v, --version\t\t\tShow version and copyright information then exit.\n");
printf("-v\t| --version\t\tShow version and copyright information then exit.\n\n"); printf(" -d, --debug\t\t\tBe verbose when operating.\n");
printf("-d\t| --debug\t\tBe verbose when operating.\n\n"); printf(" -f, --file filename\t\tParse, compile and execute the source file.\n");
printf("-f\t| --file filename\tParse, compile and execute the source file.\n\n"); printf(" -i, --input source\t\tParse, compile and execute this given string of source code.\n");
printf("-i\t| --input source\tParse, compile and execute this given string of source code.\n\n"); printf(" -c, --compile filename\tParse and compile the specified source file into an output file.\n");
printf("-c\t| --compile filename\tParse and compile the specified source file into an output file.\n\n"); printf(" -o, --output outfile\t\tName of the output file built with --compile (default: out.tb).\n");
printf("-o\t| --output outfile\tName of the output file built with --compile (default: out.tb).\n\n"); printf(" -t, --initial filename\tStart the repl as normal, after first running the given file.\n");
printf("-t\t| --initial filename\tStart the repl as normal, after first running the given file.\n\n"); printf(" -n\t\t\t\tDisable the newline character at the end of the print statement.\n");
} }
void Toy_copyrightCommandLine(int argc, const char* argv[]) { void Toy_copyrightCommandLine(int argc, const char* argv[]) {
+5 -3
View File
@@ -4,9 +4,9 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#define TOY_VERSION_MAJOR 0 #define TOY_VERSION_MAJOR 1
#define TOY_VERSION_MINOR 8 #define TOY_VERSION_MINOR 1
#define TOY_VERSION_PATCH 3 #define TOY_VERSION_PATCH 0
#define TOY_VERSION_BUILD __DATE__ " " __TIME__ #define TOY_VERSION_BUILD __DATE__ " " __TIME__
//platform/compiler-specific instructions //platform/compiler-specific instructions
@@ -39,9 +39,11 @@ typedef struct {
char* outfile; //defaults to out.tb char* outfile; //defaults to out.tb
char* source; char* source;
char* initialfile; char* initialfile;
bool enablePrintNewline;
bool verbose; bool verbose;
} Toy_CommandLine; } Toy_CommandLine;
//these are intended for the repl only, despite using the api prefix
TOY_API Toy_CommandLine Toy_commandLine; TOY_API Toy_CommandLine Toy_commandLine;
TOY_API void Toy_initCommandLine(int argc, const char* argv[]); TOY_API void Toy_initCommandLine(int argc, const char* argv[]);
+13 -4
View File
@@ -9,6 +9,7 @@
#include "toy_console_colors.h" #include "toy_console_colors.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
void Toy_initCompiler(Toy_Compiler* compiler) { void Toy_initCompiler(Toy_Compiler* compiler) {
Toy_initLiteralArray(&compiler->literalCache); Toy_initLiteralArray(&compiler->literalCache);
@@ -965,6 +966,11 @@ static Toy_Opcode Toy_writeCompilerWithJumps(Toy_Compiler* compiler, Toy_ASTNode
return TOY_OP_INDEX_ASSIGN; //override binary's instruction IF it is assign return TOY_OP_INDEX_ASSIGN; //override binary's instruction IF it is assign
} }
break; break;
case TOY_AST_NODE_PASS: {
return TOY_OP_PASS;
}
break;
} }
return TOY_OP_EOF; return TOY_OP_EOF;
@@ -976,6 +982,8 @@ void Toy_writeCompiler(Toy_Compiler* compiler, Toy_ASTNode* node) {
if (op != TOY_OP_EOF) {//compensate for indexing & dot notation being screwy if (op != TOY_OP_EOF) {//compensate for indexing & dot notation being screwy
compiler->bytecode[compiler->count++] = (unsigned char)op; //1 byte compiler->bytecode[compiler->count++] = (unsigned char)op; //1 byte
} }
//TODO: could free up AST Nodes
} }
void Toy_freeCompiler(Toy_Compiler* compiler) { void Toy_freeCompiler(Toy_Compiler* compiler) {
@@ -984,6 +992,7 @@ void Toy_freeCompiler(Toy_Compiler* compiler) {
compiler->bytecode = NULL; compiler->bytecode = NULL;
compiler->capacity = 0; compiler->capacity = 0;
compiler->count = 0; compiler->count = 0;
compiler->panic = false;
} }
static void emitByte(unsigned char** collationPtr, int* capacityPtr, int* countPtr, unsigned char byte) { static void emitByte(unsigned char** collationPtr, int* capacityPtr, int* countPtr, unsigned char byte) {
@@ -1031,7 +1040,7 @@ static void emitFloat(unsigned char** collationPtr, int* capacityPtr, int* count
} }
//return the result //return the result
static unsigned char* collateCompilerHeaderOpt(Toy_Compiler* compiler, int* size, bool embedHeader) { static unsigned char* collateCompilerHeaderOpt(Toy_Compiler* compiler, size_t* size, bool embedHeader) {
if (compiler->panic) { if (compiler->panic) {
fprintf(stderr, TOY_CC_ERROR "[internal] Can't collate a panicked compiler\n" TOY_CC_RESET); fprintf(stderr, TOY_CC_ERROR "[internal] Can't collate a panicked compiler\n" TOY_CC_RESET);
return NULL; return NULL;
@@ -1176,14 +1185,14 @@ static unsigned char* collateCompilerHeaderOpt(Toy_Compiler* compiler, int* size
void* fnCompiler = TOY_AS_FUNCTION(fn).inner.bytecode; //store the compiler here for now void* fnCompiler = TOY_AS_FUNCTION(fn).inner.bytecode; //store the compiler here for now
//collate the function into bytecode (without header) //collate the function into bytecode (without header)
int size = 0; size_t size = 0;
unsigned char* bytes = collateCompilerHeaderOpt((Toy_Compiler*)fnCompiler, &size, false); unsigned char* bytes = collateCompilerHeaderOpt((Toy_Compiler*)fnCompiler, &size, false);
//emit how long this section is, +1 for ending mark //emit how long this section is, +1 for ending mark
Toy_emitShort(&fnCollation, &fnCapacity, &fnCount, (unsigned short)size + 1); Toy_emitShort(&fnCollation, &fnCapacity, &fnCount, (unsigned short)size + 1);
//write the fn to the fn collation //write the fn to the fn collation
for (int i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
emitByte(&fnCollation, &fnCapacity, &fnCount, bytes[i]); emitByte(&fnCollation, &fnCapacity, &fnCount, bytes[i]);
} }
@@ -1291,6 +1300,6 @@ static unsigned char* collateCompilerHeaderOpt(Toy_Compiler* compiler, int* size
} }
//the whole point of the compiler is to alter bytecode, so leave it as non-const //the whole point of the compiler is to alter bytecode, so leave it as non-const
unsigned char* Toy_collateCompiler(Toy_Compiler* compiler, int* size) { unsigned char* Toy_collateCompiler(Toy_Compiler* compiler, size_t* size) {
return collateCompilerHeaderOpt(compiler, size, true); return collateCompilerHeaderOpt(compiler, size, true);
} }
+1 -1
View File
@@ -19,4 +19,4 @@ TOY_API void Toy_writeCompiler(Toy_Compiler* compiler, Toy_ASTNode* node);
TOY_API void Toy_freeCompiler(Toy_Compiler* compiler); TOY_API void Toy_freeCompiler(Toy_Compiler* compiler);
//embed the header, data section, code section, function section, etc. //embed the header, data section, code section, function section, etc.
TOY_API unsigned char* Toy_collateCompiler(Toy_Compiler* compiler, int* size); TOY_API unsigned char* Toy_collateCompiler(Toy_Compiler* compiler, size_t* size);
+199 -74
View File
@@ -12,14 +12,16 @@
#include <string.h> #include <string.h>
static void printWrapper(const char* output) { static void printWrapper(const char* output) {
printf("%s", output); if (Toy_commandLine.enablePrintNewline) {
// printf("\n"); //default new line printf("%s\n", output);
}
else {
printf("%s", output);
}
} }
static void assertWrapper(const char* output) { static void assertWrapper(const char* output) {
fprintf(stderr, TOY_CC_ERROR "Assertion failure: "); fprintf(stderr, TOY_CC_ERROR "Assertion failure: %s\n" TOY_CC_RESET, output);
fprintf(stderr, "%s", output);
fprintf(stderr, "\n" TOY_CC_RESET); //default new line
} }
static void errorWrapper(const char* output) { static void errorWrapper(const char* output) {
@@ -33,8 +35,7 @@ bool Toy_injectNativeFn(Toy_Interpreter* interpreter, const char* name, Toy_Nati
return false; return false;
} }
int identifierLength = strlen(name); Toy_Literal identifier = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString(name));
Toy_Literal identifier = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefStringLength(name, identifierLength));
//make sure the name isn't taken //make sure the name isn't taken
if (Toy_existsLiteralDictionary(&interpreter->scope->variables, identifier)) { if (Toy_existsLiteralDictionary(&interpreter->scope->variables, identifier)) {
@@ -230,6 +231,12 @@ static bool execAssert(Toy_Interpreter* interpreter) {
Toy_freeLiteral(lhsIdn); Toy_freeLiteral(lhsIdn);
} }
if (TOY_IS_IDENTIFIER(lhs)) {
Toy_freeLiteral(lhs);
Toy_freeLiteral(rhs);
return false;
}
if (!TOY_IS_STRING(rhs)) { if (!TOY_IS_STRING(rhs)) {
interpreter->errorOutput("The assert keyword needs a string as the second argument, received: "); interpreter->errorOutput("The assert keyword needs a string as the second argument, received: ");
Toy_printLiteralCustom(rhs, interpreter->errorOutput); Toy_printLiteralCustom(rhs, interpreter->errorOutput);
@@ -264,6 +271,11 @@ static bool execPrint(Toy_Interpreter* interpreter) {
Toy_freeLiteral(idn); Toy_freeLiteral(idn);
} }
if (TOY_IS_IDENTIFIER(lit)) {
Toy_freeLiteral(lit);
return false;
}
Toy_printLiteralCustom(lit, interpreter->printOutput); Toy_printLiteralCustom(lit, interpreter->printOutput);
Toy_freeLiteral(lit); Toy_freeLiteral(lit);
@@ -296,6 +308,11 @@ static bool rawLiteral(Toy_Interpreter* interpreter) {
Toy_freeLiteral(idn); Toy_freeLiteral(idn);
} }
if (TOY_IS_IDENTIFIER(lit)) {
Toy_freeLiteral(lit);
return false;
}
Toy_pushLiteralArray(&interpreter->stack, lit); Toy_pushLiteralArray(&interpreter->stack, lit);
Toy_freeLiteral(lit); Toy_freeLiteral(lit);
@@ -311,6 +328,11 @@ static bool execNegate(Toy_Interpreter* interpreter) {
Toy_freeLiteral(idn); Toy_freeLiteral(idn);
} }
if (TOY_IS_IDENTIFIER(lit)) {
Toy_freeLiteral(lit);
return false;
}
if (TOY_IS_INTEGER(lit)) { if (TOY_IS_INTEGER(lit)) {
lit = TOY_TO_INTEGER_LITERAL(-TOY_AS_INTEGER(lit)); lit = TOY_TO_INTEGER_LITERAL(-TOY_AS_INTEGER(lit));
} }
@@ -342,6 +364,11 @@ static bool execInvert(Toy_Interpreter* interpreter) {
Toy_freeLiteral(idn); Toy_freeLiteral(idn);
} }
if (TOY_IS_IDENTIFIER(lit)) {
Toy_freeLiteral(lit);
return false;
}
if (TOY_IS_BOOLEAN(lit)) { if (TOY_IS_BOOLEAN(lit)) {
lit = TOY_TO_BOOLEAN_LITERAL(!TOY_AS_BOOLEAN(lit)); lit = TOY_TO_BOOLEAN_LITERAL(!TOY_AS_BOOLEAN(lit));
} }
@@ -375,6 +402,12 @@ static bool execArithmetic(Toy_Interpreter* interpreter, Toy_Opcode opcode) {
Toy_freeLiteral(lhsIdn); 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 //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)) { if (TOY_IS_STRING(lhs) && TOY_IS_STRING(rhs) && (opcode == TOY_OP_ADDITION || opcode == TOY_OP_VAR_ADDITION_ASSIGN)) {
//check for overflow //check for overflow
@@ -507,6 +540,10 @@ static Toy_Literal parseTypeToValue(Toy_Interpreter* interpreter, Toy_Literal ty
Toy_freeLiteral(typeIdn); 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 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)) { 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++) { for (int i = 0; i < TOY_AS_TYPE(type).count; i++) {
@@ -547,6 +584,12 @@ static bool execVarDecl(Toy_Interpreter* interpreter, bool lng) {
Toy_freeLiteral(typeIdn); 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 //BUGFIX: because identifiers are getting embedded in type definitions
type = parseTypeToValue(interpreter, type); type = parseTypeToValue(interpreter, type);
@@ -564,6 +607,13 @@ static bool execVarDecl(Toy_Interpreter* interpreter, bool lng) {
Toy_freeLiteral(valIdn); 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)) { if (TOY_IS_ARRAY(val) || TOY_IS_DICTIONARY(val)) {
Toy_parseCompoundToPureValues(interpreter, &val); Toy_parseCompoundToPureValues(interpreter, &val);
} }
@@ -644,6 +694,12 @@ static bool execVarAssign(Toy_Interpreter* interpreter) {
Toy_freeLiteral(rhsIdn); 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)) { if (TOY_IS_ARRAY(rhs) || TOY_IS_DICTIONARY(rhs)) {
Toy_parseCompoundToPureValues(interpreter, &rhs); Toy_parseCompoundToPureValues(interpreter, &rhs);
} }
@@ -713,6 +769,12 @@ static bool execValCast(Toy_Interpreter* interpreter) {
Toy_freeLiteral(valueIdn); Toy_freeLiteral(valueIdn);
} }
if (TOY_IS_IDENTIFIER(value)) {
Toy_freeLiteral(type);
Toy_freeLiteral(value);
return false;
}
Toy_Literal result = TOY_TO_NULL_LITERAL; Toy_Literal result = TOY_TO_NULL_LITERAL;
if (TOY_IS_NULL(value)) { if (TOY_IS_NULL(value)) {
@@ -847,6 +909,12 @@ static bool execCompareEqual(Toy_Interpreter* interpreter, bool invert) {
Toy_freeLiteral(lhsIdn); 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); bool result = Toy_literalsAreEqual(lhs, rhs);
if (invert) { if (invert) {
@@ -875,6 +943,12 @@ static bool execCompareLess(Toy_Interpreter* interpreter, bool invert) {
Toy_freeLiteral(lhsIdn); 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 //not a number, return falure
if (!(TOY_IS_INTEGER(lhs) || TOY_IS_FLOAT(lhs))) { if (!(TOY_IS_INTEGER(lhs) || TOY_IS_FLOAT(lhs))) {
interpreter->errorOutput("Incorrect type in comparison, value \""); interpreter->errorOutput("Incorrect type in comparison, value \"");
@@ -935,6 +1009,12 @@ static bool execCompareLessEqual(Toy_Interpreter* interpreter, bool invert) {
Toy_freeLiteral(lhsIdn); 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 //not a number, return falure
if (!(TOY_IS_INTEGER(lhs) || TOY_IS_FLOAT(lhs))) { if (!(TOY_IS_INTEGER(lhs) || TOY_IS_FLOAT(lhs))) {
interpreter->errorOutput("Incorrect type in comparison, value \""); interpreter->errorOutput("Incorrect type in comparison, value \"");
@@ -996,6 +1076,12 @@ static bool execAnd(Toy_Interpreter* interpreter) {
Toy_freeLiteral(lhsIdn); 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)) { if (TOY_IS_TRUTHY(lhs) && TOY_IS_TRUTHY(rhs)) {
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_BOOLEAN_LITERAL(true)); Toy_pushLiteralArray(&interpreter->stack, TOY_TO_BOOLEAN_LITERAL(true));
} }
@@ -1023,6 +1109,12 @@ static bool execOr(Toy_Interpreter* interpreter) {
Toy_freeLiteral(lhsIdn); 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)) { if (TOY_IS_TRUTHY(lhs) || TOY_IS_TRUTHY(rhs)) {
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_BOOLEAN_LITERAL(true)); Toy_pushLiteralArray(&interpreter->stack, TOY_TO_BOOLEAN_LITERAL(true));
} }
@@ -1066,6 +1158,11 @@ static bool execFalseJump(Toy_Interpreter* interpreter) {
Toy_freeLiteral(litIdn); Toy_freeLiteral(litIdn);
} }
if (TOY_IS_IDENTIFIER(lit)) {
Toy_freeLiteral(lit);
return false;
}
if (TOY_IS_NULL(lit)) { if (TOY_IS_NULL(lit)) {
interpreter->errorOutput("Null detected in comparison\n"); interpreter->errorOutput("Null detected in comparison\n");
Toy_freeLiteral(lit); Toy_freeLiteral(lit);
@@ -1085,6 +1182,8 @@ static bool execFalseJump(Toy_Interpreter* interpreter) {
static void execInterpreter(Toy_Interpreter*); static void execInterpreter(Toy_Interpreter*);
static void readInterpreterSections(Toy_Interpreter* interpreter); static void readInterpreterSections(Toy_Interpreter* interpreter);
//expect stack: identifier, arg1, arg2, arg3..., stackSize
//also supports identifier & arg1 to be other way around (looseFirstArgument)
static bool execFnCall(Toy_Interpreter* interpreter, bool looseFirstArgument) { static bool execFnCall(Toy_Interpreter* interpreter, bool looseFirstArgument) {
//BUGFIX: depth check - don't drown! //BUGFIX: depth check - don't drown!
if (interpreter->depth >= 200) { if (interpreter->depth >= 200) {
@@ -1121,24 +1220,7 @@ static bool execFnCall(Toy_Interpreter* interpreter, bool looseFirstArgument) {
Toy_freeLiteral(lit); Toy_freeLiteral(lit);
} }
//let's screw with the fn name, too //get the function literal
if (looseFirstArgument) {
if (!TOY_IS_IDENTIFIER(identifier)) {
interpreter->errorOutput("Bad literal passed as a function identifier\n");
Toy_freeLiteral(identifier);
Toy_freeLiteral(stackSize);
Toy_freeLiteralArray(&arguments);
return false;
}
int length = TOY_AS_IDENTIFIER(identifier)->length + 1;
char buffer[TOY_MAX_STRING_LENGTH];
snprintf(buffer, TOY_MAX_STRING_LENGTH, "_%s", Toy_toCString(TOY_AS_IDENTIFIER(identifier))); //prepend an underscore
Toy_freeLiteral(identifier);
identifier = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefStringLength(buffer, length));
}
Toy_Literal func = identifier; Toy_Literal func = identifier;
if (!Toy_parseIdentifierToValue(interpreter, &func)) { if (!Toy_parseIdentifierToValue(interpreter, &func)) {
@@ -1148,30 +1230,7 @@ static bool execFnCall(Toy_Interpreter* interpreter, bool looseFirstArgument) {
return false; return false;
} }
//check for side-loaded native functions if (!TOY_IS_FUNCTION(func) && !TOY_IS_FUNCTION_NATIVE(func)) {
if (TOY_IS_FUNCTION_NATIVE(func)) {
//reverse the order to the correct order
Toy_LiteralArray correct;
Toy_initLiteralArray(&correct);
while(arguments.count) {
Toy_Literal lit = Toy_popLiteralArray(&arguments);
Toy_pushLiteralArray(&correct, lit);
Toy_freeLiteral(lit);
}
Toy_freeLiteralArray(&arguments);
//call the native function
TOY_AS_FUNCTION_NATIVE(func)(interpreter, &correct);
Toy_freeLiteralArray(&correct);
Toy_freeLiteral(stackSize);
Toy_freeLiteral(identifier);
return true;
}
if (!TOY_IS_FUNCTION(func)) {
interpreter->errorOutput("Function not found: "); interpreter->errorOutput("Function not found: ");
Toy_printLiteralCustom(identifier, interpreter->errorOutput); Toy_printLiteralCustom(identifier, interpreter->errorOutput);
interpreter->errorOutput("\n"); interpreter->errorOutput("\n");
@@ -1182,7 +1241,18 @@ static bool execFnCall(Toy_Interpreter* interpreter, bool looseFirstArgument) {
return false; return false;
} }
bool ret = Toy_callLiteralFn(interpreter, func, &arguments, &interpreter->stack); //BUGFIX: correct the argument order
Toy_LiteralArray correct;
Toy_initLiteralArray(&correct);
while (arguments.count > 0) {
Toy_Literal lit = Toy_popLiteralArray(&arguments);
Toy_pushLiteralArray(&correct, lit);
Toy_freeLiteral(lit);
}
//call the function literal
bool ret = Toy_callLiteralFn(interpreter, func, &correct, &interpreter->stack);
if (!ret) { if (!ret) {
interpreter->errorOutput("Error encountered in function \""); interpreter->errorOutput("Error encountered in function \"");
@@ -1190,6 +1260,7 @@ static bool execFnCall(Toy_Interpreter* interpreter, bool looseFirstArgument) {
interpreter->errorOutput("\"\n"); interpreter->errorOutput("\"\n");
} }
Toy_freeLiteralArray(&correct);
Toy_freeLiteralArray(&arguments); Toy_freeLiteralArray(&arguments);
Toy_freeLiteral(func); Toy_freeLiteral(func);
Toy_freeLiteral(stackSize); Toy_freeLiteral(stackSize);
@@ -1198,25 +1269,17 @@ static bool execFnCall(Toy_Interpreter* interpreter, bool looseFirstArgument) {
return ret; return ret;
} }
//expects arguments in correct order
bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_LiteralArray* arguments, Toy_LiteralArray* returns) { bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_LiteralArray* arguments, Toy_LiteralArray* returns) {
//check for side-loaded native functions //check for side-loaded native functions
if (TOY_IS_FUNCTION_NATIVE(func)) { if (TOY_IS_FUNCTION_NATIVE(func)) {
//reverse the order to the correct order //TODO: parse out identifier values, see issue #64
Toy_LiteralArray correct;
Toy_initLiteralArray(&correct);
while(arguments->count) {
Toy_Literal lit = Toy_popLiteralArray(arguments);
Toy_pushLiteralArray(&correct, lit);
Toy_freeLiteral(lit);
}
//call the native function //call the native function
int returnsCount = TOY_AS_FUNCTION_NATIVE(func)(interpreter, &correct); int returnsCount = TOY_AS_FUNCTION_NATIVE(func)(interpreter, arguments);
if (returnsCount < 0) { if (returnsCount < 0) {
interpreter->errorOutput("Unknown error from native function\n"); // interpreter->errorOutput("Unknown error from native function\n");
Toy_freeLiteralArray(&correct);
return false; return false;
} }
@@ -1238,13 +1301,12 @@ bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_Liter
} }
Toy_freeLiteralArray(&returnsFromInner); Toy_freeLiteralArray(&returnsFromInner);
Toy_freeLiteralArray(&correct);
return true; return true;
} }
//normal Toy function //normal Toy function
if (!TOY_IS_FUNCTION(func)) { if (!TOY_IS_FUNCTION(func)) {
interpreter->errorOutput("Function required in Toy_callLiteralFn()\n"); interpreter->errorOutput("Function literal required in Toy_callLiteralFn()\n");
return false; return false;
} }
@@ -1292,6 +1354,9 @@ bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_Liter
return false; return false;
} }
//BUGFIX: access the arguments from the beginning
int argumentIndex = 0;
//contents is the indexes of identifier & type //contents is the indexes of identifier & type
for (int i = 0; i < paramArray->count - (TOY_IS_NULL(restParam) ? 0 : 2); i += 2) { //don't count the rest parameter, if present for (int i = 0; i < paramArray->count - (TOY_IS_NULL(restParam) ? 0 : 2); i += 2) { //don't count the rest parameter, if present
//declare and define each entry in the scope //declare and define each entry in the scope
@@ -1307,13 +1372,28 @@ bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_Liter
return false; return false;
} }
Toy_Literal arg = Toy_popLiteralArray(arguments); //access the arguments in order
Toy_Literal arg = TOY_TO_NULL_LITERAL;
if (argumentIndex < arguments->count) {
arg = Toy_copyLiteral(arguments->literals[argumentIndex++]);
}
Toy_Literal argIdn = arg; Toy_Literal argIdn = arg;
if (TOY_IS_IDENTIFIER(arg) && Toy_parseIdentifierToValue(interpreter, &arg)) { if (TOY_IS_IDENTIFIER(arg) && Toy_parseIdentifierToValue(interpreter, &arg)) {
Toy_freeLiteral(argIdn); 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)) { if (!Toy_setScopeVariable(inner.scope, paramArray->literals[i], arg, false)) {
interpreter->errorOutput("[internal] Could not define parameter (bad type?)\n"); interpreter->errorOutput("[internal] Could not define parameter (bad type?)\n");
@@ -1334,8 +1414,9 @@ bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_Liter
Toy_LiteralArray rest; Toy_LiteralArray rest;
Toy_initLiteralArray(&rest); Toy_initLiteralArray(&rest);
while (arguments->count > 0) { //access the arguments in order
Toy_Literal lit = Toy_popLiteralArray(arguments); while (argumentIndex < arguments->count) {
Toy_Literal lit = Toy_copyLiteral(arguments->literals[argumentIndex++]);
Toy_pushLiteralArray(&rest, lit); Toy_pushLiteralArray(&rest, lit);
Toy_freeLiteral(lit); Toy_freeLiteral(lit);
} }
@@ -1442,6 +1523,9 @@ bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_Liter
Toy_freeLiteralArray(&inner.stack); Toy_freeLiteralArray(&inner.stack);
Toy_freeLiteralArray(&inner.literalCache); Toy_freeLiteralArray(&inner.literalCache);
//BUGFIX: this function needs to eat the arguments
Toy_freeLiteralArray(arguments);
//actual bytecode persists until next call //actual bytecode persists until next call
return true; return true;
} }
@@ -1478,6 +1562,12 @@ static bool execFnReturn(Toy_Interpreter* interpreter) {
Toy_freeLiteral(litIdn); 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)) { if (TOY_IS_ARRAY(lit) || TOY_IS_DICTIONARY(lit)) {
Toy_parseCompoundToPureValues(interpreter, &lit); Toy_parseCompoundToPureValues(interpreter, &lit);
} }
@@ -1549,6 +1639,17 @@ static bool execIndex(Toy_Interpreter* interpreter, bool assignIntermediate) {
freeIdn = true; 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)) { if (!TOY_IS_ARRAY(compound) && !TOY_IS_DICTIONARY(compound) && !TOY_IS_STRING(compound)) {
interpreter->errorOutput("Unknown compound found in indexing notation: "); interpreter->errorOutput("Unknown compound found in indexing notation: ");
Toy_printLiteralCustom(compound, interpreter->errorOutput); Toy_printLiteralCustom(compound, interpreter->errorOutput);
@@ -1633,12 +1734,33 @@ static bool execIndexAssign(Toy_Interpreter* interpreter) {
Toy_freeLiteral(assignIdn); 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; Toy_Literal compoundIdn = compound;
bool freeIdn = false; bool freeIdn = false;
if (TOY_IS_IDENTIFIER(compound) && Toy_parseIdentifierToValue(interpreter, &compound)) { if (TOY_IS_IDENTIFIER(compound) && Toy_parseIdentifierToValue(interpreter, &compound)) {
freeIdn = true; 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)) { if (!TOY_IS_ARRAY(compound) && !TOY_IS_DICTIONARY(compound) && !TOY_IS_STRING(compound)) {
interpreter->errorOutput("Unknown compound found in index assigning notation\n"); interpreter->errorOutput("Unknown compound found in index assigning notation\n");
Toy_freeLiteral(assign); Toy_freeLiteral(assign);
@@ -1827,6 +1949,10 @@ static void execInterpreter(Toy_Interpreter* interpreter) {
while(opcode != TOY_OP_EOF && opcode != TOY_OP_SECTION_END && !interpreter->panic) { while(opcode != TOY_OP_EOF && opcode != TOY_OP_SECTION_END && !interpreter->panic) {
switch(opcode) { switch(opcode) {
case TOY_OP_PASS:
//DO NOTHING
break;
case TOY_OP_ASSERT: case TOY_OP_ASSERT:
if (!execAssert(interpreter)) { if (!execAssert(interpreter)) {
return; return;
@@ -2335,7 +2461,6 @@ static void readInterpreterSections(Toy_Interpreter* interpreter) {
//change the type to normal //change the type to normal
interpreter->literalCache.literals[i] = TOY_TO_FUNCTION_LITERAL(bytes, size); interpreter->literalCache.literals[i] = TOY_TO_FUNCTION_LITERAL(bytes, size);
TOY_AS_FUNCTION(interpreter->literalCache.literals[i]).scope = NULL;
} }
} }
@@ -2445,12 +2570,12 @@ void Toy_resetInterpreter(Toy_Interpreter* interpreter) {
interpreter->scope = Toy_pushScope(NULL); interpreter->scope = Toy_pushScope(NULL);
//globally available functions //globally available functions
Toy_injectNativeFn(interpreter, "_set", Toy_private_set); Toy_injectNativeFn(interpreter, "set", Toy_private_set);
Toy_injectNativeFn(interpreter, "_get", Toy_private_get); Toy_injectNativeFn(interpreter, "get", Toy_private_get);
Toy_injectNativeFn(interpreter, "_push", Toy_private_push); Toy_injectNativeFn(interpreter, "push", Toy_private_push);
Toy_injectNativeFn(interpreter, "_pop", Toy_private_pop); Toy_injectNativeFn(interpreter, "pop", Toy_private_pop);
Toy_injectNativeFn(interpreter, "_length", Toy_private_length); Toy_injectNativeFn(interpreter, "length", Toy_private_length);
Toy_injectNativeFn(interpreter, "_clear", Toy_private_clear); Toy_injectNativeFn(interpreter, "clear", Toy_private_clear);
} }
void Toy_freeInterpreter(Toy_Interpreter* interpreter) { void Toy_freeInterpreter(Toy_Interpreter* interpreter) {
-2
View File
@@ -6,8 +6,6 @@
#include "toy_literal_dictionary.h" #include "toy_literal_dictionary.h"
#include "toy_scope.h" #include "toy_scope.h"
typedef void (*Toy_PrintFn)(const char*);
//the interpreter acts depending on the bytecode instructions //the interpreter acts depending on the bytecode instructions
typedef struct Toy_Interpreter { typedef struct Toy_Interpreter {
//input //input
+8 -8
View File
@@ -117,7 +117,7 @@ static Toy_Token makeErrorToken(Toy_Lexer* lexer, char* msg) {
#ifndef TOY_EXPORT #ifndef TOY_EXPORT
if (Toy_commandLine.verbose) { if (Toy_commandLine.verbose) {
printf("err:"); printf("err:");
Toy_printToken(&token); Toy_private_printToken(&token);
} }
#endif #endif
@@ -136,7 +136,7 @@ static Toy_Token makeToken(Toy_Lexer* lexer, Toy_TokenType type) {
//BUG #10: this shows TOKEN_EOF twice due to the overarching structure of the program - can't be fixed //BUG #10: this shows TOKEN_EOF twice due to the overarching structure of the program - can't be fixed
if (Toy_commandLine.verbose) { if (Toy_commandLine.verbose) {
printf("tok:"); printf("tok:");
Toy_printToken(&token); Toy_private_printToken(&token);
} }
#endif #endif
@@ -168,7 +168,7 @@ static Toy_Token makeIntegerOrFloat(Toy_Lexer* lexer) {
} else { } else {
printf("flt:"); printf("flt:");
} }
Toy_printToken(&token); Toy_private_printToken(&token);
} }
#endif #endif
@@ -221,7 +221,7 @@ static Toy_Token makeString(Toy_Lexer* lexer, char terminator) {
#ifndef TOY_EXPORT #ifndef TOY_EXPORT
if (Toy_commandLine.verbose) { if (Toy_commandLine.verbose) {
printf("str:"); printf("str:");
Toy_printToken(&token); Toy_private_printToken(&token);
} }
#endif #endif
@@ -248,7 +248,7 @@ static Toy_Token makeKeywordOrIdentifier(Toy_Lexer* lexer) {
#ifndef TOY_EXPORT #ifndef TOY_EXPORT
if (Toy_commandLine.verbose) { if (Toy_commandLine.verbose) {
printf("kwd:"); printf("kwd:");
Toy_printToken(&token); Toy_private_printToken(&token);
} }
#endif #endif
@@ -267,7 +267,7 @@ static Toy_Token makeKeywordOrIdentifier(Toy_Lexer* lexer) {
#ifndef TOY_EXPORT #ifndef TOY_EXPORT
if (Toy_commandLine.verbose) { if (Toy_commandLine.verbose) {
printf("idf:"); printf("idf:");
Toy_printToken(&token); Toy_private_printToken(&token);
} }
#endif #endif
@@ -281,7 +281,7 @@ void Toy_initLexer(Toy_Lexer* lexer, const char* source) {
lexer->source = source; lexer->source = source;
} }
Toy_Token Toy_scanLexer(Toy_Lexer* lexer) { Toy_Token Toy_private_scanLexer(Toy_Lexer* lexer) {
eatWhitespace(lexer); eatWhitespace(lexer);
lexer->start = lexer->current; lexer->start = lexer->current;
@@ -352,7 +352,7 @@ static void trim(char** s, int* l) { //all this to remove a newline?
} }
//for debugging //for debugging
void Toy_printToken(Toy_Token* token) { void Toy_private_printToken(Toy_Token* token) {
if (token->type == TOY_TOKEN_ERROR) { if (token->type == TOY_TOKEN_ERROR) {
printf(TOY_CC_ERROR "Error\t%d\t%.*s\n" TOY_CC_RESET, token->line, token->length, token->lexeme); printf(TOY_CC_ERROR "Error\t%d\t%.*s\n" TOY_CC_RESET, token->line, token->length, token->lexeme);
return; return;
+2 -2
View File
@@ -21,9 +21,9 @@ typedef struct {
} Toy_Token; } Toy_Token;
TOY_API void Toy_initLexer(Toy_Lexer* lexer, const char* source); TOY_API void Toy_initLexer(Toy_Lexer* lexer, const char* source);
TOY_API Toy_Token Toy_scanLexer(Toy_Lexer* lexer); TOY_API Toy_Token Toy_private_scanLexer(Toy_Lexer* lexer);
//for debugging //for debugging
TOY_API void Toy_printToken(Toy_Token* token); TOY_API void Toy_private_printToken(Toy_Token* token);
TOY_API void Toy_private_setComments(Toy_Lexer* lexer, bool enabled); TOY_API void Toy_private_setComments(Toy_Lexer* lexer, bool enabled);
+11 -9
View File
@@ -8,6 +8,7 @@
#include "toy_console_colors.h" #include "toy_console_colors.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
//hash util functions //hash util functions
static unsigned int hashString(const char* string, int length) { static unsigned int hashString(const char* string, int length) {
@@ -84,11 +85,11 @@ bool Toy_private_isTruthy(Toy_Literal x) {
} }
Toy_Literal Toy_private_toStringLiteral(Toy_RefString* ptr) { Toy_Literal Toy_private_toStringLiteral(Toy_RefString* ptr) {
return ((Toy_Literal){{ .string.ptr = ptr },TOY_LITERAL_STRING, 0}); return ((Toy_Literal){{ .string = { .ptr = ptr }},TOY_LITERAL_STRING, 0});
} }
Toy_Literal Toy_private_toIdentifierLiteral(Toy_RefString* ptr) { Toy_Literal Toy_private_toIdentifierLiteral(Toy_RefString* ptr) {
return ((Toy_Literal){{ .identifier.ptr = ptr, .identifier.hash = hashString(Toy_toCString(ptr), Toy_lengthRefString(ptr)) },TOY_LITERAL_IDENTIFIER, 0}); return ((Toy_Literal){{ .identifier = { .ptr = ptr, .hash = hashString(Toy_toCString(ptr), Toy_lengthRefString(ptr)) }},TOY_LITERAL_IDENTIFIER, 0});
} }
Toy_Literal* Toy_private_typePushSubtype(Toy_Literal* lit, Toy_Literal subtype) { Toy_Literal* Toy_private_typePushSubtype(Toy_Literal* lit, Toy_Literal subtype) {
@@ -155,7 +156,8 @@ Toy_Literal Toy_copyLiteral(Toy_Literal original) {
} }
case TOY_LITERAL_IDENTIFIER: { case TOY_LITERAL_IDENTIFIER: {
return TOY_TO_IDENTIFIER_LITERAL(Toy_copyRefString(TOY_AS_IDENTIFIER(original))); //NOTE: could optimise this by copying the hash manually, but it's a very small increase in performance
return TOY_TO_IDENTIFIER_LITERAL(Toy_copyRefString(TOY_AS_IDENTIFIER(original)));
} }
case TOY_LITERAL_TYPE: { case TOY_LITERAL_TYPE: {
@@ -239,10 +241,10 @@ bool Toy_literalsAreEqual(Toy_Literal lhs, Toy_Literal rhs) {
// ints and floats are compatible // 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) || TOY_IS_FLOAT(lhs)) && (TOY_IS_INTEGER(rhs) || TOY_IS_FLOAT(rhs))) {
if (TOY_IS_INTEGER(lhs)) { if (TOY_IS_INTEGER(lhs)) {
return TOY_AS_INTEGER(lhs) + TOY_AS_FLOAT(rhs); return TOY_AS_INTEGER(lhs) == TOY_AS_FLOAT(rhs);
} }
else { else {
return TOY_AS_FLOAT(lhs) + TOY_AS_INTEGER(rhs); return TOY_AS_FLOAT(lhs) == TOY_AS_INTEGER(rhs);
} }
} }
@@ -404,20 +406,20 @@ int Toy_hashLiteral(Toy_Literal lit) {
case TOY_LITERAL_FUNCTION: case TOY_LITERAL_FUNCTION:
case TOY_LITERAL_FUNCTION_NATIVE: case TOY_LITERAL_FUNCTION_NATIVE:
case TOY_LITERAL_FUNCTION_HOOK: case TOY_LITERAL_FUNCTION_HOOK:
return 0; //can't hash these return -1; //can't hash these
case TOY_LITERAL_IDENTIFIER: case TOY_LITERAL_IDENTIFIER:
return TOY_HASH_I(lit); //pre-computed return TOY_HASH_I(lit); //pre-computed
case TOY_LITERAL_TYPE: case TOY_LITERAL_TYPE:
return TOY_AS_TYPE(lit).typeOf; //nothing else I can do return -1; //not much i can really do
case TOY_LITERAL_OPAQUE: case TOY_LITERAL_OPAQUE:
case TOY_LITERAL_ANY: case TOY_LITERAL_ANY:
return -1; return -1;
default: default:
//should never bee seen //should never be seen
fprintf(stderr, TOY_CC_ERROR "[internal] Unrecognized literal type in hash: %d\n" TOY_CC_RESET, lit.type); fprintf(stderr, TOY_CC_ERROR "[internal] Unrecognized literal type in hash: %d\n" TOY_CC_RESET, lit.type);
return 0; return 0;
} }
@@ -453,7 +455,7 @@ void Toy_printLiteral(Toy_Literal literal) {
Toy_printLiteralCustom(literal, stdoutWrapper); Toy_printLiteralCustom(literal, stdoutWrapper);
} }
void Toy_printLiteralCustom(Toy_Literal literal, void (printFn)(const char*)) { void Toy_printLiteralCustom(Toy_Literal literal, Toy_PrintFn printFn) {
switch(literal.type) { switch(literal.type) {
case TOY_LITERAL_NULL: case TOY_LITERAL_NULL:
printFn("null"); printFn("null");
+10 -9
View File
@@ -8,10 +8,10 @@
struct Toy_Literal; struct Toy_Literal;
struct Toy_Interpreter; struct Toy_Interpreter;
struct Toy_LiteralArray; struct Toy_LiteralArray;
struct Toy_Scope;
typedef int (*Toy_NativeFn)(struct Toy_Interpreter* interpreter, struct Toy_LiteralArray* arguments); 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 int (*Toy_HookFn)(struct Toy_Interpreter* interpreter, struct Toy_Literal identifier, struct Toy_Literal alias);
typedef void (*Toy_PrintFn)(const char*);
#include <string.h>
typedef enum { typedef enum {
TOY_LITERAL_NULL, TOY_LITERAL_NULL,
@@ -58,7 +58,7 @@ typedef struct Toy_Literal {
Toy_NativeFn native; //8 Toy_NativeFn native; //8
Toy_HookFn hook; //8 Toy_HookFn hook; //8
} inner; //8 } inner; //8
void* scope; //8 struct Toy_Scope* scope; //8
} function; //16 } function; //16
struct { //for variable names struct { //for variable names
@@ -118,12 +118,12 @@ typedef struct Toy_Literal {
#define TOY_TO_STRING_LITERAL(value) Toy_private_toStringLiteral(value) #define TOY_TO_STRING_LITERAL(value) Toy_private_toStringLiteral(value)
#define TOY_TO_ARRAY_LITERAL(value) ((Toy_Literal){{ .array = value }, TOY_LITERAL_ARRAY, 0}) #define TOY_TO_ARRAY_LITERAL(value) ((Toy_Literal){{ .array = value }, TOY_LITERAL_ARRAY, 0})
#define TOY_TO_DICTIONARY_LITERAL(value) ((Toy_Literal){{ .dictionary = value }, TOY_LITERAL_DICTIONARY, 0}) #define TOY_TO_DICTIONARY_LITERAL(value) ((Toy_Literal){{ .dictionary = value }, TOY_LITERAL_DICTIONARY, 0})
#define TOY_TO_FUNCTION_LITERAL(value, l) ((Toy_Literal){{ .function.inner.bytecode = value, .function.scope = NULL }, TOY_LITERAL_FUNCTION, l}) #define TOY_TO_FUNCTION_LITERAL(value, l) ((Toy_Literal){{ .function = { .inner = { .bytecode = value }, .scope = NULL }}, TOY_LITERAL_FUNCTION, l})
#define TOY_TO_FUNCTION_NATIVE_LITERAL(value) ((Toy_Literal){{ .function.inner.native = value, .function.scope = NULL }, TOY_LITERAL_FUNCTION_NATIVE, 0}) #define TOY_TO_FUNCTION_NATIVE_LITERAL(value) ((Toy_Literal){{ .function = { .inner = { .native = value }, .scope = NULL }}, TOY_LITERAL_FUNCTION_NATIVE, 0})
#define TOY_TO_FUNCTION_HOOK_LITERAL(value) ((Toy_Literal){{ .function.inner.hook = value, .function.scope = NULL }, TOY_LITERAL_FUNCTION_HOOK, 0}) #define TOY_TO_FUNCTION_HOOK_LITERAL(value) ((Toy_Literal){{ .function = { .inner = { .hook = value }, .scope = NULL }}, TOY_LITERAL_FUNCTION_HOOK, 0})
#define TOY_TO_IDENTIFIER_LITERAL(value) Toy_private_toIdentifierLiteral(value) #define TOY_TO_IDENTIFIER_LITERAL(value) Toy_private_toIdentifierLiteral(value)
#define TOY_TO_TYPE_LITERAL(value, c) ((Toy_Literal){{ .type.typeOf = value, .type.constant = c, .type.subtypes = NULL, .type.capacity = 0, .type.count = 0 }, TOY_LITERAL_TYPE, 0}) #define TOY_TO_TYPE_LITERAL(value, c) ((Toy_Literal){{ .type = { .typeOf = value, .constant = c, .subtypes = NULL, .capacity = 0, .count = 0 }}, TOY_LITERAL_TYPE, 0})
#define TOY_TO_OPAQUE_LITERAL(value, t) ((Toy_Literal){{ .opaque.ptr = value, .opaque.tag = t }, TOY_LITERAL_OPAQUE, 0}) #define TOY_TO_OPAQUE_LITERAL(value, t) ((Toy_Literal){{ .opaque = { .ptr = value, .tag = t }}, TOY_LITERAL_OPAQUE, 0})
//BUGFIX: For blank indexing //BUGFIX: For blank indexing
#define TOY_IS_INDEX_BLANK(value) ((value).type == TOY_LITERAL_INDEX_BLANK) #define TOY_IS_INDEX_BLANK(value) ((value).type == TOY_LITERAL_INDEX_BLANK)
@@ -151,5 +151,6 @@ TOY_API Toy_Literal Toy_copyLiteral(Toy_Literal original);
TOY_API bool Toy_literalsAreEqual(Toy_Literal lhs, Toy_Literal rhs); TOY_API bool Toy_literalsAreEqual(Toy_Literal lhs, Toy_Literal rhs);
TOY_API int Toy_hashLiteral(Toy_Literal lit); TOY_API int Toy_hashLiteral(Toy_Literal lit);
//not thread-safe
TOY_API void Toy_printLiteral(Toy_Literal literal); TOY_API void Toy_printLiteral(Toy_Literal literal);
TOY_API void Toy_printLiteralCustom(Toy_Literal literal, void (printFn)(const char*)); TOY_API void Toy_printLiteralCustom(Toy_Literal literal, Toy_PrintFn);
+2
View File
@@ -18,3 +18,5 @@ TOY_API bool Toy_setLiteralArray(Toy_LiteralArray* array, Toy_Literal index, Toy
TOY_API Toy_Literal Toy_getLiteralArray(Toy_LiteralArray* array, Toy_Literal index); TOY_API Toy_Literal Toy_getLiteralArray(Toy_LiteralArray* array, Toy_Literal index);
int Toy_findLiteralIndex(Toy_LiteralArray* array, Toy_Literal literal); int Toy_findLiteralIndex(Toy_LiteralArray* array, Toy_Literal literal);
//TODO: add a function to get the capacity & count
+25 -21
View File
@@ -7,7 +7,7 @@
#include <stdio.h> #include <stdio.h>
//util functions //util functions
static void setEntryValues(Toy_private_entry* entry, Toy_Literal key, Toy_Literal value) { static void setEntryValues(Toy_private_dictionary_entry* entry, Toy_Literal key, Toy_Literal value) {
//much simpler now //much simpler now
Toy_freeLiteral(entry->key); Toy_freeLiteral(entry->key);
entry->key = Toy_copyLiteral(key); entry->key = Toy_copyLiteral(key);
@@ -16,7 +16,11 @@ static void setEntryValues(Toy_private_entry* entry, Toy_Literal key, Toy_Litera
entry->value = Toy_copyLiteral(value); entry->value = Toy_copyLiteral(value);
} }
static Toy_private_entry* getEntryArray(Toy_private_entry* array, int capacity, Toy_Literal key, unsigned int hash, bool mustExist) { 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 //find "key", starting at index
unsigned int index = hash % capacity; unsigned int index = hash % capacity;
unsigned int start = index; unsigned int start = index;
@@ -26,7 +30,7 @@ static Toy_private_entry* getEntryArray(Toy_private_entry* array, int capacity,
//literal probing and collision checking //literal probing and collision checking
while (index != start) { //WARNING: this is the only function allowed to retrieve an entry from the array while (index != start) { //WARNING: this is the only function allowed to retrieve an entry from the array
Toy_private_entry* entry = &array[index]; Toy_private_dictionary_entry* entry = &array[index];
if (TOY_IS_NULL(entry->key)) { //if key is empty, it's either empty or tombstone if (TOY_IS_NULL(entry->key)) { //if key is empty, it's either empty or tombstone
if (TOY_IS_NULL(entry->value) && !mustExist) { if (TOY_IS_NULL(entry->value) && !mustExist) {
@@ -46,9 +50,9 @@ static Toy_private_entry* getEntryArray(Toy_private_entry* array, int capacity,
return NULL; return NULL;
} }
static void adjustEntryCapacity(Toy_private_entry** dictionaryHandle, int oldCapacity, int capacity) { static void adjustEntryCapacity(Toy_private_dictionary_entry** dictionaryHandle, int oldCapacity, int capacity) {
//new entry space //new entry space
Toy_private_entry* newEntries = TOY_ALLOCATE(Toy_private_entry, capacity); Toy_private_dictionary_entry* newEntries = TOY_ALLOCATE(Toy_private_dictionary_entry, capacity);
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
newEntries[i].key = TOY_TO_NULL_LITERAL; newEntries[i].key = TOY_TO_NULL_LITERAL;
@@ -62,19 +66,19 @@ static void adjustEntryCapacity(Toy_private_entry** dictionaryHandle, int oldCap
} }
//place the key and value in the new array (reusing string memory) //place the key and value in the new array (reusing string memory)
Toy_private_entry* entry = getEntryArray(newEntries, capacity, TOY_TO_NULL_LITERAL, Toy_hashLiteral((*dictionaryHandle)[i].key), false); Toy_private_dictionary_entry* entry = getEntryArray(newEntries, capacity, TOY_TO_NULL_LITERAL, Toy_hashLiteral((*dictionaryHandle)[i].key), false);
entry->key = (*dictionaryHandle)[i].key; entry->key = (*dictionaryHandle)[i].key;
entry->value = (*dictionaryHandle)[i].value; entry->value = (*dictionaryHandle)[i].value;
} }
//clear the old array //clear the old array
TOY_FREE_ARRAY(Toy_private_entry, *dictionaryHandle, oldCapacity); TOY_FREE_ARRAY(Toy_private_dictionary_entry, *dictionaryHandle, oldCapacity);
*dictionaryHandle = newEntries; *dictionaryHandle = newEntries;
} }
static bool setEntryArray(Toy_private_entry** dictionaryHandle, int* capacityPtr, int contains, Toy_Literal key, Toy_Literal value, int hash) { static bool setEntryArray(Toy_private_dictionary_entry** dictionaryHandle, int* capacityPtr, int contains, Toy_Literal key, Toy_Literal value, int hash) {
//expand array if needed //expand array if needed
if (contains + 1 > *capacityPtr * TOY_DICTIONARY_MAX_LOAD) { if (contains + 1 > *capacityPtr * TOY_DICTIONARY_MAX_LOAD) {
int oldCapacity = *capacityPtr; int oldCapacity = *capacityPtr;
@@ -82,7 +86,7 @@ static bool setEntryArray(Toy_private_entry** dictionaryHandle, int* capacityPtr
adjustEntryCapacity(dictionaryHandle, oldCapacity, *capacityPtr); //custom rather than automatic reallocation adjustEntryCapacity(dictionaryHandle, oldCapacity, *capacityPtr); //custom rather than automatic reallocation
} }
Toy_private_entry* entry = getEntryArray(*dictionaryHandle, *capacityPtr, key, hash, false); Toy_private_dictionary_entry* entry = getEntryArray(*dictionaryHandle, *capacityPtr, key, hash, false);
//true = contains increase //true = contains increase
if (TOY_IS_NULL(entry->key)) { if (TOY_IS_NULL(entry->key)) {
@@ -97,14 +101,14 @@ static bool setEntryArray(Toy_private_entry** dictionaryHandle, int* capacityPtr
return false; return false;
} }
static void freeEntry(Toy_private_entry* entry) { static void freeEntry(Toy_private_dictionary_entry* entry) {
Toy_freeLiteral(entry->key); Toy_freeLiteral(entry->key);
Toy_freeLiteral(entry->value); Toy_freeLiteral(entry->value);
entry->key = TOY_TO_NULL_LITERAL; entry->key = TOY_TO_NULL_LITERAL;
entry->value = TOY_TO_NULL_LITERAL; entry->value = TOY_TO_NULL_LITERAL;
} }
static void freeEntryArray(Toy_private_entry* array, int capacity) { static void freeEntryArray(Toy_private_dictionary_entry* array, int capacity) {
if (array == NULL) { if (array == NULL) {
return; return;
} }
@@ -115,17 +119,17 @@ static void freeEntryArray(Toy_private_entry* array, int capacity) {
} }
} }
TOY_FREE_ARRAY(Toy_private_entry, array, capacity); TOY_FREE_ARRAY(Toy_private_dictionary_entry, array, capacity);
} }
//exposed functions //exposed functions
void Toy_initLiteralDictionary(Toy_LiteralDictionary* dictionary) { 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) //HACK: because modulo by 0 is undefined, set the capacity to a non-zero value (and allocate the arrays)
dictionary->entries = NULL; dictionary->entries = NULL;
dictionary->capacity = TOY_GROW_CAPACITY(0); dictionary->capacity = 0;
dictionary->contains = 0; dictionary->contains = 0;
dictionary->count = 0; dictionary->count = 0;
adjustEntryCapacity(&dictionary->entries, 0, dictionary->capacity); dictionary->capacity = 0;
} }
void Toy_freeLiteralDictionary(Toy_LiteralDictionary* dictionary) { void Toy_freeLiteralDictionary(Toy_LiteralDictionary* dictionary) {
@@ -141,7 +145,7 @@ void Toy_setLiteralDictionary(Toy_LiteralDictionary* dictionary, Toy_Literal key
} }
//BUGFIX: Can't hash a function //BUGFIX: Can't hash a function
if (TOY_IS_FUNCTION(key) || TOY_IS_FUNCTION_NATIVE(key)) { if (TOY_IS_FUNCTION(key) || TOY_IS_FUNCTION_NATIVE(key) || TOY_IS_FUNCTION_HOOK(key)) {
fprintf(stderr, TOY_CC_ERROR "Dictionaries can't have function keys (set)\n" TOY_CC_RESET); fprintf(stderr, TOY_CC_ERROR "Dictionaries can't have function keys (set)\n" TOY_CC_RESET);
return; return;
} }
@@ -166,7 +170,7 @@ Toy_Literal Toy_getLiteralDictionary(Toy_LiteralDictionary* dictionary, Toy_Lite
} }
//BUGFIX: Can't hash a function //BUGFIX: Can't hash a function
if (TOY_IS_FUNCTION(key) || TOY_IS_FUNCTION_NATIVE(key)) { if (TOY_IS_FUNCTION(key) || TOY_IS_FUNCTION_NATIVE(key) || TOY_IS_FUNCTION_HOOK(key)) {
fprintf(stderr, TOY_CC_ERROR "Dictionaries can't have function keys (get)\n" TOY_CC_RESET); fprintf(stderr, TOY_CC_ERROR "Dictionaries can't have function keys (get)\n" TOY_CC_RESET);
return TOY_TO_NULL_LITERAL; return TOY_TO_NULL_LITERAL;
} }
@@ -176,7 +180,7 @@ Toy_Literal Toy_getLiteralDictionary(Toy_LiteralDictionary* dictionary, Toy_Lite
return TOY_TO_NULL_LITERAL; return TOY_TO_NULL_LITERAL;
} }
Toy_private_entry* entry = getEntryArray(dictionary->entries, dictionary->capacity, key, Toy_hashLiteral(key), true); Toy_private_dictionary_entry* entry = getEntryArray(dictionary->entries, dictionary->capacity, key, Toy_hashLiteral(key), true);
if (entry != NULL) { if (entry != NULL) {
return Toy_copyLiteral(entry->value); return Toy_copyLiteral(entry->value);
@@ -193,7 +197,7 @@ void Toy_removeLiteralDictionary(Toy_LiteralDictionary* dictionary, Toy_Literal
} }
//BUGFIX: Can't hash a function //BUGFIX: Can't hash a function
if (TOY_IS_FUNCTION(key) || TOY_IS_FUNCTION_NATIVE(key)) { if (TOY_IS_FUNCTION(key) || TOY_IS_FUNCTION_NATIVE(key) || TOY_IS_FUNCTION_HOOK(key)) {
fprintf(stderr, TOY_CC_ERROR "Dictionaries can't have function keys (remove)\n" TOY_CC_RESET); fprintf(stderr, TOY_CC_ERROR "Dictionaries can't have function keys (remove)\n" TOY_CC_RESET);
return; return;
} }
@@ -203,7 +207,7 @@ void Toy_removeLiteralDictionary(Toy_LiteralDictionary* dictionary, Toy_Literal
return; return;
} }
Toy_private_entry* entry = getEntryArray(dictionary->entries, dictionary->capacity, key, Toy_hashLiteral(key), true); Toy_private_dictionary_entry* entry = getEntryArray(dictionary->entries, dictionary->capacity, key, Toy_hashLiteral(key), true);
if (entry != NULL) { if (entry != NULL) {
freeEntry(entry); freeEntry(entry);
@@ -214,6 +218,6 @@ void Toy_removeLiteralDictionary(Toy_LiteralDictionary* dictionary, Toy_Literal
bool Toy_existsLiteralDictionary(Toy_LiteralDictionary* dictionary, Toy_Literal key) { bool Toy_existsLiteralDictionary(Toy_LiteralDictionary* dictionary, Toy_Literal key) {
//null & not tombstoned //null & not tombstoned
Toy_private_entry* entry = getEntryArray(dictionary->entries, dictionary->capacity, key, Toy_hashLiteral(key), false); 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));
} }
+3 -3
View File
@@ -7,13 +7,13 @@
//TODO: benchmark this //TODO: benchmark this
#define TOY_DICTIONARY_MAX_LOAD 0.75 #define TOY_DICTIONARY_MAX_LOAD 0.75
typedef struct Toy_private_entry { typedef struct Toy_private_dictionary_entry {
Toy_Literal key; Toy_Literal key;
Toy_Literal value; Toy_Literal value;
} Toy_private_entry; } Toy_private_dictionary_entry;
typedef struct Toy_LiteralDictionary { typedef struct Toy_LiteralDictionary {
Toy_private_entry* entries; Toy_private_dictionary_entry* entries;
int capacity; int capacity;
int count; int count;
int contains; //count + tombstones, for internal use int contains; //count + tombstones, for internal use
+2 -3
View File
@@ -15,15 +15,14 @@ void* Toy_private_defaultMemoryAllocator(void* pointer, size_t oldSize, size_t n
if (newSize == 0) { if (newSize == 0) {
free(pointer); free(pointer);
return NULL; return NULL;
} }
void* mem = realloc(pointer, newSize); void* mem = realloc(pointer, newSize);
if (mem == NULL) { if (mem == NULL) {
fprintf(stderr, TOY_CC_ERROR "[internal] Memory allocation error (requested %d, replacing %d)\n" TOY_CC_RESET, (int)newSize, (int)oldSize); fprintf(stderr, TOY_CC_ERROR "[internal] Memory allocation error (requested %zu, replacing %zu)\n" TOY_CC_RESET, newSize, oldSize);
exit(-1); return NULL;
} }
return mem; return mem;
+10 -7
View File
@@ -2,13 +2,16 @@
#include "toy_common.h" #include "toy_common.h"
#define TOY_ALLOCATE(type, count) ((type*)Toy_reallocate(NULL, 0, sizeof(type) * (count))) #define TOY_GROW_CAPACITY(capacity) ((capacity) < 8 ? 8 : (capacity) * 2)
#define TOY_FREE(type, pointer) Toy_reallocate(pointer, sizeof(type), 0) #define TOY_GROW_CAPACITY_FAST(capacity) ((capacity) < 32 ? 32 : (capacity) * 2)
#define TOY_GROW_CAPACITY(capacity) ((capacity) < 8 ? 8 : (capacity) * 2)
#define TOY_GROW_CAPACITY_FAST(capacity) ((capacity) < 32 ? 32 : (capacity) * 2) #define TOY_ALLOCATE(type, count) ((type*)Toy_reallocate(NULL, 0, sizeof(type) * (count)))
#define TOY_GROW_ARRAY(type, pointer, oldCount, count) (type*)Toy_reallocate((type*)pointer, sizeof(type) * (oldCount), sizeof(type) * (count))
#define TOY_SHRINK_ARRAY(type, pointer, oldCount, count) (type*)Toy_reallocate((type*)pointer, sizeof(type) * (oldCount), sizeof(type) * (count)) #define TOY_FREE(type, pointer) Toy_reallocate(pointer, sizeof(type), 0)
#define TOY_FREE_ARRAY(type, pointer, oldCount) Toy_reallocate((type*)pointer, sizeof(type) * (oldCount), 0) #define TOY_FREE_ARRAY(type, pointer, oldCount) Toy_reallocate((type*)pointer, sizeof(type) * (oldCount), 0)
#define TOY_GROW_ARRAY(type, pointer, oldCount, count) (type*)Toy_reallocate((type*)pointer, sizeof(type) * (oldCount), sizeof(type) * (count))
#define TOY_SHRINK_ARRAY(type, pointer, oldCount, count) (type*)Toy_reallocate((type*)pointer, sizeof(type) * (oldCount), sizeof(type) * (count))
//implementation details //implementation details
TOY_API void* Toy_reallocate(void* pointer, size_t oldSize, size_t newSize); TOY_API void* Toy_reallocate(void* pointer, size_t oldSize, size_t newSize);
+3
View File
@@ -3,6 +3,9 @@
typedef enum Toy_Opcode { typedef enum Toy_Opcode {
TOY_OP_EOF, TOY_OP_EOF,
//do nothing
TOY_OP_PASS,
//basic statements //basic statements
TOY_OP_ASSERT, TOY_OP_ASSERT,
TOY_OP_PRINT, TOY_OP_PRINT,
+54 -7
View File
@@ -32,7 +32,7 @@ static void error(Toy_Parser* parser, Toy_Token token, const char* message) {
static void advance(Toy_Parser* parser) { static void advance(Toy_Parser* parser) {
parser->previous = parser->current; parser->previous = parser->current;
parser->current = Toy_scanLexer(parser->lexer); parser->current = Toy_private_scanLexer(parser->lexer);
if (parser->current.type == TOY_TOKEN_ERROR) { if (parser->current.type == TOY_TOKEN_ERROR) {
error(parser, parser->current, "Toy_Lexer error"); error(parser, parser->current, "Toy_Lexer error");
@@ -810,13 +810,20 @@ static Toy_Opcode indexAccess(Toy_Parser* parser, Toy_ASTNode** nodeHandle) { //
//eat the first //eat the first
if (!match(parser, TOY_TOKEN_COLON)) { if (!match(parser, TOY_TOKEN_COLON)) {
Toy_freeASTNode(first); Toy_freeASTNode(first);
first = NULL;
parsePrecedence(parser, &first, PREC_TERNARY); parsePrecedence(parser, &first, PREC_TERNARY);
match(parser, TOY_TOKEN_COLON); match(parser, TOY_TOKEN_COLON);
readFirst = true; 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) { if (readFirst) {
Toy_freeASTNode(second); Toy_freeASTNode(second);
second = NULL; second = NULL;
@@ -832,10 +839,18 @@ static Toy_Opcode indexAccess(Toy_Parser* parser, Toy_ASTNode** nodeHandle) { //
//eat the second //eat the second
if (!match(parser, TOY_TOKEN_COLON)) { if (!match(parser, TOY_TOKEN_COLON)) {
Toy_freeASTNode(second); Toy_freeASTNode(second);
second = NULL;
parsePrecedence(parser, &second, PREC_TERNARY); parsePrecedence(parser, &second, PREC_TERNARY);
match(parser, TOY_TOKEN_COLON); 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)) { if (match(parser, TOY_TOKEN_BRACKET_RIGHT)) {
Toy_freeASTNode(third); Toy_freeASTNode(third);
third = NULL; third = NULL;
@@ -845,7 +860,16 @@ static Toy_Opcode indexAccess(Toy_Parser* parser, Toy_ASTNode** nodeHandle) { //
//eat the third //eat the third
Toy_freeASTNode(third); Toy_freeASTNode(third);
third = NULL;
parsePrecedence(parser, &third, PREC_TERNARY); 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); Toy_emitASTNodeIndex(nodeHandle, first, second, third);
consume(parser, TOY_TOKEN_BRACKET_RIGHT, "Expected ']' in index notation"); consume(parser, TOY_TOKEN_BRACKET_RIGHT, "Expected ']' in index notation");
@@ -1350,13 +1374,36 @@ static void forStmt(Toy_Parser* parser, Toy_ASTNode** nodeHandle) {
//read the clauses //read the clauses
consume(parser, TOY_TOKEN_PAREN_LEFT, "Expected '(' at beginning of for clause"); consume(parser, TOY_TOKEN_PAREN_LEFT, "Expected '(' at beginning of for clause");
declaration(parser, &preClause); //allow defining variables in the pre-clause //check the pre-clause
if (parser->current.type != TOY_TOKEN_SEMICOLON) {
declaration(parser, &preClause); //allow defining variables in the pre-clause
}
else {
consume(parser, TOY_TOKEN_SEMICOLON, "Expected ';' after empty declaration of for clause");
Toy_emitASTNodePass(&preClause);
}
parsePrecedence(parser, &condition, PREC_TERNARY); //check the condition clause
consume(parser, TOY_TOKEN_SEMICOLON, "Expected ';' after condition of for clause"); if (parser->current.type != TOY_TOKEN_SEMICOLON) {
parsePrecedence(parser, &condition, PREC_TERNARY);
consume(parser, TOY_TOKEN_SEMICOLON, "Expected ';' after condition of for clause");
}
else {
consume(parser, TOY_TOKEN_SEMICOLON, "Expected ';' after empty condition of for clause");
//empty clause defaults to forever
Toy_Literal f = TOY_TO_BOOLEAN_LITERAL(true);
Toy_emitASTNodeLiteral(&condition, f);
}
parsePrecedence(parser, &postClause, PREC_ASSIGNMENT); //check the postfix clause
consume(parser, TOY_TOKEN_PAREN_RIGHT, "Expected ')' at end of for clause"); if (parser->current.type != TOY_TOKEN_PAREN_RIGHT) {
parsePrecedence(parser, &postClause, PREC_ASSIGNMENT);
consume(parser, TOY_TOKEN_PAREN_RIGHT, "Expected ')' at end of for clause");
}
else {
consume(parser, TOY_TOKEN_PAREN_RIGHT, "Expected ')' after empty increment of for clause");
Toy_emitASTNodePass(&postClause);
}
//read the path //read the path
declaration(parser, &thenPath); declaration(parser, &thenPath);
-2
View File
@@ -1,7 +1,5 @@
#include "toy_refstring.h" #include "toy_refstring.h"
#include <string.h>
//memory allocation //memory allocation
extern void* Toy_private_defaultMemoryAllocator(void* pointer, size_t oldSize, size_t newSize); extern void* Toy_private_defaultMemoryAllocator(void* pointer, size_t oldSize, size_t newSize);
static Toy_RefStringAllocatorFn allocate = Toy_private_defaultMemoryAllocator; static Toy_RefStringAllocatorFn allocate = Toy_private_defaultMemoryAllocator;
+6 -4
View File
@@ -1,13 +1,12 @@
#pragma once #pragma once
#include <stdbool.h>
#include <stddef.h>
#include "toy_common.h" #include "toy_common.h"
#include <string.h>
//memory allocation hook //memory allocation hook
typedef void* (*Toy_RefStringAllocatorFn)(void* pointer, size_t oldSize, size_t newSize); typedef void* (*Toy_RefStringAllocatorFn)(void* pointer, size_t oldSize, size_t newSize);
void Toy_setRefStringAllocatorFn(Toy_RefStringAllocatorFn); TOY_API void Toy_setRefStringAllocatorFn(Toy_RefStringAllocatorFn);
//the RefString structure //the RefString structure
typedef struct Toy_RefString { typedef struct Toy_RefString {
@@ -27,3 +26,6 @@ TOY_API Toy_RefString* Toy_deepCopyRefString(Toy_RefString* refString);
TOY_API const char* Toy_toCString(Toy_RefString* refString); TOY_API const char* Toy_toCString(Toy_RefString* refString);
TOY_API bool Toy_equalsRefString(Toy_RefString* lhs, Toy_RefString* rhs); TOY_API bool Toy_equalsRefString(Toy_RefString* lhs, Toy_RefString* rhs);
TOY_API bool Toy_equalsRefStringCString(Toy_RefString* lhs, char* cstring); TOY_API bool Toy_equalsRefStringCString(Toy_RefString* lhs, char* cstring);
//TODO: merge refstring memory
+11 -3
View File
@@ -126,7 +126,7 @@ static bool checkType(Toy_Literal typeLiteral, Toy_Literal original, Toy_Literal
} }
//find the internal child of original that matches this child of value //find the internal child of original that matches this child of value
Toy_private_entry* ptr = NULL; Toy_private_dictionary_entry* ptr = NULL;
for (int j = 0; j < TOY_AS_DICTIONARY(original)->capacity; j++) { for (int j = 0; j < TOY_AS_DICTIONARY(original)->capacity; j++) {
if (Toy_literalsAreEqual(TOY_AS_DICTIONARY(original)->entries[j].key, TOY_AS_DICTIONARY(value)->entries[i].key)) { if (Toy_literalsAreEqual(TOY_AS_DICTIONARY(original)->entries[j].key, TOY_AS_DICTIONARY(value)->entries[i].key)) {
@@ -159,6 +159,10 @@ static bool checkType(Toy_Literal typeLiteral, Toy_Literal original, Toy_Literal
return false; return false;
} }
if (TOY_AS_TYPE(typeLiteral).typeOf == TOY_LITERAL_OPAQUE && !TOY_IS_OPAQUE(value)) {
return false;
}
return true; return true;
} }
@@ -185,7 +189,7 @@ Toy_Scope* Toy_popScope(Toy_Scope* scope) {
Toy_Scope* ret = scope->ancestor; Toy_Scope* ret = scope->ancestor;
//BUGFIX: when freeing a scope, free the function's scopes manually //BUGFIX: when freeing a scope, free the functions' scopes manually - I *think* this is related to the closure hack-in
for (int i = 0; i < scope->variables.capacity; i++) { for (int i = 0; i < scope->variables.capacity; i++) {
//handle keys, just in case //handle keys, just in case
if (TOY_IS_FUNCTION(scope->variables.entries[i].key)) { if (TOY_IS_FUNCTION(scope->variables.entries[i].key)) {
@@ -205,6 +209,10 @@ Toy_Scope* Toy_popScope(Toy_Scope* scope) {
} }
Toy_Scope* Toy_copyScope(Toy_Scope* original) { Toy_Scope* Toy_copyScope(Toy_Scope* original) {
if (original == NULL) {
return NULL;
}
Toy_Scope* scope = TOY_ALLOCATE(Toy_Scope, 1); Toy_Scope* scope = TOY_ALLOCATE(Toy_Scope, 1);
scope->ancestor = original->ancestor; scope->ancestor = original->ancestor;
Toy_initLiteralDictionary(&scope->variables); Toy_initLiteralDictionary(&scope->variables);
@@ -286,7 +294,7 @@ bool Toy_setScopeVariable(Toy_Scope* scope, Toy_Literal key, Toy_Literal value,
} }
//actually assign //actually assign
Toy_setLiteralDictionary(&scope->variables, key, value); Toy_setLiteralDictionary(&scope->variables, key, value); //key & value are copied here
Toy_freeLiteral(typeLiteral); Toy_freeLiteral(typeLiteral);
Toy_freeLiteral(original); Toy_freeLiteral(original);
+1
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "toy_literal.h"
#include "toy_literal_array.h" #include "toy_literal_array.h"
#include "toy_literal_dictionary.h" #include "toy_literal_dictionary.h"
+17 -17
View File
@@ -2,11 +2,11 @@
var a = [1, 2, 3]; var a = [1, 2, 3];
var b = [4, 5, 6]; var b = [4, 5, 6];
assert _length(a) == _length(b), "a and b lengths are wrong"; assert length(a) == length(b), "a and b lengths are wrong";
var acc = 0; var acc = 0;
for (var i = 0; i < _length(a); i++) { for (var i = 0; i < length(a); i++) {
acc += _get(a, i) * _get(b, i); acc += get(a, i) * get(b, i);
} }
assert acc == 32, "dot product failed"; assert acc == 32, "dot product failed";
@@ -15,38 +15,38 @@ assert acc == 32, "dot product failed";
//assume the args are matrices //assume the args are matrices
fn matrix(first, second) { fn matrix(first, second) {
//get the matrix size //get the matrix size
var l1 = _length(first); //rows var l1 = length(first); //rows
var l2 = _length(_get(first, 0)); //cols var l2 = length(get(first, 0)); //cols
var l3 = _length(second); //rows var l3 = length(second); //rows
var l4 = _length(_get(second, 0)); //cols var l4 = length(get(second, 0)); //cols
//pre-allocate the matrix //pre-allocate the matrix
var row = []; var row = [];
for (var j = 0; j < l4; j++) { for (var j = 0; j < l4; j++) {
_push(row, 0); push(row, 0);
} }
var result = []; var result = [];
for (var i = 0; i < l1; i++) { for (var i = 0; i < l1; i++) {
_push(result, row); push(result, row);
} }
//assign the values //assign the values
for (var i = 0; i < _length(first); i++) { for (var i = 0; i < length(first); i++) {
//select each element of "first" //select each element of "first"
var firstElement = _get(first, i); var firstElement = get(first, i);
//for each element of second //for each element of second
for (var i2 = 0; i2 < _length(second); i2++) { for (var i2 = 0; i2 < length(second); i2++) {
for (var j2 = 0; j2 < _length(_get(second, 0)); j2++) { for (var j2 = 0; j2 < length(get(second, 0)); j2++) {
var val = _get(_get(first, i), i2) * _get(_get(second, i2), j2); var val = get(get(first, i), i2) * get(get(second, i2), j2);
//TODO: needs better notation than this tmpRow variable //TODO: needs better notation than this tmpRow variable
var tmpRow = _get(result, i); var tmpRow = get(result, i);
_set(tmpRow, j2, val); set(tmpRow, j2, val);
_set(result, i, tmpRow); set(result, i, tmpRow);
//result[ i ][ j2 ] += first[i][i2] * second[i2][j2] //result[ i ][ j2 ] += first[i][i2] * second[i2][j2]
} }
+1 -1
View File
@@ -9,7 +9,7 @@ It appears to be a compiler issue, see issue #38 for more info.
*/ */
fn _getValue(self) { fn getValue(self) {
return self; return self;
} }
+3 -3
View File
@@ -1,10 +1,10 @@
//test function chaining with the dot operator //test function chaining with the dot operator
fn _identity(self) { fn identity(self) {
return self; return self;
} }
fn _check(self) { fn check(self) {
assert self == 42, "dot chaining failed"; assert self == 42, "dot chaining failed";
return self; return self;
} }
@@ -20,7 +20,7 @@ val
//test the value is actually altered //test the value is actually altered
fn _increment(self) { fn increment(self) {
return self + 1; return self + 1;
} }
+1 -1
View File
@@ -1,5 +1,5 @@
fn _add(self, inc) { fn add(self, inc) {
return self + inc; return self + inc;
} }
+1 -1
View File
@@ -63,7 +63,7 @@ extra("one", "two", "three", "four", "five", "six", "seven");
//test underscore functions //test underscore functions
fn _example(self, a, b, c) { fn example(self, a, b, c) {
assert a == "a", "underscore failed (a)"; assert a == "a", "underscore failed (a)";
assert b == "b", "underscore failed (b)"; assert b == "b", "underscore failed (b)";
assert c == "c", "underscore failed (c)"; assert c == "c", "underscore failed (c)";
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";
Binary file not shown.
+20
View File
@@ -1,5 +1,18 @@
import standard; 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 //test clock
{ {
//this depends on external factors, so only check the length //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 //test indexOf
{ {
var a = [1, 2, 42, 3]; var a = [1, 2, 42, 3];
@@ -0,0 +1 @@
"a"[--];
+39 -39
View File
@@ -3,41 +3,41 @@
//test arrays without types //test arrays without types
var array = []; var array = [];
assert _length(array) == 0, "_length failed with array"; assert length(array) == 0, "length failed with array";
_push(array, 1); push(array, 1);
_push(array, 2); push(array, 2);
_push(array, 3); push(array, 3);
_push(array, 4); push(array, 4);
_push(array, "foo"); push(array, "foo");
assert _length(array) == 5, "_push failed with array"; assert length(array) == 5, "push failed with array";
assert _pop(array) == "foo", "_pop failed with array"; assert pop(array) == "foo", "pop failed with array";
_set(array, 2, "bar"); set(array, 2, "bar");
assert array == [1, 2, "bar", 4], "_set failed with array"; assert array == [1, 2, "bar", 4], "set failed with array";
assert _get(array, 3) == 4, "_get failed with array"; assert get(array, 3) == 4, "get failed with array";
//test dictionaries without types //test dictionaries without types
var dict = [:]; var dict = [:];
_set(dict, "key", "value"); set(dict, "key", "value");
_set(dict, 1, 2); set(dict, 1, 2);
assert dict == ["key":"value", 1:2], "_set failed with dictionaries"; assert dict == ["key":"value", 1:2], "set failed with dictionaries";
assert _get(dict, "key") == "value", "_get failed with dictionaries"; assert get(dict, "key") == "value", "get failed with dictionaries";
//test _length //test length
assert _length(array) == 4 && _length(dict) == 2, "_length failed with array or dictionaries"; assert length(array) == 4 && length(dict) == 2, "length failed with array or dictionaries";
//test clear //test clear
_clear(array); clear(array);
_clear(dict); clear(dict);
assert _length(array) == 0 && _length(dict) == 0, "_clear failed with array or dictionaries"; assert length(array) == 0 && length(dict) == 0, "clear failed with array or dictionaries";
} }
@@ -45,46 +45,46 @@
//test arrays with types //test arrays with types
var array: [int] = []; var array: [int] = [];
assert _length(array) == 0, "_length failed with array (+ types)"; assert length(array) == 0, "length failed with array (+ types)";
_push(array, 1); push(array, 1);
_push(array, 2); push(array, 2);
_push(array, 3); push(array, 3);
_push(array, 4); push(array, 4);
_push(array, 10); push(array, 10);
assert _length(array) == 5, "_push or failed with array (+ types)"; assert length(array) == 5, "push or failed with array (+ types)";
assert _pop(array) == 10, "_pop failed with array (+ types)"; assert pop(array) == 10, "pop failed with array (+ types)";
_set(array, 2, 70); set(array, 2, 70);
assert array == [1, 2, 70, 4], "_set failed with array (+ types)"; assert array == [1, 2, 70, 4], "set failed with array (+ types)";
assert _get(array, 3) == 4, "_get failed with array (+ types)"; assert get(array, 3) == 4, "get failed with array (+ types)";
//test dictionaries with types //test dictionaries with types
var dict: [string : string] = [:]; var dict: [string : string] = [:];
_set(dict, "key", "value"); set(dict, "key", "value");
assert dict == ["key":"value"], "_set failed with dictionaries (+ types)"; assert dict == ["key":"value"], "set failed with dictionaries (+ types)";
assert _get(dict, "key") == "value", "_get failed with dictionaries (+ types)"; assert get(dict, "key") == "value", "get failed with dictionaries (+ types)";
//test length with types //test length with types
assert _length(array) == 4 && _length(dict) == 1, "_length failed with array or dictionaries (+ types)"; assert length(array) == 4 && length(dict) == 1, "length failed with array or dictionaries (+ types)";
//test clear with types //test clear with types
_clear(array); clear(array);
_clear(dict); clear(dict);
assert _length(array) == 0 && _length(dict) == 0, "_clear failed with array or dictionaries (+ types)"; assert length(array) == 0 && length(dict) == 0, "clear failed with array or dictionaries (+ types)";
} }
{ {
var str = "hello world"; var str = "hello world";
assert _length(str) == 11, "_length failed with string"; assert length(str) == 11, "length failed with string";
} }
+2 -2
View File
@@ -1,5 +1,5 @@
//polyfill the _insert function //polyfill the insert function
fn _insert(self, k, v) { fn insert(self, k, v) {
var tmp1 = v; var tmp1 = v;
var tmp2; var tmp2;
for (var i = k; i < self.length(); i++) { for (var i = k; i < self.length(); i++) {
+1 -1
View File
@@ -1,5 +1,5 @@
//polyfill the remove function //polyfill the remove function
fn _remove(self, k) { fn remove(self, k) {
var result = []; var result = [];
for (var i = 0; i <= k - 1; i++) { for (var i = 0; i <= k - 1; i++) {
+15 -6
View File
@@ -1,12 +1,21 @@
fn fib(n : int) { //memoize the fib function
if (n < 2) { var memo: [int : int] = [:];
return n;
}
return fib(n-1) + fib(n-2); fn fib(n : int) {
if (n < 2) {
return n;
}
var result = memo[n];
if (result == null) {
result = fib(n-1) + fib(n-2);
memo[n] = result;
}
return result;
} }
for (var i = 0; i < 20; i++) { for (var i = 0; i < 40; i++) {
var res = fib(i); var res = fib(i);
print string i + ": " + string res; print string i + ": " + string res;
} }
+26 -26
View File
@@ -20,14 +20,14 @@ static void noPrintFn(const char* output) {
} }
void error(char* msg) { void error(char* msg) {
printf("%s", msg); printf("%s\n", msg);
exit(-1); exit(-1);
} }
int main() { int main() {
{ {
size_t size = 0; size_t size = 0;
const char* source = Toy_readFile("scripts/call-from-host.toy", &size); const char* source = (const char*)Toy_readFile("scripts/call-from-host.toy", &size);
const unsigned char* tb = Toy_compileString(source, &size); const unsigned char* tb = Toy_compileString(source, &size);
free((void*)source); free((void*)source);
@@ -41,7 +41,7 @@ int main() {
//test answer //test answer
{ {
interpreter.printOutput("Testing answer\n"); interpreter.printOutput("Testing answer");
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
@@ -52,15 +52,15 @@ int main() {
//check the results //check the results
if (arguments.count != 0) { if (arguments.count != 0) {
error("Arguments has the wrong number of members\n"); error("Arguments has the wrong number of members");
} }
if (returns.count != 1) { if (returns.count != 1) {
error("Returns has the wrong number of members\n"); error("Returns has the wrong number of members");
} }
if (!TOY_IS_INTEGER(returns.literals[0]) || TOY_AS_INTEGER(returns.literals[0]) != 42) { if (!TOY_IS_INTEGER(returns.literals[0]) || TOY_AS_INTEGER(returns.literals[0]) != 42) {
error("Returned value is incorrect\n"); error("Returned value is incorrect");
} }
Toy_freeLiteralArray(&arguments); Toy_freeLiteralArray(&arguments);
@@ -69,7 +69,7 @@ int main() {
//test identity //test identity
{ {
interpreter.printOutput("Testing identity\n"); interpreter.printOutput("Testing identity");
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
@@ -85,17 +85,17 @@ int main() {
//check the results //check the results
if (arguments.count != 0) { if (arguments.count != 0) {
error("Arguments has the wrong number of members\n"); error("Arguments has the wrong number of members");
} }
if (returns.count != 1) { if (returns.count != 1) {
error("Returns has the wrong number of members\n"); error("Returns has the wrong number of members");
} }
float epsilon = 0.1; //because floats are evil float epsilon = 0.1; //because floats are evil
if (!TOY_IS_FLOAT(returns.literals[0]) || fabs(TOY_AS_FLOAT(returns.literals[0]) - pi) > epsilon) { if (!TOY_IS_FLOAT(returns.literals[0]) || fabs(TOY_AS_FLOAT(returns.literals[0]) - pi) > epsilon) {
error("Returned value is incorrect\n"); error("Returned value is incorrect");
} }
Toy_freeLiteralArray(&arguments); Toy_freeLiteralArray(&arguments);
@@ -104,7 +104,7 @@ int main() {
//test makeCounter (closures) //test makeCounter (closures)
{ {
interpreter.printOutput("Testing makeCounter (closures)\n"); interpreter.printOutput("Testing makeCounter (closures)");
Toy_LiteralArray arguments; Toy_LiteralArray arguments;
Toy_initLiteralArray(&arguments); Toy_initLiteralArray(&arguments);
@@ -115,11 +115,11 @@ int main() {
//check the results //check the results
if (arguments.count != 0) { if (arguments.count != 0) {
error("Arguments has the wrong number of members\n"); error("Arguments has the wrong number of members");
} }
if (returns.count != 1) { if (returns.count != 1) {
error("Returns has the wrong number of members\n"); error("Returns has the wrong number of members");
} }
//grab the resulting literal //grab the resulting literal
@@ -139,15 +139,15 @@ int main() {
//check the results //check the results
if (arguments.count != 0) { if (arguments.count != 0) {
error("Arguments (1) has the wrong number of members\n"); error("Arguments (1) has the wrong number of members");
} }
if (returns.count != 1) { if (returns.count != 1) {
error("Returns (1) has the wrong number of members\n"); error("Returns (1) has the wrong number of members");
} }
if (!TOY_IS_INTEGER(returns.literals[0]) || TOY_AS_INTEGER(returns.literals[0]) != 1) { if (!TOY_IS_INTEGER(returns.literals[0]) || TOY_AS_INTEGER(returns.literals[0]) != 1) {
error("Returned value (1) is incorrect\n"); error("Returned value (1) is incorrect");
} }
Toy_freeLiteralArray(&arguments); Toy_freeLiteralArray(&arguments);
@@ -164,15 +164,15 @@ int main() {
//check the results //check the results
if (arguments.count != 0) { if (arguments.count != 0) {
error("Arguments (2) has the wrong number of members\n"); error("Arguments (2) has the wrong number of members");
} }
if (returns.count != 1) { if (returns.count != 1) {
error("Returns (2) has the wrong number of members\n"); error("Returns (2) has the wrong number of members");
} }
if (!TOY_IS_INTEGER(returns.literals[0]) || TOY_AS_INTEGER(returns.literals[0]) != 2) { if (!TOY_IS_INTEGER(returns.literals[0]) || TOY_AS_INTEGER(returns.literals[0]) != 2) {
error("Returned value (2) is incorrect\n"); error("Returned value (2) is incorrect");
} }
Toy_freeLiteralArray(&arguments); Toy_freeLiteralArray(&arguments);
@@ -189,15 +189,15 @@ int main() {
//check the results //check the results
if (arguments.count != 0) { if (arguments.count != 0) {
error("Arguments (3) has the wrong number of members\n"); error("Arguments (3) has the wrong number of members");
} }
if (returns.count != 1) { if (returns.count != 1) {
error("Returns (3) has the wrong number of members\n"); error("Returns (3) has the wrong number of members");
} }
if (!TOY_IS_INTEGER(returns.literals[0]) || TOY_AS_INTEGER(returns.literals[0]) != 3) { if (!TOY_IS_INTEGER(returns.literals[0]) || TOY_AS_INTEGER(returns.literals[0]) != 3) {
error("Returned value (3) is incorrect\n"); error("Returned value (3) is incorrect");
} }
Toy_freeLiteralArray(&arguments); Toy_freeLiteralArray(&arguments);
@@ -209,7 +209,7 @@ int main() {
//test assertion failure //test assertion failure
{ {
interpreter.printOutput("Testing assertion failure\n"); interpreter.printOutput("Testing assertion failure");
Toy_setInterpreterAssert(&interpreter, noPrintFn); Toy_setInterpreterAssert(&interpreter, noPrintFn);
@@ -222,15 +222,15 @@ int main() {
//check the results //check the results
if (arguments.count != 0) { if (arguments.count != 0) {
error("Arguments has the wrong number of members\n"); error("Arguments has the wrong number of members");
} }
if (returns.count != 1 || !TOY_IS_NULL(returns.literals[0])) { if (returns.count != 1 || !TOY_IS_NULL(returns.literals[0])) {
error("Returns has the wrong number of members\n"); error("Returns has the wrong number of members");
} }
if (!ret) { if (!ret) {
error("Assertion gives the wrong return value\n"); error("Assertion gives the wrong return value");
} }
Toy_freeLiteralArray(&arguments); Toy_freeLiteralArray(&arguments);
+3 -3
View File
@@ -39,7 +39,7 @@ int main() {
Toy_writeCompiler(&compiler, node); Toy_writeCompiler(&compiler, node);
//collate //collate
int size = 0; size_t size = 0;
unsigned char* bytecode = Toy_collateCompiler(&compiler, &size); unsigned char* bytecode = Toy_collateCompiler(&compiler, &size);
//cleanup //cleanup
@@ -52,7 +52,7 @@ int main() {
{ {
//source //source
size_t sourceLength = 0; size_t sourceLength = 0;
const char* source = Toy_readFile("scripts/compiler_sample_code.toy", &sourceLength); const char* source = (const char*)Toy_readFile("scripts/compiler_sample_code.toy", &sourceLength);
//test basic compilation & collation //test basic compilation & collation
Toy_Lexer lexer; Toy_Lexer lexer;
@@ -78,7 +78,7 @@ int main() {
} }
//collate //collate
int size = 0; size_t size = 0;
unsigned char* bytecode = Toy_collateCompiler(&compiler, &size); unsigned char* bytecode = Toy_collateCompiler(&compiler, &size);
//cleanup //cleanup
+2 -2
View File
@@ -53,7 +53,7 @@ void runSourceCustom(const char* source) {
void runSourceFileCustom(const char* fname) { void runSourceFileCustom(const char* fname) {
size_t size = 0; //not used size_t size = 0; //not used
const char* source = Toy_readFile(fname, &size); const char* source = (const char*)Toy_readFile(fname, &size);
runSourceCustom(source); runSourceCustom(source);
free((void*)source); free((void*)source);
} }
@@ -87,7 +87,7 @@ int main() {
Toy_writeCompiler(&compiler, node); Toy_writeCompiler(&compiler, node);
//collate //collate
int size = 0; size_t size = 0;
const unsigned char* bytecode = Toy_collateCompiler(&compiler, &size); const unsigned char* bytecode = Toy_collateCompiler(&compiler, &size);
//NOTE: suppress print output for testing //NOTE: suppress print output for testing
+4 -4
View File
@@ -15,10 +15,10 @@ int main() {
Toy_initLexer(&lexer, source); Toy_initLexer(&lexer, source);
//get each token //get each token
Toy_Token print = Toy_scanLexer(&lexer); Toy_Token print = Toy_private_scanLexer(&lexer);
Toy_Token null = Toy_scanLexer(&lexer); Toy_Token null = Toy_private_scanLexer(&lexer);
Toy_Token semi = Toy_scanLexer(&lexer); Toy_Token semi = Toy_private_scanLexer(&lexer);
Toy_Token eof = Toy_scanLexer(&lexer); Toy_Token eof = Toy_private_scanLexer(&lexer);
//test each token is correct //test each token is correct
if (strncmp(print.lexeme, "print", print.length)) { if (strncmp(print.lexeme, "print", print.length)) {
+6 -54
View File
@@ -14,6 +14,7 @@
#include "../repl/repl_tools.h" #include "../repl/repl_tools.h"
#include "../repl/lib_about.h" #include "../repl/lib_about.h"
#include "../repl/lib_random.h"
#include "../repl/lib_runner.h" #include "../repl/lib_runner.h"
#include "../repl/lib_standard.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); Toy_setInterpreterError(&interpreter, errorWrapper);
//inject the standard libraries into this interpreter //inject the standard libraries into this interpreter
if (hook != Toy_hookStandard) {
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
}
Toy_injectNativeHook(&interpreter, library, hook); Toy_injectNativeHook(&interpreter, library, hook);
Toy_runInterpreter(&interpreter, tb, size); Toy_runInterpreter(&interpreter, tb, size);
Toy_freeInterpreter(&interpreter); 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 { typedef struct Payload {
char* fname; char* fname;
char* libname; char* libname;
@@ -94,6 +80,7 @@ int main() {
{"about.toy", "about", Toy_hookAbout}, {"about.toy", "about", Toy_hookAbout},
{"standard.toy", "standard", Toy_hookStandard}, {"standard.toy", "standard", Toy_hookStandard},
{"runner.toy", "runner", Toy_hookRunner}, {"runner.toy", "runner", Toy_hookRunner},
{"random.toy", "random", Toy_hookRandom},
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };
@@ -105,7 +92,7 @@ int main() {
//compile the source //compile the source
size_t size = 0; size_t size = 0;
const char* source = Toy_readFile(fname, &size); const char* source = (const char*)Toy_readFile(fname, &size);
if (!source) { if (!source) {
printf(TOY_CC_ERROR "Failed to load file: %s\n" TOY_CC_RESET, fname); printf(TOY_CC_ERROR "Failed to load file: %s\n" TOY_CC_RESET, fname);
failedAsserts++; failedAsserts++;
@@ -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 = 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 //lib cleanup
Toy_freeDriveDictionary(); Toy_freeDriveDictionary();
+3 -2
View File
@@ -50,7 +50,7 @@ const unsigned char* compileStringCustom(const char* source, size_t* size) {
} }
//get the bytecode dump //get the bytecode dump
const unsigned char* tb = Toy_collateCompiler(&compiler, (int*)(size)); const unsigned char* tb = Toy_collateCompiler(&compiler, size);
//cleanup //cleanup
Toy_freeCompiler(&compiler); Toy_freeCompiler(&compiler);
@@ -84,7 +84,7 @@ void runSourceCustom(const char* source) {
void runSourceFileCustom(const char* fname) { void runSourceFileCustom(const char* fname) {
size_t size = 0; //not used size_t size = 0; //not used
const char* source = Toy_readFile(fname, &size); const char* source = (const char*)Toy_readFile(fname, &size);
runSourceCustom(source); runSourceCustom(source);
free((void*)source); free((void*)source);
} }
@@ -101,6 +101,7 @@ int main() {
"declare-types-array.toy", "declare-types-array.toy",
"declare-types-dictionary-key.toy", "declare-types-dictionary-key.toy",
"declare-types-dictionary-value.toy", "declare-types-dictionary-value.toy",
"index-access-bugfix.toy",
"index-arrays-non-integer.toy", "index-arrays-non-integer.toy",
"string-concat.toy", "string-concat.toy",
"unary-inverted-nothing.toy", "unary-inverted-nothing.toy",
+1 -1
View File
@@ -68,7 +68,7 @@ static int consume(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
int main() { int main() {
{ {
size_t size = 0; size_t size = 0;
const char* source = Toy_readFile("scripts/opaque-data-type.toy", &size); const char* source = (const char*)Toy_readFile("scripts/opaque-data-type.toy", &size);
const unsigned char* tb = Toy_compileString(source, &size); const unsigned char* tb = Toy_compileString(source, &size);
free((void*)source); free((void*)source);
+1 -1
View File
@@ -58,7 +58,7 @@ int main() {
{ {
//get the source file //get the source file
size_t size = 0; size_t size = 0;
const char* source = Toy_readFile("scripts/parser_sample_code.toy", &size); const char* source = (const char*)Toy_readFile("scripts/parser_sample_code.toy", &size);
//test parsing a chunk of junk (valgrind will find leaks) //test parsing a chunk of junk (valgrind will find leaks)
Toy_Lexer lexer; Toy_Lexer lexer;
+4 -1
View File
@@ -39,11 +39,14 @@ static void* trackerAllocator(void* pointer, size_t oldSize, size_t newSize) {
return mem; return mem;
} }
int main(int argc, char* argv[]) { int main(int argc, const char* argv[]) {
if (argc <= 1) { if (argc <= 1) {
return -1; return -1;
} }
//not used, except for print
Toy_initCommandLine(argc, argv);
//setup for runner //setup for runner
Toy_initDriveDictionary(); Toy_initDriveDictionary();