Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7690dce3f6 | |||
| 1ed1993489 | |||
| 9b5327b83d | |||
| 10dbe8f8f1 | |||
| 9e4ad7a9a5 | |||
| 35bfa1b9f1 | |||
| 7f692b4cb4 | |||
| 0cef0abdb5 | |||
| 6ba42b5a9b | |||
| 3cb62274c9 | |||
| 60b561d809 | |||
| 70b2dcd829 | |||
| 0955b3ff38 | |||
| 4137935468 | |||
| ebeabcb9d4 | |||
| 4d33a9473a | |||
| 61e3cdba82 | |||
| 3b7d2be87e | |||
| fa175203c9 | |||
| b4a3e9b42b | |||
| 6347778ead |
+23
-21
@@ -71,12 +71,12 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||||
<OutDir>$(SolutionDir)out\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)out\</OutDir>
|
||||||
<IntDir>$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>$(SolutionDir)out\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)out\</OutDir>
|
||||||
<IntDir>$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -110,7 +110,7 @@
|
|||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>Toy.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Toy.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)out\$(Configuration)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)out</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)/source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)/source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
@@ -125,30 +125,32 @@
|
|||||||
<AdditionalIncludeDirectories>$(SolutionDir)/source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)/source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)out\$(Configuration)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)out</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Toy.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Toy.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="repl\lib_about.c" />
|
|
||||||
<ClCompile Include="repl\lib_random.c" />
|
|
||||||
<ClCompile Include="repl\lib_runner.c" />
|
|
||||||
<ClCompile Include="repl\lib_standard.c" />
|
|
||||||
<ClCompile Include="repl\repl_main.c" />
|
|
||||||
<ClCompile Include="repl\repl_tools.c" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="repl\lib_about.h" />
|
|
||||||
<ClInclude Include="repl\lib_random.h" />
|
|
||||||
<ClInclude Include="repl\lib_runner.h" />
|
|
||||||
<ClInclude Include="repl\lib_standard.h" />
|
|
||||||
<ClInclude Include="repl\repl_tools.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="Toy.vcxproj">
|
<ProjectReference Include="Toy.vcxproj">
|
||||||
<Project>{26360002-cc2a-469a-9b28-ba0c1af41657}</Project>
|
<Project>{26360002-cc2a-469a-9b28-ba0c1af41657}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="repl\drive_system.c" />
|
||||||
|
<ClCompile Include="repl\lib_random.c" />
|
||||||
|
<ClCompile Include="repl\lib_runner.c" />
|
||||||
|
<ClCompile Include="repl\lib_standard.c" />
|
||||||
|
<ClCompile Include="repl\lib_toy_version_info.c" />
|
||||||
|
<ClCompile Include="repl\repl_main.c" />
|
||||||
|
<ClCompile Include="repl\repl_tools.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="repl\drive_system.h" />
|
||||||
|
<ClInclude Include="repl\lib_random.h" />
|
||||||
|
<ClInclude Include="repl\lib_runner.h" />
|
||||||
|
<ClInclude Include="repl\lib_standard.h" />
|
||||||
|
<ClInclude Include="repl\lib_toy_version_info.h" />
|
||||||
|
<ClInclude Include="repl\repl_tools.h" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
|||||||
+6
-10
@@ -71,12 +71,12 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<OutDir>$(SolutionDir)out\</OutDir>
|
<OutDir>$(SolutionDir)out\</OutDir>
|
||||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>$(SolutionDir)out\</OutDir>
|
<OutDir>$(SolutionDir)out\</OutDir>
|
||||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
@@ -114,9 +114,8 @@
|
|||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>del "$(OutDir)$(ProjectName).exp"
|
<Command>
|
||||||
del "$(OutDir)$(ProjectName).pdb"
|
</Command>
|
||||||
</Command>
|
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
<Link>
|
<Link>
|
||||||
<OutputFile>$(Outdir)$(TargetName)$(TargetExt)</OutputFile>
|
<OutputFile>$(Outdir)$(TargetName)$(TargetExt)</OutputFile>
|
||||||
@@ -131,9 +130,8 @@ del "$(OutDir)$(ProjectName).pdb"
|
|||||||
<PreprocessorDefinitions>TOY_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>TOY_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>del "$(OutDir)$(ProjectName).exp"
|
<Command>
|
||||||
del "$(OutDir)$(ProjectName).pdb"
|
</Command>
|
||||||
</Command>
|
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
<Link>
|
<Link>
|
||||||
<OutputFile>$(Outdir)$(TargetName)$(TargetExt)</OutputFile>
|
<OutputFile>$(Outdir)$(TargetName)$(TargetExt)</OutputFile>
|
||||||
@@ -147,7 +145,6 @@ del "$(OutDir)$(ProjectName).pdb"
|
|||||||
<ClCompile Include="source\toy_builtin.c" />
|
<ClCompile Include="source\toy_builtin.c" />
|
||||||
<ClCompile Include="source\toy_common.c" />
|
<ClCompile Include="source\toy_common.c" />
|
||||||
<ClCompile Include="source\toy_compiler.c" />
|
<ClCompile Include="source\toy_compiler.c" />
|
||||||
<ClCompile Include="source\toy_drive_system.c" />
|
|
||||||
<ClCompile Include="source\toy_interpreter.c" />
|
<ClCompile Include="source\toy_interpreter.c" />
|
||||||
<ClCompile Include="source\toy_keyword_types.c" />
|
<ClCompile Include="source\toy_keyword_types.c" />
|
||||||
<ClCompile Include="source\toy_lexer.c" />
|
<ClCompile Include="source\toy_lexer.c" />
|
||||||
@@ -167,7 +164,6 @@ del "$(OutDir)$(ProjectName).pdb"
|
|||||||
<ClInclude Include="source\toy_common.h" />
|
<ClInclude Include="source\toy_common.h" />
|
||||||
<ClInclude Include="source\toy_compiler.h" />
|
<ClInclude Include="source\toy_compiler.h" />
|
||||||
<ClInclude Include="source\toy_console_colors.h" />
|
<ClInclude Include="source\toy_console_colors.h" />
|
||||||
<ClInclude Include="source\toy_drive_system.h" />
|
|
||||||
<ClInclude Include="source\toy_interpreter.h" />
|
<ClInclude Include="source\toy_interpreter.h" />
|
||||||
<ClInclude Include="source\toy_keyword_types.h" />
|
<ClInclude Include="source\toy_keyword_types.h" />
|
||||||
<ClInclude Include="source\toy_lexer.h" />
|
<ClInclude Include="source\toy_lexer.h" />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "toy_drive_system.h"
|
#include "drive_system.h"
|
||||||
|
|
||||||
#include "toy_memory.h"
|
#include "toy_memory.h"
|
||||||
#include "toy_literal_dictionary.h"
|
#include "toy_literal_dictionary.h"
|
||||||
@@ -18,7 +18,7 @@ void Toy_freeDriveSystem() {
|
|||||||
Toy_freeLiteralDictionary(&driveDictionary);
|
Toy_freeLiteralDictionary(&driveDictionary);
|
||||||
}
|
}
|
||||||
|
|
||||||
TOY_API void Toy_setDrivePath(char* drive, char* path) {
|
void Toy_setDrivePath(char* drive, char* path) {
|
||||||
Toy_Literal driveLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(drive));
|
Toy_Literal driveLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(drive));
|
||||||
Toy_Literal pathLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(path));
|
Toy_Literal pathLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(path));
|
||||||
|
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
# toy_drive_system.h
|
# drive_system.h
|
||||||
|
|
||||||
When accessing the file system through toy (such as with the runner library), it's best practice to utilize Toy's built-in drive system - this system (tries to) prevent malicious accessing of files outside of the designated folders. It does this by causing an error when a script tries to access a parent directory.
|
When accessing the file system through Toy (such as with the runner library), it's best practice to utilize the drive system - this system (tries to) prevent malicious accessing of files outside of the designated folders. It does this by causing an error when a script tries to access a parent directory.
|
||||||
|
|
||||||
To use the drive system, first you must designate specific folders which can be accessed, like so:
|
To use the drive system, first you must designate specific folders which can be accessed, like so:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#include "toy_drive_system.h"
|
#include "drive_system.h"
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
//the drive system uses a LiteralDictionary, which must be initialized with this
|
//the drive system uses a LiteralDictionary, which must be initialized with this
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "toy_interpreter.h"
|
|
||||||
|
|
||||||
int Toy_hookAbout(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
|
|
||||||
+1
-1
@@ -1,10 +1,10 @@
|
|||||||
#include "lib_runner.h"
|
#include "lib_runner.h"
|
||||||
|
|
||||||
#include "toy_memory.h"
|
#include "toy_memory.h"
|
||||||
#include "toy_drive_system.h"
|
|
||||||
#include "toy_interpreter.h"
|
#include "toy_interpreter.h"
|
||||||
|
|
||||||
#include "repl_tools.h"
|
#include "repl_tools.h"
|
||||||
|
#include "drive_system.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|||||||
+261
-110
@@ -47,11 +47,6 @@ static int nativeHash(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
Toy_freeLiteral(selfLiteralIdn);
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_IDENTIFIER(selfLiteral)) {
|
|
||||||
Toy_freeLiteral(selfLiteral);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toy_Literal result = TOY_TO_INTEGER_LITERAL(Toy_hashLiteral(selfLiteral));
|
Toy_Literal result = TOY_TO_INTEGER_LITERAL(Toy_hashLiteral(selfLiteral));
|
||||||
|
|
||||||
Toy_pushLiteralArray(&interpreter->stack, result);
|
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||||
@@ -77,11 +72,6 @@ static int nativeAbs(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
Toy_freeLiteral(selfLiteralIdn);
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_IDENTIFIER(selfLiteral)) {
|
|
||||||
Toy_freeLiteral(selfLiteral);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to abs\n");
|
interpreter->errorOutput("Incorrect argument type passed to abs\n");
|
||||||
Toy_freeLiteral(selfLiteral);
|
Toy_freeLiteral(selfLiteral);
|
||||||
@@ -120,11 +110,6 @@ static int nativeCeil(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
Toy_freeLiteral(selfLiteralIdn);
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_IDENTIFIER(selfLiteral)) {
|
|
||||||
Toy_freeLiteral(selfLiteral);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to ceil\n");
|
interpreter->errorOutput("Incorrect argument type passed to ceil\n");
|
||||||
Toy_freeLiteral(selfLiteral);
|
Toy_freeLiteral(selfLiteral);
|
||||||
@@ -164,11 +149,6 @@ static int nativeFloor(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
|
|||||||
Toy_freeLiteral(selfLiteralIdn);
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_IDENTIFIER(selfLiteral)) {
|
|
||||||
Toy_freeLiteral(selfLiteral);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to floor\n");
|
interpreter->errorOutput("Incorrect argument type passed to floor\n");
|
||||||
Toy_freeLiteral(selfLiteral);
|
Toy_freeLiteral(selfLiteral);
|
||||||
@@ -208,11 +188,6 @@ static int nativeMax(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
Toy_freeLiteral(selfLiteralIdn);
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_IDENTIFIER(selfLiteral)) {
|
|
||||||
Toy_freeLiteral(selfLiteral);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to max\n");
|
interpreter->errorOutput("Incorrect argument type passed to max\n");
|
||||||
Toy_freeLiteral(selfLiteral);
|
Toy_freeLiteral(selfLiteral);
|
||||||
@@ -227,11 +202,11 @@ static int nativeMax(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
|
|
||||||
//cooerce if needed
|
//cooerce if needed
|
||||||
if (TOY_IS_INTEGER(resultLiteral) && TOY_IS_FLOAT(selfLiteral)) {
|
if (TOY_IS_INTEGER(resultLiteral) && TOY_IS_FLOAT(selfLiteral)) {
|
||||||
resultLiteral = TOY_TO_FLOAT_LITERAL( TOY_AS_INTEGER(resultLiteral) );
|
resultLiteral = TOY_TO_FLOAT_LITERAL( (float)TOY_AS_INTEGER(resultLiteral) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_FLOAT(resultLiteral) && TOY_IS_INTEGER(selfLiteral)) {
|
if (TOY_IS_FLOAT(resultLiteral) && TOY_IS_INTEGER(selfLiteral)) {
|
||||||
selfLiteral = TOY_TO_FLOAT_LITERAL( TOY_AS_INTEGER(selfLiteral) );
|
selfLiteral = TOY_TO_FLOAT_LITERAL( (float)TOY_AS_INTEGER(selfLiteral) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//compare
|
//compare
|
||||||
@@ -269,11 +244,6 @@ static int nativeMin(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
Toy_freeLiteral(selfLiteralIdn);
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_IDENTIFIER(selfLiteral)) {
|
|
||||||
Toy_freeLiteral(selfLiteral);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to min\n");
|
interpreter->errorOutput("Incorrect argument type passed to min\n");
|
||||||
Toy_freeLiteral(selfLiteral);
|
Toy_freeLiteral(selfLiteral);
|
||||||
@@ -288,11 +258,11 @@ static int nativeMin(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
|
|
||||||
//cooerce if needed
|
//cooerce if needed
|
||||||
if (TOY_IS_INTEGER(resultLiteral) && TOY_IS_FLOAT(selfLiteral)) {
|
if (TOY_IS_INTEGER(resultLiteral) && TOY_IS_FLOAT(selfLiteral)) {
|
||||||
resultLiteral = TOY_TO_FLOAT_LITERAL( TOY_AS_INTEGER(resultLiteral) );
|
resultLiteral = TOY_TO_FLOAT_LITERAL( (float)TOY_AS_INTEGER(resultLiteral) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_FLOAT(resultLiteral) && TOY_IS_INTEGER(selfLiteral)) {
|
if (TOY_IS_FLOAT(resultLiteral) && TOY_IS_INTEGER(selfLiteral)) {
|
||||||
selfLiteral = TOY_TO_FLOAT_LITERAL( TOY_AS_INTEGER(selfLiteral) );
|
selfLiteral = TOY_TO_FLOAT_LITERAL( (float)TOY_AS_INTEGER(selfLiteral) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//compare
|
//compare
|
||||||
@@ -330,11 +300,6 @@ static int nativeRound(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
|
|||||||
Toy_freeLiteral(selfLiteralIdn);
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_IDENTIFIER(selfLiteral)) {
|
|
||||||
Toy_freeLiteral(selfLiteral);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to round\n");
|
interpreter->errorOutput("Incorrect argument type passed to round\n");
|
||||||
Toy_freeLiteral(selfLiteral);
|
Toy_freeLiteral(selfLiteral);
|
||||||
@@ -365,6 +330,259 @@ static int nativeRound(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nativeSign(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to sign\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_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to sign\n");
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_NULL_LITERAL;
|
||||||
|
|
||||||
|
if (TOY_IS_INTEGER(selfLiteral)) {
|
||||||
|
if (TOY_AS_INTEGER(selfLiteral) < 0) {
|
||||||
|
resultLiteral = TOY_TO_INTEGER_LITERAL(-1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resultLiteral = TOY_TO_INTEGER_LITERAL(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (TOY_IS_FLOAT(selfLiteral)) {
|
||||||
|
if (TOY_AS_FLOAT(selfLiteral) < 0) {
|
||||||
|
resultLiteral = TOY_TO_INTEGER_LITERAL(-1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resultLiteral = TOY_TO_INTEGER_LITERAL(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeNormalize(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//NOTE: this is identical to `sign`, except it returns 0 when the argument is 0.
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to normalize\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_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to normalize\n");
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_NULL_LITERAL;
|
||||||
|
|
||||||
|
if (TOY_IS_INTEGER(selfLiteral)) {
|
||||||
|
if (TOY_AS_INTEGER(selfLiteral) < 0) {
|
||||||
|
resultLiteral = TOY_TO_INTEGER_LITERAL(-1);
|
||||||
|
}
|
||||||
|
else if (TOY_AS_INTEGER(selfLiteral) > 0) {
|
||||||
|
resultLiteral = TOY_TO_INTEGER_LITERAL(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resultLiteral = TOY_TO_INTEGER_LITERAL(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (TOY_IS_FLOAT(selfLiteral)) {
|
||||||
|
if (TOY_AS_FLOAT(selfLiteral) < 0) {
|
||||||
|
resultLiteral = TOY_TO_INTEGER_LITERAL(-1);
|
||||||
|
}
|
||||||
|
else if (TOY_AS_FLOAT(selfLiteral) > 0) {
|
||||||
|
resultLiteral = TOY_TO_INTEGER_LITERAL(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resultLiteral = TOY_TO_INTEGER_LITERAL(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeClamp(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
if (arguments->count != 3) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to clamp\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the arguments
|
||||||
|
Toy_Literal maxLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal minLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal valueLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
//parse the arguments (if they're identifiers)
|
||||||
|
Toy_Literal valueLiteralIdn = valueLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(valueLiteral) && Toy_parseIdentifierToValue(interpreter, &valueLiteral)) {
|
||||||
|
Toy_freeLiteral(valueLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal minLiteralIdn = minLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(minLiteral) && Toy_parseIdentifierToValue(interpreter, &minLiteral)) {
|
||||||
|
Toy_freeLiteral(minLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal maxLiteralIdn = maxLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(maxLiteral) && Toy_parseIdentifierToValue(interpreter, &maxLiteral)) {
|
||||||
|
Toy_freeLiteral(maxLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check the types
|
||||||
|
if (!(TOY_IS_INTEGER(valueLiteral) || TOY_IS_FLOAT(valueLiteral))) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to clamp\n");
|
||||||
|
Toy_freeLiteral(valueLiteral);
|
||||||
|
Toy_freeLiteral(minLiteral);
|
||||||
|
Toy_freeLiteral(maxLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(TOY_IS_INTEGER(minLiteral) || TOY_IS_FLOAT(minLiteral))) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to clamp\n");
|
||||||
|
Toy_freeLiteral(valueLiteral);
|
||||||
|
Toy_freeLiteral(minLiteral);
|
||||||
|
Toy_freeLiteral(maxLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(TOY_IS_INTEGER(maxLiteral) || TOY_IS_FLOAT(maxLiteral))) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to clamp\n");
|
||||||
|
Toy_freeLiteral(valueLiteral);
|
||||||
|
Toy_freeLiteral(minLiteral);
|
||||||
|
Toy_freeLiteral(maxLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cast ints to floats to handle all types of numbers
|
||||||
|
float value = TOY_IS_INTEGER(valueLiteral)? TOY_AS_INTEGER(valueLiteral) : TOY_AS_FLOAT(valueLiteral);
|
||||||
|
float min = TOY_IS_INTEGER(minLiteral)? TOY_AS_INTEGER(minLiteral) : TOY_AS_FLOAT(minLiteral);
|
||||||
|
float max = TOY_IS_INTEGER(maxLiteral)? TOY_AS_INTEGER(maxLiteral) : TOY_AS_FLOAT(maxLiteral);
|
||||||
|
|
||||||
|
//determine which literal to return (this way, we retain the original type)
|
||||||
|
if (min > value) {
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, minLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (max < value) {
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, maxLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, valueLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteral(valueLiteral);
|
||||||
|
Toy_freeLiteral(minLiteral);
|
||||||
|
Toy_freeLiteral(maxLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeLerp(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
if (arguments->count != 3) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to lerp\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the arguments
|
||||||
|
Toy_Literal amountLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal endLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal startLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
//parse the arguments (if they're identifiers)
|
||||||
|
Toy_Literal startLiteralIdn = startLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(startLiteral) && Toy_parseIdentifierToValue(interpreter, &startLiteral)) {
|
||||||
|
Toy_freeLiteral(startLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal endLiteralIdn = endLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(endLiteral) && Toy_parseIdentifierToValue(interpreter, &endLiteral)) {
|
||||||
|
Toy_freeLiteral(endLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal amountLiteralIdn = amountLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(amountLiteral) && Toy_parseIdentifierToValue(interpreter, &amountLiteral)) {
|
||||||
|
Toy_freeLiteral(amountLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check the argument types
|
||||||
|
if (!(TOY_IS_INTEGER(startLiteral) || TOY_IS_FLOAT(startLiteral))) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to lerp\n");
|
||||||
|
Toy_freeLiteral(startLiteral);
|
||||||
|
Toy_freeLiteral(endLiteral);
|
||||||
|
Toy_freeLiteral(amountLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(TOY_IS_INTEGER(endLiteral) || TOY_IS_FLOAT(endLiteral))) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to lerp\n");
|
||||||
|
Toy_freeLiteral(startLiteral);
|
||||||
|
Toy_freeLiteral(endLiteral);
|
||||||
|
Toy_freeLiteral(amountLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(TOY_IS_INTEGER(amountLiteral) || TOY_IS_FLOAT(amountLiteral))) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to lerp\n");
|
||||||
|
Toy_freeLiteral(startLiteral);
|
||||||
|
Toy_freeLiteral(endLiteral);
|
||||||
|
Toy_freeLiteral(amountLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cast ints to floats to handle all types of numbers
|
||||||
|
float start = TOY_IS_INTEGER(startLiteral)? TOY_AS_INTEGER(startLiteral) : TOY_AS_FLOAT(startLiteral);
|
||||||
|
float end = TOY_IS_INTEGER(endLiteral)? TOY_AS_INTEGER(endLiteral) : TOY_AS_FLOAT(endLiteral);
|
||||||
|
float amount = TOY_IS_INTEGER(amountLiteral)? TOY_AS_INTEGER(amountLiteral) : TOY_AS_FLOAT(amountLiteral);
|
||||||
|
|
||||||
|
//calculate the result
|
||||||
|
float result = start + amount * (end - start);
|
||||||
|
|
||||||
|
//return the result
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_FLOAT_LITERAL(result);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
Toy_freeLiteral(startLiteral);
|
||||||
|
Toy_freeLiteral(endLiteral);
|
||||||
|
Toy_freeLiteral(amountLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
@@ -387,12 +605,6 @@ 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)) {
|
||||||
@@ -503,12 +715,6 @@ 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");
|
||||||
@@ -554,12 +760,6 @@ 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");
|
||||||
@@ -630,12 +830,6 @@ 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");
|
||||||
@@ -752,12 +946,6 @@ 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");
|
||||||
@@ -872,12 +1060,6 @@ 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");
|
||||||
@@ -950,11 +1132,6 @@ 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");
|
||||||
@@ -1000,11 +1177,6 @@ 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");
|
||||||
@@ -1057,12 +1229,6 @@ 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");
|
||||||
@@ -1110,12 +1276,6 @@ 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");
|
||||||
@@ -1225,13 +1385,6 @@ 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");
|
||||||
@@ -1327,12 +1480,6 @@ 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");
|
||||||
@@ -1997,6 +2144,10 @@ int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L
|
|||||||
{"max", nativeMax},
|
{"max", nativeMax},
|
||||||
{"min", nativeMin},
|
{"min", nativeMin},
|
||||||
{"round", nativeRound},
|
{"round", nativeRound},
|
||||||
|
{"sign", nativeSign},
|
||||||
|
{"normalize", nativeNormalize},
|
||||||
|
{"clamp", nativeClamp},
|
||||||
|
{"lerp", nativeLerp},
|
||||||
|
|
||||||
//compound utils
|
//compound utils
|
||||||
{"concat", nativeConcat}, //array, dictionary, string
|
{"concat", nativeConcat}, //array, dictionary, string
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
#include "lib_about.h"
|
#include "lib_toy_version_info.h"
|
||||||
|
|
||||||
#include "toy_memory.h"
|
#include "toy_memory.h"
|
||||||
|
|
||||||
int Toy_hookAbout(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
int Toy_hookToyVersionInfo(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
||||||
//the about keys
|
//the info keys
|
||||||
Toy_Literal majorKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("major"));
|
Toy_Literal majorKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("major"));
|
||||||
Toy_Literal minorKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("minor"));
|
Toy_Literal minorKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("minor"));
|
||||||
Toy_Literal patchKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("patch"));
|
Toy_Literal patchKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("patch"));
|
||||||
Toy_Literal buildKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("build"));
|
Toy_Literal buildKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("build"));
|
||||||
Toy_Literal authorKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("author"));
|
Toy_Literal authorKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("author"));
|
||||||
|
|
||||||
//the about identifiers
|
//the info identifiers
|
||||||
Toy_Literal majorIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("major"));
|
Toy_Literal majorIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("major"));
|
||||||
Toy_Literal minorIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("minor"));
|
Toy_Literal minorIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("minor"));
|
||||||
Toy_Literal patchIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("patch"));
|
Toy_Literal patchIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("patch"));
|
||||||
Toy_Literal buildIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("build"));
|
Toy_Literal buildIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("build"));
|
||||||
Toy_Literal authorIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("author"));
|
Toy_Literal authorIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("author"));
|
||||||
|
|
||||||
//the about values
|
//the info values
|
||||||
Toy_Literal majorLiteral = TOY_TO_INTEGER_LITERAL(TOY_VERSION_MAJOR);
|
Toy_Literal majorLiteral = TOY_TO_INTEGER_LITERAL(TOY_VERSION_MAJOR);
|
||||||
Toy_Literal minorLiteral = TOY_TO_INTEGER_LITERAL(TOY_VERSION_MINOR);
|
Toy_Literal minorLiteral = TOY_TO_INTEGER_LITERAL(TOY_VERSION_MINOR);
|
||||||
Toy_Literal patchLiteral = TOY_TO_INTEGER_LITERAL(TOY_VERSION_PATCH);
|
Toy_Literal patchLiteral = TOY_TO_INTEGER_LITERAL(TOY_VERSION_PATCH);
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "toy_interpreter.h"
|
||||||
|
|
||||||
|
int Toy_hookToyVersionInfo(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
|
||||||
+3
-2
@@ -1,5 +1,6 @@
|
|||||||
#include "repl_tools.h"
|
#include "repl_tools.h"
|
||||||
#include "lib_about.h"
|
#include "drive_system.h"
|
||||||
|
#include "lib_toy_version_info.h"
|
||||||
#include "lib_standard.h"
|
#include "lib_standard.h"
|
||||||
#include "lib_random.h"
|
#include "lib_random.h"
|
||||||
#include "lib_runner.h"
|
#include "lib_runner.h"
|
||||||
@@ -25,7 +26,7 @@ void repl(const char* initialInput) {
|
|||||||
Toy_initInterpreter(&interpreter);
|
Toy_initInterpreter(&interpreter);
|
||||||
|
|
||||||
//inject the libs
|
//inject the libs
|
||||||
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
|
Toy_injectNativeHook(&interpreter, "toy_version_info", Toy_hookToyVersionInfo);
|
||||||
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
|
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
|
||||||
Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom);
|
Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom);
|
||||||
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
|
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
|
||||||
|
|||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
#include "repl_tools.h"
|
#include "repl_tools.h"
|
||||||
#include "lib_about.h"
|
#include "lib_toy_version_info.h"
|
||||||
#include "lib_standard.h"
|
#include "lib_standard.h"
|
||||||
#include "lib_random.h"
|
#include "lib_random.h"
|
||||||
#include "lib_runner.h"
|
#include "lib_runner.h"
|
||||||
@@ -111,7 +111,7 @@ void Toy_runBinary(const unsigned char* tb, size_t size) {
|
|||||||
Toy_initInterpreter(&interpreter);
|
Toy_initInterpreter(&interpreter);
|
||||||
|
|
||||||
//inject the libs
|
//inject the libs
|
||||||
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
|
Toy_injectNativeHook(&interpreter, "toy_version_info", Toy_hookToyVersionInfo);
|
||||||
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
|
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
|
||||||
Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom);
|
Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom);
|
||||||
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
|
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
|
||||||
@@ -159,7 +159,7 @@ static unsigned char readByte(const unsigned char* tb, int* count) {
|
|||||||
|
|
||||||
static const char* readString(const unsigned char* tb, int* count) {
|
static const char* readString(const unsigned char* tb, int* count) {
|
||||||
const unsigned char* ret = tb + *count;
|
const unsigned char* ret = tb + *count;
|
||||||
*count += strlen((char*)ret) + 1; //+1 for null character
|
*count += (int)strlen((char*)ret) + 1; //+1 for null character
|
||||||
return (const char*)ret;
|
return (const char*)ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@ const unsigned char* Toy_compileString(const char* source, size_t* size);
|
|||||||
|
|
||||||
This function takes a bytecode array of `size` size, and executes it. The libraries available to the code are currently:
|
This function takes a bytecode array of `size` size, and executes it. The libraries available to the code are currently:
|
||||||
|
|
||||||
* lib_about
|
* lib_toy_version_info
|
||||||
* lib_standard
|
* lib_standard
|
||||||
* lib_random
|
* lib_random
|
||||||
* lib_runner
|
* lib_runner
|
||||||
|
|||||||
+3
-3
@@ -11,14 +11,14 @@ OBJ = $(addprefix $(ODIR)/,$(SRC:.c=.o))
|
|||||||
OUTNAME=toy
|
OUTNAME=toy
|
||||||
|
|
||||||
ifeq ($(findstring CYGWIN, $(shell uname)),CYGWIN)
|
ifeq ($(findstring CYGWIN, $(shell uname)),CYGWIN)
|
||||||
LIBLINE =-Wl,--out-implib=../$(TOY_OUTDIR)/lib$(OUTNAME).dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive
|
LIBLINE=-Wl,-rpath,. -Wl,--out-implib=../$(TOY_OUTDIR)/lib$(OUTNAME).dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive
|
||||||
OUT=../$(TOY_OUTDIR)/$(OUTNAME).dll
|
OUT=../$(TOY_OUTDIR)/$(OUTNAME).dll
|
||||||
else ifeq ($(shell uname),Linux)
|
else ifeq ($(shell uname),Linux)
|
||||||
LIBLINE=-Wl,--out-implib=../$(TOY_OUTDIR)/lib$(OUTNAME).a -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive
|
LIBLINE=-Wl,-rpath,. -Wl,--out-implib=../$(TOY_OUTDIR)/lib$(OUTNAME).a -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive
|
||||||
OUT=../$(TOY_OUTDIR)/lib$(OUTNAME).so
|
OUT=../$(TOY_OUTDIR)/lib$(OUTNAME).so
|
||||||
CFLAGS += -fPIC
|
CFLAGS += -fPIC
|
||||||
else ifeq ($(OS),Windows_NT)
|
else ifeq ($(OS),Windows_NT)
|
||||||
LIBLINE =-Wl,--out-implib=../$(TOY_OUTDIR)/lib$(OUTNAME).dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive
|
LIBLINE=-Wl,-rpath,. -Wl,--out-implib=../$(TOY_OUTDIR)/lib$(OUTNAME).dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive
|
||||||
OUT=../$(TOY_OUTDIR)/$(OUTNAME).dll
|
OUT=../$(TOY_OUTDIR)/$(OUTNAME).dll
|
||||||
else ifeq ($(shell uname),Darwin)
|
else ifeq ($(shell uname),Darwin)
|
||||||
LIBLINE = $(OBJ)
|
LIBLINE = $(OBJ)
|
||||||
|
|||||||
@@ -17,13 +17,11 @@ The most important macro is `TOY_API`, which specifies functions intended for th
|
|||||||
* [toy_common.h](toy_common_h.md)
|
* [toy_common.h](toy_common_h.md)
|
||||||
* [toy_console_colors.h](toy_console_colors_h.md)
|
* [toy_console_colors.h](toy_console_colors_h.md)
|
||||||
* [toy_memory.h](toy_memory_h.md)
|
* [toy_memory.h](toy_memory_h.md)
|
||||||
* [toy_drive_system.h](toy_drive_system_h.md)
|
|
||||||
!*/
|
!*/
|
||||||
|
|
||||||
#include "toy_common.h"
|
#include "toy_common.h"
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
#include "toy_memory.h"
|
#include "toy_memory.h"
|
||||||
#include "toy_drive_system.h"
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
## Core Pipeline
|
## Core Pipeline
|
||||||
|
|||||||
+1
-1
@@ -64,7 +64,7 @@ The current patch version of Toy. This value is embedded into the bytecode.
|
|||||||
This value MUST fit into an unsigned char.
|
This value MUST fit into an unsigned char.
|
||||||
!*/
|
!*/
|
||||||
|
|
||||||
#define TOY_VERSION_PATCH 0
|
#define TOY_VERSION_PATCH 1
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
### TOY_VERSION_BUILD
|
### TOY_VERSION_BUILD
|
||||||
|
|||||||
+383
-363
@@ -11,6 +11,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
//printing utilities
|
||||||
static void printWrapper(const char* output) {
|
static void printWrapper(const char* output) {
|
||||||
//allow for disabling of newlines in the repl
|
//allow for disabling of newlines in the repl
|
||||||
#ifndef TOY_EXPORT
|
#ifndef TOY_EXPORT
|
||||||
@@ -33,6 +34,19 @@ static void errorWrapper(const char* output) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "%s" TOY_CC_RESET, output); //no newline
|
fprintf(stderr, TOY_CC_ERROR "%s" TOY_CC_RESET, output); //no newline
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Toy_setInterpreterPrint(Toy_Interpreter* interpreter, Toy_PrintFn printOutput) {
|
||||||
|
interpreter->printOutput = printOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toy_setInterpreterAssert(Toy_Interpreter* interpreter, Toy_PrintFn assertOutput) {
|
||||||
|
interpreter->assertOutput = assertOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toy_setInterpreterError(Toy_Interpreter* interpreter, Toy_PrintFn errorOutput) {
|
||||||
|
interpreter->errorOutput = errorOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
//injection utilities
|
||||||
bool Toy_injectNativeFn(Toy_Interpreter* interpreter, const char* name, Toy_NativeFn func) {
|
bool Toy_injectNativeFn(Toy_Interpreter* interpreter, const char* name, Toy_NativeFn func) {
|
||||||
//reject reserved words
|
//reject reserved words
|
||||||
if (Toy_findTypeByKeyword(name) != TOY_TOKEN_EOF) {
|
if (Toy_findTypeByKeyword(name) != TOY_TOKEN_EOF) {
|
||||||
@@ -42,19 +56,21 @@ bool Toy_injectNativeFn(Toy_Interpreter* interpreter, const char* name, Toy_Nati
|
|||||||
|
|
||||||
Toy_Literal identifier = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString(name));
|
Toy_Literal identifier = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString(name));
|
||||||
|
|
||||||
//make sure the name isn't taken
|
//make sure the name isn't taken (manually to skip the scope chain)
|
||||||
if (Toy_existsLiteralDictionary(&interpreter->scope->variables, identifier)) {
|
if (Toy_existsLiteralDictionary(&interpreter->scope->variables, identifier)) {
|
||||||
interpreter->errorOutput("Can't override an existing variable\n");
|
interpreter->errorOutput("Can't override an existing variable\n");
|
||||||
|
Toy_freeLiteral(identifier);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_Literal fn = TOY_TO_FUNCTION_NATIVE_LITERAL(func);
|
Toy_Literal fn = TOY_TO_FUNCTION_NATIVE_LITERAL(func);
|
||||||
Toy_Literal type = TOY_TO_TYPE_LITERAL(fn.type, true);
|
Toy_Literal type = TOY_TO_TYPE_LITERAL(fn.type, true);
|
||||||
|
|
||||||
Toy_setLiteralDictionary(&interpreter->scope->variables, identifier, fn);
|
Toy_declareScopeVariable(interpreter->scope, identifier, type);
|
||||||
Toy_setLiteralDictionary(&interpreter->scope->types, identifier, type);
|
Toy_setScopeVariable(interpreter->scope, identifier, fn, false);
|
||||||
|
|
||||||
Toy_freeLiteral(identifier);
|
Toy_freeLiteral(identifier);
|
||||||
|
Toy_freeLiteral(fn);
|
||||||
Toy_freeLiteral(type);
|
Toy_freeLiteral(type);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -67,12 +83,12 @@ bool Toy_injectNativeHook(Toy_Interpreter* interpreter, const char* name, Toy_Ho
|
|||||||
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->hooks, identifier)) {
|
if (Toy_existsLiteralDictionary(interpreter->hooks, identifier)) {
|
||||||
interpreter->errorOutput("Can't override an existing hook\n");
|
interpreter->errorOutput("Can't override an existing hook\n");
|
||||||
|
Toy_freeLiteral(identifier);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,11 +96,27 @@ bool Toy_injectNativeHook(Toy_Interpreter* interpreter, const char* name, Toy_Ho
|
|||||||
Toy_setLiteralDictionary(interpreter->hooks, identifier, fn);
|
Toy_setLiteralDictionary(interpreter->hooks, identifier, fn);
|
||||||
|
|
||||||
Toy_freeLiteral(identifier);
|
Toy_freeLiteral(identifier);
|
||||||
|
Toy_freeLiteral(fn);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_parseCompoundToPureValues(Toy_Interpreter* interpreter, Toy_Literal* literalPtr) {
|
//parsing to value utilities
|
||||||
|
bool Toy_parseIdentifierToValue(Toy_Interpreter* interpreter, Toy_Literal* literalPtr) {
|
||||||
|
//this converts identifiers to values
|
||||||
|
if (TOY_IS_IDENTIFIER(*literalPtr)) {
|
||||||
|
if (!Toy_getScopeVariable(interpreter->scope, *literalPtr, literalPtr)) {
|
||||||
|
interpreter->errorOutput("Undeclared variable ");
|
||||||
|
Toy_printLiteralCustom(*literalPtr, interpreter->errorOutput);
|
||||||
|
interpreter->errorOutput("\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toy_parseCompoundToValue(Toy_Interpreter* interpreter, Toy_Literal* literalPtr) {
|
||||||
//parse out an array
|
//parse out an array
|
||||||
if (TOY_IS_ARRAY(*literalPtr)) {
|
if (TOY_IS_ARRAY(*literalPtr)) {
|
||||||
for (int i = 0; i < TOY_AS_ARRAY(*literalPtr)->count; i++) {
|
for (int i = 0; i < TOY_AS_ARRAY(*literalPtr)->count; i++) {
|
||||||
@@ -105,7 +137,7 @@ void Toy_parseCompoundToPureValues(Toy_Interpreter* interpreter, Toy_Literal* li
|
|||||||
|
|
||||||
//recurse on sub-compounds
|
//recurse on sub-compounds
|
||||||
if (TOY_IS_ARRAY(TOY_AS_ARRAY(*literalPtr)->literals[i]) || TOY_IS_DICTIONARY(TOY_AS_ARRAY(*literalPtr)->literals[i])) {
|
if (TOY_IS_ARRAY(TOY_AS_ARRAY(*literalPtr)->literals[i]) || TOY_IS_DICTIONARY(TOY_AS_ARRAY(*literalPtr)->literals[i])) {
|
||||||
Toy_parseCompoundToPureValues(interpreter, &TOY_AS_ARRAY(*literalPtr)->literals[i]);
|
Toy_parseCompoundToValue(interpreter, &TOY_AS_ARRAY(*literalPtr)->literals[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,11 +154,11 @@ void Toy_parseCompoundToPureValues(Toy_Interpreter* interpreter, Toy_Literal* li
|
|||||||
|
|
||||||
//recurse on sub-compounds
|
//recurse on sub-compounds
|
||||||
if (TOY_IS_ARRAY(TOY_AS_DICTIONARY(*literalPtr)->entries[i].key) || TOY_IS_DICTIONARY(TOY_AS_DICTIONARY(*literalPtr)->entries[i].key)) {
|
if (TOY_IS_ARRAY(TOY_AS_DICTIONARY(*literalPtr)->entries[i].key) || TOY_IS_DICTIONARY(TOY_AS_DICTIONARY(*literalPtr)->entries[i].key)) {
|
||||||
Toy_parseCompoundToPureValues(interpreter, &TOY_AS_DICTIONARY(*literalPtr)->entries[i].key);
|
Toy_parseCompoundToValue(interpreter, &TOY_AS_DICTIONARY(*literalPtr)->entries[i].key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_ARRAY(TOY_AS_DICTIONARY(*literalPtr)->entries[i].value) || TOY_IS_DICTIONARY(TOY_AS_DICTIONARY(*literalPtr)->entries[i].value)) {
|
if (TOY_IS_ARRAY(TOY_AS_DICTIONARY(*literalPtr)->entries[i].value) || TOY_IS_DICTIONARY(TOY_AS_DICTIONARY(*literalPtr)->entries[i].value)) {
|
||||||
Toy_parseCompoundToPureValues(interpreter, &TOY_AS_DICTIONARY(*literalPtr)->entries[i].value);
|
Toy_parseCompoundToValue(interpreter, &TOY_AS_DICTIONARY(*literalPtr)->entries[i].value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,14 +191,14 @@ void Toy_parseCompoundToPureValues(Toy_Interpreter* interpreter, Toy_Literal* li
|
|||||||
Toy_parseIdentifierToValue(interpreter, &key);
|
Toy_parseIdentifierToValue(interpreter, &key);
|
||||||
}
|
}
|
||||||
if (TOY_IS_ARRAY(key) || TOY_IS_DICTIONARY(key)) {
|
if (TOY_IS_ARRAY(key) || TOY_IS_DICTIONARY(key)) {
|
||||||
Toy_parseCompoundToPureValues(interpreter, &key);
|
Toy_parseCompoundToValue(interpreter, &key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_IDENTIFIER(value)) {
|
if (TOY_IS_IDENTIFIER(value)) {
|
||||||
Toy_parseIdentifierToValue(interpreter, &value);
|
Toy_parseIdentifierToValue(interpreter, &value);
|
||||||
}
|
}
|
||||||
if (TOY_IS_ARRAY(value) || TOY_IS_DICTIONARY(value)) {
|
if (TOY_IS_ARRAY(value) || TOY_IS_DICTIONARY(value)) {
|
||||||
Toy_parseCompoundToPureValues(interpreter, &value);
|
Toy_parseCompoundToValue(interpreter, &value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_setLiteralDictionary(ret, key, value);
|
Toy_setLiteralDictionary(ret, key, value);
|
||||||
@@ -181,38 +213,29 @@ void Toy_parseCompoundToPureValues(Toy_Interpreter* interpreter, Toy_Literal* li
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Toy_parseIdentifierToValue(Toy_Interpreter* interpreter, Toy_Literal* literalPtr) {
|
void parseTypeToValue(Toy_Interpreter* interpreter, Toy_Literal* literalPtr) {
|
||||||
//this converts identifiers to values
|
//if an identifier is embedded in the type, figure out what it is
|
||||||
if (TOY_IS_IDENTIFIER(*literalPtr)) {
|
Toy_Literal idn = *literalPtr;
|
||||||
if (!Toy_getScopeVariable(interpreter->scope, *literalPtr, literalPtr)) {
|
if (TOY_IS_IDENTIFIER(*literalPtr) && Toy_parseIdentifierToValue(interpreter, literalPtr)) {
|
||||||
interpreter->errorOutput("Undeclared variable ");
|
Toy_freeLiteral(idn);
|
||||||
Toy_printLiteralCustom(*literalPtr, interpreter->errorOutput);
|
}
|
||||||
interpreter->errorOutput("\n");
|
|
||||||
return false;
|
//if this is an array or dictionary, continue to the subtypes
|
||||||
|
if (TOY_IS_TYPE(*literalPtr) && (TOY_AS_TYPE(*literalPtr).typeOf == TOY_LITERAL_ARRAY || TOY_AS_TYPE(*literalPtr).typeOf == TOY_LITERAL_DICTIONARY)) {
|
||||||
|
for (int i = 0; i < TOY_AS_TYPE(*literalPtr).count; i++) {
|
||||||
|
parseTypeToValue(interpreter, &((Toy_Literal*)(TOY_AS_TYPE(*literalPtr).subtypes))[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (TOY_IS_ARRAY(*literalPtr) || TOY_IS_DICTIONARY(*literalPtr)) {
|
//BUGFIX: make sure it actually is a type
|
||||||
// Toy_parseCompoundToPureValues(interpreter, literalPtr);
|
if (!TOY_IS_TYPE(*literalPtr)) {
|
||||||
// }
|
interpreter->errorOutput("Bad type encountered: ");
|
||||||
|
Toy_printLiteralCustom(*literalPtr, interpreter->errorOutput);
|
||||||
return true;
|
interpreter->errorOutput("\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//utilities for the host program
|
//reading utils
|
||||||
void Toy_setInterpreterPrint(Toy_Interpreter* interpreter, Toy_PrintFn printOutput) {
|
|
||||||
interpreter->printOutput = printOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Toy_setInterpreterAssert(Toy_Interpreter* interpreter, Toy_PrintFn assertOutput) {
|
|
||||||
interpreter->assertOutput = assertOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Toy_setInterpreterError(Toy_Interpreter* interpreter, Toy_PrintFn errorOutput) {
|
|
||||||
interpreter->errorOutput = errorOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
//utils
|
|
||||||
static unsigned char readByte(const unsigned char* tb, int* count) {
|
static unsigned char readByte(const unsigned char* tb, int* count) {
|
||||||
unsigned char ret = *(unsigned char*)(tb + *count);
|
unsigned char ret = *(unsigned char*)(tb + *count);
|
||||||
*count += 1;
|
*count += 1;
|
||||||
@@ -332,7 +355,8 @@ static bool execPushLiteral(Toy_Interpreter* interpreter, bool lng) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rawLiteral(Toy_Interpreter* interpreter) {
|
static bool execRawLiteral(Toy_Interpreter* interpreter) {
|
||||||
|
//this seems to be only used by increments and decrements
|
||||||
Toy_Literal lit = Toy_popLiteralArray(&interpreter->stack);
|
Toy_Literal lit = Toy_popLiteralArray(&interpreter->stack);
|
||||||
|
|
||||||
Toy_Literal idn = lit;
|
Toy_Literal idn = lit;
|
||||||
@@ -544,31 +568,6 @@ static bool execArithmetic(Toy_Interpreter* interpreter, Toy_Opcode opcode) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Toy_Literal parseTypeToValue(Toy_Interpreter* interpreter, Toy_Literal type) {
|
|
||||||
//if an identifier is embedded in the type, figure out what it iss
|
|
||||||
Toy_Literal typeIdn = type;
|
|
||||||
if (TOY_IS_IDENTIFIER(type) && Toy_parseIdentifierToValue(interpreter, &type)) {
|
|
||||||
Toy_freeLiteral(typeIdn);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if this is an array or dictionary, continue to the subtypes
|
|
||||||
if (TOY_IS_TYPE(type) && (TOY_AS_TYPE(type).typeOf == TOY_LITERAL_ARRAY || TOY_AS_TYPE(type).typeOf == TOY_LITERAL_DICTIONARY)) {
|
|
||||||
for (int i = 0; i < TOY_AS_TYPE(type).count; i++) {
|
|
||||||
((Toy_Literal*)(TOY_AS_TYPE(type).subtypes))[i] = parseTypeToValue(interpreter, ((Toy_Literal*)(TOY_AS_TYPE(type).subtypes))[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//BUGFIX: make sure it actually is a type
|
|
||||||
if (!TOY_IS_TYPE(type)) {
|
|
||||||
interpreter->errorOutput("Bad type encountered: ");
|
|
||||||
Toy_printLiteralCustom(type, interpreter->errorOutput);
|
|
||||||
interpreter->errorOutput("\n");
|
|
||||||
//TODO: would be better to return an int here...
|
|
||||||
}
|
|
||||||
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool execVarDecl(Toy_Interpreter* interpreter, bool lng) {
|
static bool execVarDecl(Toy_Interpreter* interpreter, bool lng) {
|
||||||
//read the index in the cache
|
//read the index in the cache
|
||||||
int identifierIndex = 0;
|
int identifierIndex = 0;
|
||||||
@@ -592,7 +591,7 @@ static bool execVarDecl(Toy_Interpreter* interpreter, bool lng) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//BUGFIX: because identifiers are getting embedded in type definitions
|
//BUGFIX: because identifiers are getting embedded in type definitions
|
||||||
type = parseTypeToValue(interpreter, type);
|
parseTypeToValue(interpreter, &type);
|
||||||
|
|
||||||
if (!Toy_declareScopeVariable(interpreter->scope, identifier, type)) {
|
if (!Toy_declareScopeVariable(interpreter->scope, identifier, type)) {
|
||||||
interpreter->errorOutput("Can't redefine the variable \"");
|
interpreter->errorOutput("Can't redefine the variable \"");
|
||||||
@@ -609,7 +608,7 @@ static bool execVarDecl(Toy_Interpreter* interpreter, bool lng) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_ARRAY(val) || TOY_IS_DICTIONARY(val)) {
|
if (TOY_IS_ARRAY(val) || TOY_IS_DICTIONARY(val)) {
|
||||||
Toy_parseCompoundToPureValues(interpreter, &val);
|
Toy_parseCompoundToValue(interpreter, &val);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: could restrict opaque data to only opaque variables
|
//TODO: could restrict opaque data to only opaque variables
|
||||||
@@ -689,7 +688,7 @@ static bool execVarAssign(Toy_Interpreter* interpreter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_ARRAY(rhs) || TOY_IS_DICTIONARY(rhs)) {
|
if (TOY_IS_ARRAY(rhs) || TOY_IS_DICTIONARY(rhs)) {
|
||||||
Toy_parseCompoundToPureValues(interpreter, &rhs);
|
Toy_parseCompoundToValue(interpreter, &rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TOY_IS_IDENTIFIER(lhs)) {
|
if (!TOY_IS_IDENTIFIER(lhs)) {
|
||||||
@@ -733,11 +732,11 @@ static bool execVarAssign(Toy_Interpreter* interpreter) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool execVarArithmeticAssign(Toy_Interpreter* interpreter) {
|
static bool execVarArithmeticAssignInterjection(Toy_Interpreter* interpreter) {
|
||||||
Toy_Literal rhs = Toy_popLiteralArray(&interpreter->stack);
|
Toy_Literal rhs = Toy_popLiteralArray(&interpreter->stack);
|
||||||
Toy_Literal lhs = Toy_popLiteralArray(&interpreter->stack);
|
Toy_Literal lhs = Toy_popLiteralArray(&interpreter->stack);
|
||||||
|
|
||||||
//duplicate the name
|
//duplicate the (presumably) identifier
|
||||||
Toy_pushLiteralArray(&interpreter->stack, lhs);
|
Toy_pushLiteralArray(&interpreter->stack, lhs);
|
||||||
Toy_pushLiteralArray(&interpreter->stack, lhs);
|
Toy_pushLiteralArray(&interpreter->stack, lhs);
|
||||||
Toy_pushLiteralArray(&interpreter->stack, rhs);
|
Toy_pushLiteralArray(&interpreter->stack, rhs);
|
||||||
@@ -757,7 +756,10 @@ static bool execValCast(Toy_Interpreter* interpreter) {
|
|||||||
Toy_freeLiteral(valueIdn);
|
Toy_freeLiteral(valueIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_Literal result = TOY_TO_NULL_LITERAL;
|
Toy_Literal typeIdn = type;
|
||||||
|
if (TOY_IS_IDENTIFIER(type) && Toy_parseIdentifierToValue(interpreter, &type)) {
|
||||||
|
Toy_freeLiteral(typeIdn);
|
||||||
|
}
|
||||||
|
|
||||||
if (TOY_IS_NULL(value)) {
|
if (TOY_IS_NULL(value)) {
|
||||||
interpreter->errorOutput("Can't cast a null value\n");
|
interpreter->errorOutput("Can't cast a null value\n");
|
||||||
@@ -768,6 +770,8 @@ static bool execValCast(Toy_Interpreter* interpreter) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Toy_Literal result = TOY_TO_NULL_LITERAL;
|
||||||
|
|
||||||
//cast the rhs to the type represented by lhs
|
//cast the rhs to the type represented by lhs
|
||||||
switch(TOY_AS_TYPE(type).typeOf) {
|
switch(TOY_AS_TYPE(type).typeOf) {
|
||||||
case TOY_LITERAL_BOOLEAN:
|
case TOY_LITERAL_BOOLEAN:
|
||||||
@@ -845,6 +849,11 @@ static bool execValCast(Toy_Interpreter* interpreter) {
|
|||||||
interpreter->errorOutput("Unknown cast type found: ");
|
interpreter->errorOutput("Unknown cast type found: ");
|
||||||
Toy_printLiteralCustom(type, interpreter->errorOutput);
|
Toy_printLiteralCustom(type, interpreter->errorOutput);
|
||||||
interpreter->errorOutput("\n");
|
interpreter->errorOutput("\n");
|
||||||
|
|
||||||
|
Toy_freeLiteral(result);
|
||||||
|
Toy_freeLiteral(value);
|
||||||
|
Toy_freeLiteral(type);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -891,14 +900,16 @@ static bool execCompareEqual(Toy_Interpreter* interpreter, bool invert) {
|
|||||||
Toy_freeLiteral(lhsIdn);
|
Toy_freeLiteral(lhsIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool result = Toy_literalsAreEqual(lhs, rhs);
|
bool equal = Toy_literalsAreEqual(lhs, rhs);
|
||||||
|
|
||||||
if (invert) {
|
if (invert) {
|
||||||
result = !result;
|
equal = !equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_BOOLEAN_LITERAL(result));
|
Toy_Literal result = TOY_TO_BOOLEAN_LITERAL(equal);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||||
|
|
||||||
|
Toy_freeLiteral(result);
|
||||||
Toy_freeLiteral(lhs);
|
Toy_freeLiteral(lhs);
|
||||||
Toy_freeLiteral(rhs);
|
Toy_freeLiteral(rhs);
|
||||||
|
|
||||||
@@ -948,17 +959,19 @@ static bool execCompareLess(Toy_Interpreter* interpreter, bool invert) {
|
|||||||
rhs = TOY_TO_FLOAT_LITERAL(TOY_AS_INTEGER(rhs));
|
rhs = TOY_TO_FLOAT_LITERAL(TOY_AS_INTEGER(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool result;
|
bool less;
|
||||||
|
|
||||||
if (!invert) {
|
if (!invert) {
|
||||||
result = (TOY_AS_FLOAT(lhs) < TOY_AS_FLOAT(rhs));
|
less = (TOY_AS_FLOAT(lhs) < TOY_AS_FLOAT(rhs));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = (TOY_AS_FLOAT(lhs) > TOY_AS_FLOAT(rhs));
|
less = (TOY_AS_FLOAT(lhs) > TOY_AS_FLOAT(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_BOOLEAN_LITERAL(result));
|
Toy_Literal result = TOY_TO_BOOLEAN_LITERAL(less);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||||
|
|
||||||
|
Toy_freeLiteral(result);
|
||||||
Toy_freeLiteral(lhs);
|
Toy_freeLiteral(lhs);
|
||||||
Toy_freeLiteral(rhs);
|
Toy_freeLiteral(rhs);
|
||||||
|
|
||||||
@@ -1009,17 +1022,19 @@ static bool execCompareLessEqual(Toy_Interpreter* interpreter, bool invert) {
|
|||||||
rhs = TOY_TO_FLOAT_LITERAL(TOY_AS_INTEGER(rhs));
|
rhs = TOY_TO_FLOAT_LITERAL(TOY_AS_INTEGER(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool result;
|
bool lessEqual;
|
||||||
|
|
||||||
if (!invert) {
|
if (!invert) {
|
||||||
result = (TOY_AS_FLOAT(lhs) < TOY_AS_FLOAT(rhs)) || Toy_literalsAreEqual(lhs, rhs);
|
lessEqual = (TOY_AS_FLOAT(lhs) < TOY_AS_FLOAT(rhs)) || Toy_literalsAreEqual(lhs, rhs);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = (TOY_AS_FLOAT(lhs) > TOY_AS_FLOAT(rhs)) || Toy_literalsAreEqual(lhs, rhs);
|
lessEqual = (TOY_AS_FLOAT(lhs) > TOY_AS_FLOAT(rhs)) || Toy_literalsAreEqual(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_BOOLEAN_LITERAL(result));
|
Toy_Literal result = TOY_TO_BOOLEAN_LITERAL(lessEqual);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||||
|
|
||||||
|
Toy_freeLiteral(result);
|
||||||
Toy_freeLiteral(lhs);
|
Toy_freeLiteral(lhs);
|
||||||
Toy_freeLiteral(rhs);
|
Toy_freeLiteral(rhs);
|
||||||
|
|
||||||
@@ -1040,7 +1055,7 @@ static bool execAnd(Toy_Interpreter* interpreter) {
|
|||||||
Toy_freeLiteral(lhsIdn);
|
Toy_freeLiteral(lhsIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
//short-circuit support
|
//short-circuit - broken, see issue #73
|
||||||
if (!TOY_IS_TRUTHY(lhs)) {
|
if (!TOY_IS_TRUTHY(lhs)) {
|
||||||
Toy_pushLiteralArray(&interpreter->stack, lhs);
|
Toy_pushLiteralArray(&interpreter->stack, lhs);
|
||||||
}
|
}
|
||||||
@@ -1068,7 +1083,7 @@ static bool execOr(Toy_Interpreter* interpreter) {
|
|||||||
Toy_freeLiteral(lhsIdn);
|
Toy_freeLiteral(lhsIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
//short-circuit support
|
//short-circuit - broken, see issue #73
|
||||||
if (TOY_IS_TRUTHY(lhs)) {
|
if (TOY_IS_TRUTHY(lhs)) {
|
||||||
Toy_pushLiteralArray(&interpreter->stack, lhs);
|
Toy_pushLiteralArray(&interpreter->stack, lhs);
|
||||||
}
|
}
|
||||||
@@ -1096,7 +1111,7 @@ static bool execJump(Toy_Interpreter* interpreter) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool execFalseJump(Toy_Interpreter* interpreter) {
|
static bool execJumpIfFalse(Toy_Interpreter* interpreter) {
|
||||||
int target = (int)readShort(interpreter->bytecode, &interpreter->count);
|
int target = (int)readShort(interpreter->bytecode, &interpreter->count);
|
||||||
|
|
||||||
if (target + interpreter->codeStart > interpreter->length) {
|
if (target + interpreter->codeStart > interpreter->length) {
|
||||||
@@ -1127,10 +1142,6 @@ static bool execFalseJump(Toy_Interpreter* interpreter) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//forward declare
|
|
||||||
static void execInterpreter(Toy_Interpreter*);
|
|
||||||
static void readInterpreterSections(Toy_Interpreter* interpreter);
|
|
||||||
|
|
||||||
//expect stack: identifier, arg1, arg2, arg3..., stackSize
|
//expect stack: identifier, arg1, arg2, arg3..., stackSize
|
||||||
//also supports identifier & arg1 to be other way around (looseFirstArgument)
|
//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) {
|
||||||
@@ -1213,275 +1224,6 @@ 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) {
|
|
||||||
//check for side-loaded native functions
|
|
||||||
if (TOY_IS_FUNCTION_NATIVE(func)) {
|
|
||||||
//TODO: parse out identifier values, see issue #64
|
|
||||||
|
|
||||||
//call the native function
|
|
||||||
int returnsCount = TOY_AS_FUNCTION_NATIVE(func)(interpreter, arguments);
|
|
||||||
|
|
||||||
if (returnsCount < 0) {
|
|
||||||
// interpreter->errorOutput("Unknown error from native function\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//get the results
|
|
||||||
Toy_LiteralArray returnsFromInner;
|
|
||||||
Toy_initLiteralArray(&returnsFromInner);
|
|
||||||
|
|
||||||
for (int i = 0; i < (returnsCount || 1); i++) {
|
|
||||||
Toy_Literal lit = Toy_popLiteralArray(&interpreter->stack);
|
|
||||||
Toy_pushLiteralArray(&returnsFromInner, lit); //NOTE: also reverses the order
|
|
||||||
Toy_freeLiteral(lit);
|
|
||||||
}
|
|
||||||
|
|
||||||
//flip them around and pass to returns
|
|
||||||
while (returnsFromInner.count > 0) {
|
|
||||||
Toy_Literal lit = Toy_popLiteralArray(&returnsFromInner);
|
|
||||||
Toy_pushLiteralArray(returns, lit);
|
|
||||||
Toy_freeLiteral(lit);
|
|
||||||
}
|
|
||||||
|
|
||||||
Toy_freeLiteralArray(&returnsFromInner);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//normal Toy function
|
|
||||||
if (!TOY_IS_FUNCTION(func)) {
|
|
||||||
interpreter->errorOutput("Function literal required in Toy_callLiteralFn()\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//set up a new interpreter
|
|
||||||
Toy_Interpreter inner;
|
|
||||||
|
|
||||||
//init the inner interpreter manually
|
|
||||||
Toy_initLiteralArray(&inner.literalCache);
|
|
||||||
inner.scope = Toy_pushScope(func.as.function.scope);
|
|
||||||
inner.bytecode = ((Toy_RefFunction*)(TOY_AS_FUNCTION(func).inner.ptr))->data;
|
|
||||||
inner.length = ((Toy_RefFunction*)(TOY_AS_FUNCTION(func).inner.ptr))->length;
|
|
||||||
inner.count = 0;
|
|
||||||
inner.codeStart = -1;
|
|
||||||
inner.depth = interpreter->depth + 1;
|
|
||||||
inner.panic = false;
|
|
||||||
Toy_initLiteralArray(&inner.stack);
|
|
||||||
inner.hooks = interpreter->hooks;
|
|
||||||
Toy_setInterpreterPrint(&inner, interpreter->printOutput);
|
|
||||||
Toy_setInterpreterAssert(&inner, interpreter->assertOutput);
|
|
||||||
Toy_setInterpreterError(&inner, interpreter->errorOutput);
|
|
||||||
|
|
||||||
//prep the sections
|
|
||||||
readInterpreterSections(&inner);
|
|
||||||
|
|
||||||
//prep the arguments
|
|
||||||
Toy_LiteralArray* paramArray = TOY_AS_ARRAY(inner.literalCache.literals[ readShort(inner.bytecode, &inner.count) ]);
|
|
||||||
Toy_LiteralArray* returnArray = TOY_AS_ARRAY(inner.literalCache.literals[ readShort(inner.bytecode, &inner.count) ]);
|
|
||||||
|
|
||||||
//get the rest param, if it exists
|
|
||||||
Toy_Literal restParam = TOY_TO_NULL_LITERAL;
|
|
||||||
if (paramArray->count >= 2 && TOY_AS_TYPE(paramArray->literals[ paramArray->count -1 ]).typeOf == TOY_LITERAL_FUNCTION_ARG_REST) {
|
|
||||||
restParam = paramArray->literals[ paramArray->count -2 ];
|
|
||||||
}
|
|
||||||
|
|
||||||
//check the param total is correct
|
|
||||||
if ((TOY_IS_NULL(restParam) && paramArray->count != arguments->count * 2) || (!TOY_IS_NULL(restParam) && paramArray->count -2 > arguments->count * 2)) {
|
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to a function\n");
|
|
||||||
|
|
||||||
//free, and skip out
|
|
||||||
Toy_popScope(inner.scope);
|
|
||||||
|
|
||||||
Toy_freeLiteralArray(&inner.stack);
|
|
||||||
Toy_freeLiteralArray(&inner.literalCache);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//BUGFIX: access the arguments from the beginning
|
|
||||||
int argumentIndex = 0;
|
|
||||||
|
|
||||||
//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
|
|
||||||
//declare and define each entry in the scope
|
|
||||||
if (!Toy_declareScopeVariable(inner.scope, paramArray->literals[i], paramArray->literals[i + 1])) {
|
|
||||||
interpreter->errorOutput("[internal] Could not re-declare parameter\n");
|
|
||||||
|
|
||||||
//free, and skip out
|
|
||||||
Toy_popScope(inner.scope);
|
|
||||||
|
|
||||||
Toy_freeLiteralArray(&inner.stack);
|
|
||||||
Toy_freeLiteralArray(&inner.literalCache);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//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;
|
|
||||||
if (TOY_IS_IDENTIFIER(arg) && Toy_parseIdentifierToValue(interpreter, &arg)) {
|
|
||||||
Toy_freeLiteral(argIdn);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Toy_setScopeVariable(inner.scope, paramArray->literals[i], arg, false)) {
|
|
||||||
interpreter->errorOutput("[internal] Could not define parameter (bad type?)\n");
|
|
||||||
|
|
||||||
//free, and skip out
|
|
||||||
Toy_freeLiteral(arg);
|
|
||||||
Toy_popScope(inner.scope);
|
|
||||||
|
|
||||||
Toy_freeLiteralArray(&inner.stack);
|
|
||||||
Toy_freeLiteralArray(&inner.literalCache);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Toy_freeLiteral(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if using rest, pack the optional extra arguments into the rest parameter (array)
|
|
||||||
if (!TOY_IS_NULL(restParam)) {
|
|
||||||
Toy_LiteralArray rest;
|
|
||||||
Toy_initLiteralArray(&rest);
|
|
||||||
|
|
||||||
//access the arguments in order
|
|
||||||
while (argumentIndex < arguments->count) {
|
|
||||||
Toy_Literal lit = Toy_copyLiteral(arguments->literals[argumentIndex++]);
|
|
||||||
Toy_pushLiteralArray(&rest, lit);
|
|
||||||
Toy_freeLiteral(lit);
|
|
||||||
}
|
|
||||||
|
|
||||||
Toy_Literal restType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_ARRAY, true);
|
|
||||||
Toy_Literal any = TOY_TO_TYPE_LITERAL(TOY_LITERAL_ANY, false);
|
|
||||||
TOY_TYPE_PUSH_SUBTYPE(&restType, any);
|
|
||||||
|
|
||||||
//declare & define the rest parameter
|
|
||||||
if (!Toy_declareScopeVariable(inner.scope, restParam, restType)) {
|
|
||||||
interpreter->errorOutput("[internal] Could not declare rest parameter\n");
|
|
||||||
|
|
||||||
//free, and skip out
|
|
||||||
Toy_freeLiteral(restType);
|
|
||||||
Toy_freeLiteralArray(&rest);
|
|
||||||
Toy_popScope(inner.scope);
|
|
||||||
|
|
||||||
Toy_freeLiteralArray(&inner.stack);
|
|
||||||
Toy_freeLiteralArray(&inner.literalCache);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toy_Literal lit = TOY_TO_ARRAY_LITERAL(&rest);
|
|
||||||
if (!Toy_setScopeVariable(inner.scope, restParam, lit, false)) {
|
|
||||||
interpreter->errorOutput("[internal] Could not define rest parameter\n");
|
|
||||||
|
|
||||||
//free, and skip out
|
|
||||||
Toy_freeLiteral(restType);
|
|
||||||
Toy_freeLiteral(lit);
|
|
||||||
Toy_popScope(inner.scope);
|
|
||||||
|
|
||||||
Toy_freeLiteralArray(&inner.stack);
|
|
||||||
Toy_freeLiteralArray(&inner.literalCache);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toy_freeLiteral(restType);
|
|
||||||
Toy_freeLiteralArray(&rest);
|
|
||||||
}
|
|
||||||
|
|
||||||
//execute the interpreter
|
|
||||||
execInterpreter(&inner);
|
|
||||||
|
|
||||||
//adopt the panic state
|
|
||||||
interpreter->panic = inner.panic;
|
|
||||||
|
|
||||||
//accept the stack as the results
|
|
||||||
Toy_LiteralArray returnsFromInner;
|
|
||||||
Toy_initLiteralArray(&returnsFromInner);
|
|
||||||
|
|
||||||
//unpack the results
|
|
||||||
for (int i = 0; i < (returnArray->count || 1); i++) {
|
|
||||||
Toy_Literal lit = Toy_popLiteralArray(&inner.stack);
|
|
||||||
Toy_pushLiteralArray(&returnsFromInner, lit); //NOTE: also reverses the order
|
|
||||||
Toy_freeLiteral(lit);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool returnValue = true;
|
|
||||||
|
|
||||||
//TODO: remove this when multiple assignment is enabled - note the BUGFIX that balances the stack
|
|
||||||
if (returnsFromInner.count > 1) {
|
|
||||||
interpreter->errorOutput("Too many values returned (multiple returns not yet supported)\n");
|
|
||||||
|
|
||||||
returnValue = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < returnsFromInner.count && returnValue; i++) {
|
|
||||||
Toy_Literal ret = Toy_popLiteralArray(&returnsFromInner);
|
|
||||||
|
|
||||||
//check the return types
|
|
||||||
if (returnArray->count > 0 && TOY_AS_TYPE(returnArray->literals[i]).typeOf != ret.type) {
|
|
||||||
interpreter->errorOutput("Bad type found in return value\n");
|
|
||||||
|
|
||||||
//free, and skip out
|
|
||||||
returnValue = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toy_pushLiteralArray(returns, ret); //NOTE: reverses again
|
|
||||||
Toy_freeLiteral(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
//manual free
|
|
||||||
//BUGFIX: handle scopes of functions, which refer to the parent scope (leaking memory)
|
|
||||||
while(inner.scope != TOY_AS_FUNCTION(func).scope) {
|
|
||||||
for (int i = 0; i < inner.scope->variables.capacity; i++) {
|
|
||||||
//handle keys, just in case
|
|
||||||
if (TOY_IS_FUNCTION(inner.scope->variables.entries[i].key)) {
|
|
||||||
Toy_popScope(TOY_AS_FUNCTION(inner.scope->variables.entries[i].key).scope);
|
|
||||||
TOY_AS_FUNCTION(inner.scope->variables.entries[i].key).scope = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TOY_IS_FUNCTION(inner.scope->variables.entries[i].value)) {
|
|
||||||
Toy_popScope(TOY_AS_FUNCTION(inner.scope->variables.entries[i].value).scope);
|
|
||||||
TOY_AS_FUNCTION(inner.scope->variables.entries[i].value).scope = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner.scope = Toy_popScope(inner.scope);
|
|
||||||
}
|
|
||||||
Toy_freeLiteralArray(&returnsFromInner);
|
|
||||||
Toy_freeLiteralArray(&inner.stack);
|
|
||||||
Toy_freeLiteralArray(&inner.literalCache);
|
|
||||||
|
|
||||||
//BUGFIX: this function needs to eat the arguments
|
|
||||||
Toy_freeLiteralArray(arguments);
|
|
||||||
|
|
||||||
//actual bytecode persists until next call
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Toy_callFn(Toy_Interpreter* interpreter, const char* name, Toy_LiteralArray* arguments, Toy_LiteralArray* returns) {
|
|
||||||
Toy_Literal key = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefStringLength(name, strlen(name)));
|
|
||||||
Toy_Literal val = TOY_TO_NULL_LITERAL;
|
|
||||||
|
|
||||||
if (!Toy_isDeclaredScopeVariable(interpreter->scope, key)) {
|
|
||||||
interpreter->errorOutput("No function with that name\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toy_getScopeVariable(interpreter->scope, key, &val);
|
|
||||||
|
|
||||||
bool ret = Toy_callLiteralFn(interpreter, val, arguments, returns);
|
|
||||||
|
|
||||||
Toy_freeLiteral(key);
|
|
||||||
Toy_freeLiteral(val);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool execFnReturn(Toy_Interpreter* interpreter) {
|
static bool execFnReturn(Toy_Interpreter* interpreter) {
|
||||||
Toy_LiteralArray returns;
|
Toy_LiteralArray returns;
|
||||||
Toy_initLiteralArray(&returns);
|
Toy_initLiteralArray(&returns);
|
||||||
@@ -1496,7 +1238,7 @@ static bool execFnReturn(Toy_Interpreter* interpreter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_IS_ARRAY(lit) || TOY_IS_DICTIONARY(lit)) {
|
if (TOY_IS_ARRAY(lit) || TOY_IS_DICTIONARY(lit)) {
|
||||||
Toy_parseCompoundToPureValues(interpreter, &lit);
|
Toy_parseCompoundToValue(interpreter, &lit);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_pushLiteralArray(&returns, lit); //reverses the order
|
Toy_pushLiteralArray(&returns, lit); //reverses the order
|
||||||
@@ -1639,7 +1381,13 @@ static bool execIndex(Toy_Interpreter* interpreter, bool assignIntermediate) {
|
|||||||
static bool execIndexAssign(Toy_Interpreter* interpreter, int assignDepth) {
|
static bool execIndexAssign(Toy_Interpreter* interpreter, int assignDepth) {
|
||||||
//assume -> compound, first, second, third, assign are all on the stack
|
//assume -> compound, first, second, third, assign are all on the stack
|
||||||
|
|
||||||
Toy_Literal assign = TOY_TO_NULL_LITERAL, third = TOY_TO_NULL_LITERAL, second = TOY_TO_NULL_LITERAL, first = TOY_TO_NULL_LITERAL, compound = TOY_TO_NULL_LITERAL, result = TOY_TO_NULL_LITERAL;
|
Toy_Literal assign = TOY_TO_NULL_LITERAL;
|
||||||
|
Toy_Literal third = TOY_TO_NULL_LITERAL;
|
||||||
|
Toy_Literal second = TOY_TO_NULL_LITERAL;
|
||||||
|
Toy_Literal first = TOY_TO_NULL_LITERAL;
|
||||||
|
Toy_Literal compound = TOY_TO_NULL_LITERAL;
|
||||||
|
Toy_Literal result = TOY_TO_NULL_LITERAL;
|
||||||
|
|
||||||
Toy_Literal compoundIdn = TOY_TO_NULL_LITERAL;
|
Toy_Literal compoundIdn = TOY_TO_NULL_LITERAL;
|
||||||
bool freeIdn = false;
|
bool freeIdn = false;
|
||||||
|
|
||||||
@@ -1840,7 +1588,7 @@ static void execInterpreter(Toy_Interpreter* interpreter) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_OP_LITERAL_RAW:
|
case TOY_OP_LITERAL_RAW:
|
||||||
if (!rawLiteral(interpreter)) {
|
if (!execRawLiteral(interpreter)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1866,11 +1614,13 @@ static void execInterpreter(Toy_Interpreter* interpreter) {
|
|||||||
case TOY_OP_VAR_MULTIPLICATION_ASSIGN:
|
case TOY_OP_VAR_MULTIPLICATION_ASSIGN:
|
||||||
case TOY_OP_VAR_DIVISION_ASSIGN:
|
case TOY_OP_VAR_DIVISION_ASSIGN:
|
||||||
case TOY_OP_VAR_MODULO_ASSIGN:
|
case TOY_OP_VAR_MODULO_ASSIGN:
|
||||||
execVarArithmeticAssign(interpreter);
|
execVarArithmeticAssignInterjection(interpreter); //hang on, let me just prep this first
|
||||||
|
|
||||||
if (!execArithmetic(interpreter, opcode)) {
|
if (!execArithmetic(interpreter, opcode)) {
|
||||||
Toy_freeLiteral(Toy_popLiteralArray(&interpreter->stack));
|
Toy_freeLiteral(Toy_popLiteralArray(&interpreter->stack)); //remove the extra identifier if this went south
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!execVarAssign(interpreter)) {
|
if (!execVarAssign(interpreter)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1881,6 +1631,7 @@ static void execInterpreter(Toy_Interpreter* interpreter) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_OP_GROUPING_END:
|
case TOY_OP_GROUPING_END:
|
||||||
|
//And so doeth, yeet thine operation upwards
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//scope
|
//scope
|
||||||
@@ -1987,7 +1738,7 @@ static void execInterpreter(Toy_Interpreter* interpreter) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_OP_IF_FALSE_JUMP:
|
case TOY_OP_IF_FALSE_JUMP:
|
||||||
if (!execFalseJump(interpreter)) {
|
if (!execJumpIfFalse(interpreter)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2456,3 +2207,272 @@ void Toy_freeInterpreter(Toy_Interpreter* interpreter) {
|
|||||||
|
|
||||||
interpreter->hooks = NULL;
|
interpreter->hooks = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//for function calls
|
||||||
|
bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_LiteralArray* arguments, Toy_LiteralArray* returns) {
|
||||||
|
//check for side-loaded native functions
|
||||||
|
if (TOY_IS_FUNCTION_NATIVE(func)) {
|
||||||
|
//TODO: parse out identifier values, see issue #64
|
||||||
|
|
||||||
|
//call the native function
|
||||||
|
int returnsCount = TOY_AS_FUNCTION_NATIVE(func)(interpreter, arguments);
|
||||||
|
|
||||||
|
if (returnsCount < 0) {
|
||||||
|
// interpreter->errorOutput("Unknown error from native function\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the results
|
||||||
|
Toy_LiteralArray returnsFromInner;
|
||||||
|
Toy_initLiteralArray(&returnsFromInner);
|
||||||
|
|
||||||
|
for (int i = 0; i < (returnsCount || 1); i++) {
|
||||||
|
Toy_Literal lit = Toy_popLiteralArray(&interpreter->stack);
|
||||||
|
Toy_pushLiteralArray(&returnsFromInner, lit); //NOTE: also reverses the order
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
//flip them around and pass to returns
|
||||||
|
while (returnsFromInner.count > 0) {
|
||||||
|
Toy_Literal lit = Toy_popLiteralArray(&returnsFromInner);
|
||||||
|
Toy_pushLiteralArray(returns, lit);
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&returnsFromInner);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//normal Toy function
|
||||||
|
if (!TOY_IS_FUNCTION(func)) {
|
||||||
|
interpreter->errorOutput("Function literal required in Toy_callLiteralFn()\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//set up a new interpreter
|
||||||
|
Toy_Interpreter inner;
|
||||||
|
|
||||||
|
//init the inner interpreter manually
|
||||||
|
Toy_initLiteralArray(&inner.literalCache);
|
||||||
|
inner.scope = Toy_pushScope(func.as.function.scope);
|
||||||
|
inner.bytecode = ((Toy_RefFunction*)(TOY_AS_FUNCTION(func).inner.ptr))->data;
|
||||||
|
inner.length = ((Toy_RefFunction*)(TOY_AS_FUNCTION(func).inner.ptr))->length;
|
||||||
|
inner.count = 0;
|
||||||
|
inner.codeStart = -1;
|
||||||
|
inner.depth = interpreter->depth + 1;
|
||||||
|
inner.panic = false;
|
||||||
|
Toy_initLiteralArray(&inner.stack);
|
||||||
|
inner.hooks = interpreter->hooks;
|
||||||
|
Toy_setInterpreterPrint(&inner, interpreter->printOutput);
|
||||||
|
Toy_setInterpreterAssert(&inner, interpreter->assertOutput);
|
||||||
|
Toy_setInterpreterError(&inner, interpreter->errorOutput);
|
||||||
|
|
||||||
|
//prep the sections
|
||||||
|
readInterpreterSections(&inner);
|
||||||
|
|
||||||
|
//prep the arguments
|
||||||
|
Toy_LiteralArray* paramArray = TOY_AS_ARRAY(inner.literalCache.literals[ readShort(inner.bytecode, &inner.count) ]);
|
||||||
|
Toy_LiteralArray* returnArray = TOY_AS_ARRAY(inner.literalCache.literals[ readShort(inner.bytecode, &inner.count) ]);
|
||||||
|
|
||||||
|
//get the rest param, if it exists
|
||||||
|
Toy_Literal restParam = TOY_TO_NULL_LITERAL;
|
||||||
|
if (paramArray->count >= 2 && TOY_AS_TYPE(paramArray->literals[ paramArray->count -1 ]).typeOf == TOY_LITERAL_FUNCTION_ARG_REST) {
|
||||||
|
restParam = paramArray->literals[ paramArray->count -2 ];
|
||||||
|
}
|
||||||
|
|
||||||
|
//check the param total is correct
|
||||||
|
if ((TOY_IS_NULL(restParam) && paramArray->count != arguments->count * 2) || (!TOY_IS_NULL(restParam) && paramArray->count -2 > arguments->count * 2)) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments passed to a function\n");
|
||||||
|
|
||||||
|
//free, and skip out
|
||||||
|
Toy_popScope(inner.scope);
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&inner.stack);
|
||||||
|
Toy_freeLiteralArray(&inner.literalCache);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//BUGFIX: access the arguments from the beginning
|
||||||
|
int argumentIndex = 0;
|
||||||
|
|
||||||
|
//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
|
||||||
|
//declare and define each entry in the scope
|
||||||
|
if (!Toy_declareScopeVariable(inner.scope, paramArray->literals[i], paramArray->literals[i + 1])) {
|
||||||
|
interpreter->errorOutput("[internal] Could not re-declare parameter\n");
|
||||||
|
|
||||||
|
//free, and skip out
|
||||||
|
Toy_popScope(inner.scope);
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&inner.stack);
|
||||||
|
Toy_freeLiteralArray(&inner.literalCache);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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;
|
||||||
|
if (TOY_IS_IDENTIFIER(arg) && Toy_parseIdentifierToValue(interpreter, &arg)) {
|
||||||
|
Toy_freeLiteral(argIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Toy_setScopeVariable(inner.scope, paramArray->literals[i], arg, false)) {
|
||||||
|
interpreter->errorOutput("[internal] Could not define parameter (bad type?)\n");
|
||||||
|
|
||||||
|
//free, and skip out
|
||||||
|
Toy_freeLiteral(arg);
|
||||||
|
Toy_popScope(inner.scope);
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&inner.stack);
|
||||||
|
Toy_freeLiteralArray(&inner.literalCache);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Toy_freeLiteral(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if using rest, pack the optional extra arguments into the rest parameter (array)
|
||||||
|
if (!TOY_IS_NULL(restParam)) {
|
||||||
|
Toy_LiteralArray rest;
|
||||||
|
Toy_initLiteralArray(&rest);
|
||||||
|
|
||||||
|
//access the arguments in order
|
||||||
|
while (argumentIndex < arguments->count) {
|
||||||
|
Toy_Literal lit = Toy_copyLiteral(arguments->literals[argumentIndex++]);
|
||||||
|
Toy_pushLiteralArray(&rest, lit);
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal restType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_ARRAY, true);
|
||||||
|
Toy_Literal any = TOY_TO_TYPE_LITERAL(TOY_LITERAL_ANY, false);
|
||||||
|
TOY_TYPE_PUSH_SUBTYPE(&restType, any);
|
||||||
|
|
||||||
|
//declare & define the rest parameter
|
||||||
|
if (!Toy_declareScopeVariable(inner.scope, restParam, restType)) {
|
||||||
|
interpreter->errorOutput("[internal] Could not declare rest parameter\n");
|
||||||
|
|
||||||
|
//free, and skip out
|
||||||
|
Toy_freeLiteral(restType);
|
||||||
|
Toy_freeLiteralArray(&rest);
|
||||||
|
Toy_popScope(inner.scope);
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&inner.stack);
|
||||||
|
Toy_freeLiteralArray(&inner.literalCache);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal lit = TOY_TO_ARRAY_LITERAL(&rest);
|
||||||
|
if (!Toy_setScopeVariable(inner.scope, restParam, lit, false)) {
|
||||||
|
interpreter->errorOutput("[internal] Could not define rest parameter\n");
|
||||||
|
|
||||||
|
//free, and skip out
|
||||||
|
Toy_freeLiteral(restType);
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
Toy_popScope(inner.scope);
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&inner.stack);
|
||||||
|
Toy_freeLiteralArray(&inner.literalCache);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteral(restType);
|
||||||
|
Toy_freeLiteralArray(&rest);
|
||||||
|
}
|
||||||
|
|
||||||
|
//execute the interpreter
|
||||||
|
execInterpreter(&inner);
|
||||||
|
|
||||||
|
//adopt the panic state
|
||||||
|
interpreter->panic = inner.panic;
|
||||||
|
|
||||||
|
//accept the stack as the results
|
||||||
|
Toy_LiteralArray returnsFromInner;
|
||||||
|
Toy_initLiteralArray(&returnsFromInner);
|
||||||
|
|
||||||
|
//unpack the results
|
||||||
|
for (int i = 0; i < (returnArray->count || 1); i++) {
|
||||||
|
Toy_Literal lit = Toy_popLiteralArray(&inner.stack);
|
||||||
|
Toy_pushLiteralArray(&returnsFromInner, lit); //NOTE: also reverses the order
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool returnValue = true;
|
||||||
|
|
||||||
|
//TODO: remove this when multiple assignment is enabled - note the BUGFIX that balances the stack
|
||||||
|
if (returnsFromInner.count > 1) {
|
||||||
|
interpreter->errorOutput("Too many values returned (multiple returns not yet supported)\n");
|
||||||
|
|
||||||
|
returnValue = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < returnsFromInner.count && returnValue; i++) {
|
||||||
|
Toy_Literal ret = Toy_popLiteralArray(&returnsFromInner);
|
||||||
|
|
||||||
|
//check the return types
|
||||||
|
if (returnArray->count > 0 && TOY_AS_TYPE(returnArray->literals[i]).typeOf != ret.type) {
|
||||||
|
interpreter->errorOutput("Bad type found in return value\n");
|
||||||
|
|
||||||
|
//free, and skip out
|
||||||
|
returnValue = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_pushLiteralArray(returns, ret); //NOTE: reverses again
|
||||||
|
Toy_freeLiteral(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
//manual free
|
||||||
|
//BUGFIX: handle scopes of functions, which refer to the parent scope (leaking memory)
|
||||||
|
while(inner.scope != TOY_AS_FUNCTION(func).scope) {
|
||||||
|
for (int i = 0; i < inner.scope->variables.capacity; i++) {
|
||||||
|
//handle keys, just in case
|
||||||
|
if (TOY_IS_FUNCTION(inner.scope->variables.entries[i].key)) {
|
||||||
|
Toy_popScope(TOY_AS_FUNCTION(inner.scope->variables.entries[i].key).scope);
|
||||||
|
TOY_AS_FUNCTION(inner.scope->variables.entries[i].key).scope = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_IS_FUNCTION(inner.scope->variables.entries[i].value)) {
|
||||||
|
Toy_popScope(TOY_AS_FUNCTION(inner.scope->variables.entries[i].value).scope);
|
||||||
|
TOY_AS_FUNCTION(inner.scope->variables.entries[i].value).scope = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner.scope = Toy_popScope(inner.scope);
|
||||||
|
}
|
||||||
|
Toy_freeLiteralArray(&returnsFromInner);
|
||||||
|
Toy_freeLiteralArray(&inner.stack);
|
||||||
|
Toy_freeLiteralArray(&inner.literalCache);
|
||||||
|
|
||||||
|
//BUGFIX: this function needs to eat the arguments
|
||||||
|
Toy_freeLiteralArray(arguments);
|
||||||
|
|
||||||
|
//actual bytecode persists until next call
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Toy_callFn(Toy_Interpreter* interpreter, const char* name, Toy_LiteralArray* arguments, Toy_LiteralArray* returns) {
|
||||||
|
Toy_Literal key = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefStringLength(name, strlen(name)));
|
||||||
|
Toy_Literal val = TOY_TO_NULL_LITERAL;
|
||||||
|
|
||||||
|
if (!Toy_isDeclaredScopeVariable(interpreter->scope, key)) {
|
||||||
|
interpreter->errorOutput("No function with that name\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_getScopeVariable(interpreter->scope, key, &val);
|
||||||
|
|
||||||
|
bool ret = Toy_callLiteralFn(interpreter, val, arguments, returns);
|
||||||
|
|
||||||
|
Toy_freeLiteral(key);
|
||||||
|
Toy_freeLiteral(val);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
+2
-15
@@ -750,23 +750,10 @@ static Toy_Opcode decrementInfix(Toy_Parser* parser, Toy_ASTNode** nodeHandle) {
|
|||||||
static Toy_Opcode fnCall(Toy_Parser* parser, Toy_ASTNode** nodeHandle) {
|
static Toy_Opcode fnCall(Toy_Parser* parser, Toy_ASTNode** nodeHandle) {
|
||||||
//wait - is the previous token a type? this should be casting instead
|
//wait - is the previous token a type? this should be casting instead
|
||||||
if (parser->previous.type >= TOY_TOKEN_NULL && parser->previous.type <= TOY_TOKEN_ANY) {
|
if (parser->previous.type >= TOY_TOKEN_NULL && parser->previous.type <= TOY_TOKEN_ANY) {
|
||||||
//casting type
|
|
||||||
Toy_ASTNode* lhsNode = NULL;
|
|
||||||
castingPrefix(parser, &lhsNode);
|
|
||||||
advance(parser);
|
|
||||||
|
|
||||||
//casting value
|
//casting value
|
||||||
Toy_ASTNode* rhsNode = NULL;
|
parsePrecedence(parser, nodeHandle, PREC_CALL);
|
||||||
grouping(parser, &rhsNode);
|
|
||||||
|
|
||||||
//emit the cast node
|
return TOY_OP_TYPE_CAST; //opcode value
|
||||||
|
|
||||||
Toy_emitASTNodeBinary(&lhsNode, rhsNode, TOY_OP_TYPE_CAST);
|
|
||||||
|
|
||||||
//pass it off to the caller
|
|
||||||
*nodeHandle = lhsNode;
|
|
||||||
|
|
||||||
return TOY_OP_GROUPING_BEGIN; //dummy value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
advance(parser); //skip the left paren
|
advance(parser); //skip the left paren
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ IDIR +=. ../source ../repl
|
|||||||
CFLAGS +=$(addprefix -I,$(IDIR)) -g -Wall -W -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable
|
CFLAGS +=$(addprefix -I,$(IDIR)) -g -Wall -W -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable
|
||||||
LIBS +=
|
LIBS +=
|
||||||
ODIR = obj
|
ODIR = obj
|
||||||
TARGETS = $(wildcard ../source/*.c) $(wildcard ../repl/lib_*.c) ../repl/repl_tools.c
|
TARGETS = $(wildcard ../source/*.c) $(wildcard ../repl/lib_*.c) ../repl/repl_tools.c ../repl/drive_system.c
|
||||||
TESTS = $(wildcard test_*.c)
|
TESTS = $(wildcard test_*.c)
|
||||||
OBJ = $(addprefix $(ODIR)/,$(TARGETS:../source/%.c=%.o)) $(addprefix $(ODIR)/,$(TESTS:.c=.o))
|
OBJ = $(addprefix $(ODIR)/,$(TARGETS:../source/%.c=%.o)) $(addprefix $(ODIR)/,$(TESTS:.c=.o))
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
//test for casting + grouping, see #67
|
||||||
|
{
|
||||||
|
assert string(10 % 4) == "2", "basic group casting failed";
|
||||||
|
assert string 4 == "4", "normal casting failed";
|
||||||
|
|
||||||
|
assert typeof string(10 % 4) == string, "group casting type failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print "All good";
|
||||||
@@ -101,6 +101,63 @@ import standard;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test sign
|
||||||
|
{
|
||||||
|
assert sign(4) == 1, "sign(int) failed";
|
||||||
|
assert sign(-4) == -1, "sign(-int) failed";
|
||||||
|
assert sign(4.1) == 1, "sign(float) failed";
|
||||||
|
assert sign(-4.1) == -1, "sign(-float) failed";
|
||||||
|
assert sign(0) == 1, "sign(0) failed";
|
||||||
|
|
||||||
|
var x = 4.1;
|
||||||
|
|
||||||
|
assert x.sign() == 1, "var.sign() failed";
|
||||||
|
|
||||||
|
assert typeof sign(1.0) == int, "typeof sign() == int failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test normalize
|
||||||
|
{
|
||||||
|
assert normalize(4) == 1, "normalize(int) failed";
|
||||||
|
assert normalize(-4) == -1, "normalize(-int) failed";
|
||||||
|
assert normalize(4.1) == 1, "normalize(float) failed";
|
||||||
|
assert normalize(-4.1) == -1, "normalize(-float) failed";
|
||||||
|
assert normalize(0) == 0, "normalize(0) failed";
|
||||||
|
|
||||||
|
var x = 4.1;
|
||||||
|
|
||||||
|
assert x.normalize() == 1, "var.normalize() failed";
|
||||||
|
|
||||||
|
assert typeof normalize(1.0) == int, "typeof normalize() == int failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test clamp
|
||||||
|
{
|
||||||
|
assert clamp(1, 0, 5) == 1, "clamp(1, 0, 5) failed";
|
||||||
|
assert clamp(0, 1, 5) == 1, "clamp(0, 1, 5) failed";
|
||||||
|
assert clamp(10, 1, 5) == 5, "clamp(10, 1, 5) failed";
|
||||||
|
|
||||||
|
assert clamp(1.0, 0.0, 5.0) == 1, "clamp(1.0, 0.0, 5.0) failed";
|
||||||
|
assert clamp(0.0, 1.0, 5.0) == 1, "clamp(0.0, 1.0, 5.0) failed";
|
||||||
|
assert clamp(10.0, 1.0, 5.0) == 5, "clamp(10.0, 1.0, 5.0) failed";
|
||||||
|
|
||||||
|
assert typeof clamp(10, 1, 5) == int, "typeof clamp(10, 1, 5) == int failed";
|
||||||
|
assert typeof clamp(10.0, 1, 5) == int, "typeof clamp(10.0, 1, 5) == int failed";
|
||||||
|
assert typeof clamp(10, 1, 5.0) == float, "typeof clamp(10, 1, 5.0) == float failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test lerp
|
||||||
|
{
|
||||||
|
assert lerp(0, 10, 0.5) == 5, "lerp 50% failed";
|
||||||
|
assert lerp(0, 10, 1.5) == 15, "lerp 150% failed";
|
||||||
|
|
||||||
|
assert typeof lerp(0, 10, 0) == float, "typeof lerp result failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//test concat
|
//test concat
|
||||||
{
|
{
|
||||||
//test array concat
|
//test array concat
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import about as about;
|
import toy_version_info as toy_version_info;
|
||||||
import about;
|
import toy_version_info;
|
||||||
|
|
||||||
assert author == "Kayne Ruse, KR Game Studios", "Author failed";
|
assert author == "Kayne Ruse, KR Game Studios", "Author failed";
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "toy_drive_system.h"
|
#include "drive_system.h"
|
||||||
|
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ int main() {
|
|||||||
"dottify-bugfix.toy",
|
"dottify-bugfix.toy",
|
||||||
"function-within-function-bugfix.toy",
|
"function-within-function-bugfix.toy",
|
||||||
"functions.toy",
|
"functions.toy",
|
||||||
|
"group-casting-bugfix.toy",
|
||||||
"increment-postfix-bugfix.toy",
|
"increment-postfix-bugfix.toy",
|
||||||
"index-arrays.toy",
|
"index-arrays.toy",
|
||||||
"index-assignment-both-bugfix.toy",
|
"index-assignment-both-bugfix.toy",
|
||||||
|
|||||||
@@ -6,18 +6,18 @@
|
|||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
#include "toy_memory.h"
|
#include "toy_memory.h"
|
||||||
#include "toy_drive_system.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../repl/repl_tools.h"
|
#include "../repl/repl_tools.h"
|
||||||
|
#include "../repl/drive_system.h"
|
||||||
|
|
||||||
#include "../repl/lib_about.h"
|
#include "../repl/lib_toy_version_info.h"
|
||||||
|
#include "../repl/lib_standard.h"
|
||||||
#include "../repl/lib_random.h"
|
#include "../repl/lib_random.h"
|
||||||
#include "../repl/lib_runner.h"
|
#include "../repl/lib_runner.h"
|
||||||
#include "../repl/lib_standard.h"
|
|
||||||
|
|
||||||
//supress the print output
|
//supress the print output
|
||||||
static void noPrintFn(const char* output) {
|
static void noPrintFn(const char* output) {
|
||||||
@@ -72,7 +72,7 @@ int main() {
|
|||||||
//run each file in test/scripts
|
//run each file in test/scripts
|
||||||
Payload payloads[] = {
|
Payload payloads[] = {
|
||||||
{"interactions.toy", "standard", Toy_hookStandard}, //interactions needs standard
|
{"interactions.toy", "standard", Toy_hookStandard}, //interactions needs standard
|
||||||
{"about.toy", "about", Toy_hookAbout},
|
{"toy_version_info.toy", "toy_version_info", Toy_hookToyVersionInfo},
|
||||||
{"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},
|
{"random.toy", "random", Toy_hookRandom},
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
//changing of the guard - made for @hyperiondev's microcontrollers
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
std::string convert(std::string str) {
|
||||||
|
str = str.substr(str.find_last_of("\\/")+1);
|
||||||
|
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
|
||||||
|
std::replace(str.begin(), str.end(), '.', '_');
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string convertToGuardStart(std::string str) {
|
||||||
|
str = convert(str);
|
||||||
|
return "#ifndef " + str + "\n#define " + str + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string convertToGuardEnd(std::string str) {
|
||||||
|
str = convert(str);
|
||||||
|
return "\n#endif //" + str + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
if (argc <= 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int fileCounter = 1; fileCounter < argc; fileCounter++) {
|
||||||
|
std::ifstream is; //input stream
|
||||||
|
std::string buffer; //store output file
|
||||||
|
|
||||||
|
//open
|
||||||
|
is.open(argv[fileCounter]);
|
||||||
|
if (!is.is_open()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!is.eof()) {
|
||||||
|
std::string top; //I dislike C++
|
||||||
|
getline(is, top);
|
||||||
|
|
||||||
|
//check for pragma guard
|
||||||
|
if (top == "#pragma once") {
|
||||||
|
top = convertToGuardStart(argv[fileCounter]);
|
||||||
|
getline(is, buffer, '\0');
|
||||||
|
buffer += convertToGuardEnd(argv[fileCounter]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
top += "\n";
|
||||||
|
getline(is, buffer, '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = top + buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
//finally
|
||||||
|
is.close();
|
||||||
|
|
||||||
|
std::ofstream os;
|
||||||
|
|
||||||
|
os.open(argv[fileCounter]);
|
||||||
|
if (!os.is_open()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
os << buffer;
|
||||||
|
|
||||||
|
os.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user