Compare commits

..

13 Commits

Author SHA1 Message Date
Kayne Ruse eb8e522bf2 Merged standard and timer, resolved #48 2023-02-13 13:58:41 +00:00
Kayne Ruse 16b71ba6f4 Implemented quicksort in _sort() 2023-02-13 13:31:58 +00:00
Kayne Ruse 9725f3c6a3 Patched some very obscure bugs 2023-02-12 16:54:44 +00:00
Kayne Ruse 8653a2663f Added _indexOf 2023-02-12 14:32:26 +00:00
Kayne Ruse ab2cd5dc93 Removed lib timer properly, see #62 2023-02-12 14:19:14 +00:00
Kayne Ruse 724804a78a Playing with level.toy 2023-02-11 15:27:23 +00:00
Kayne Ruse 77a128e0f7 Added the -t option to the repl 2023-02-11 14:51:19 +00:00
Kayne Ruse 5343e1054d Straightened out file extensions 2023-02-11 14:26:55 +00:00
Kayne Ruse 3930ec0477 Tweaked README.md 2023-02-11 06:48:16 +00:00
Kayne Ruse 996744d7ec Resolved #59 2023-02-11 05:10:32 +00:00
Kayne Ruse c00b32017b Dummied out lib timer 2023-02-11 01:42:44 +00:00
Kayne Ruse 457014d577 Added MSVC build support, likely broke tests 2023-02-11 00:49:21 +00:00
Kayne Ruse be4cbf1ad6 Pack 'em up! 2023-02-10 21:53:38 +00:00
37 changed files with 2555 additions and 2376 deletions
+4 -3
View File
@@ -1,6 +1,4 @@
#Editor generated files
*.sln
*.vcproj
*.suo
*.ncb
*.user
@@ -13,7 +11,9 @@ Out/
release/
debug/
out/
bin/
.cache/
.vs/
#Project generated files
*.db
@@ -22,9 +22,10 @@ out/
*.exe
*.meta
*.log
out
*.out
*.stackdump
*.tb
*.filters
#Shell files
*.bat
+3 -1
View File
@@ -23,7 +23,9 @@ Special thanks to http://craftinginterpreters.com/ for their fantastic book that
For Windows(mingw32 & cygwin), Linux and MacOS, simply run `make` in the root directory.
Note: MacOS is not officially supported (no machines for testing), but we'll do our best!
For Windows(MSVC), Visual Studio project files are included.
Note: MacOS and Windows(MSVC) are not officially supported, but we'll do our best!
## Tools
+133
View File
@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{97F823E5-3AB8-47EF-B142-C15DD7CADF76}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IgnoreImportLibrary>false</IgnoreImportLibrary>
<OutDir>$(SolutionDir)out\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
<AdditionalDependencies>Toy.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)out\$(Configuration)</AdditionalLibraryDirectories>
</Link>
<ClCompile>
<AdditionalIncludeDirectories>C:\Users\kayne\Desktop\Toy\source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="repl\lib_about.c" />
<ClCompile Include="repl\lib_compound.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_compound.h" />
<ClInclude Include="repl\lib_runner.h" />
<ClInclude Include="repl\lib_standard.h" />
<ClInclude Include="repl\repl_tools.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+148
View File
@@ -0,0 +1,148 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{26360002-CC2A-469A-9B28-BA0C1AF41657}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)out\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TOY_EXPORTS;TOY_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;TOY_EXPORTS;TOY_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>TOY_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="source\toy_ast_node.c" />
<ClCompile Include="source\toy_builtin.c" />
<ClCompile Include="source\toy_common.c" />
<ClCompile Include="source\toy_compiler.c" />
<ClCompile Include="source\toy_interpreter.c" />
<ClCompile Include="source\toy_keyword_types.c" />
<ClCompile Include="source\toy_lexer.c" />
<ClCompile Include="source\toy_literal.c" />
<ClCompile Include="source\toy_literal_array.c" />
<ClCompile Include="source\toy_literal_dictionary.c" />
<ClCompile Include="source\toy_memory.c" />
<ClCompile Include="source\toy_parser.c" />
<ClCompile Include="source\toy_refstring.c" />
<ClCompile Include="source\toy_scope.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="source\toy_ast_node.h" />
<ClInclude Include="source\toy_builtin.h" />
<ClInclude Include="source\toy_common.h" />
<ClInclude Include="source\toy_compiler.h" />
<ClInclude Include="source\toy_console_colors.h" />
<ClInclude Include="source\toy_interpreter.h" />
<ClInclude Include="source\toy_keyword_types.h" />
<ClInclude Include="source\toy_lexer.h" />
<ClInclude Include="source\toy_literal.h" />
<ClInclude Include="source\toy_literal_array.h" />
<ClInclude Include="source\toy_literal_dictionary.h" />
<ClInclude Include="source\toy_memory.h" />
<ClInclude Include="source\toy_opcodes.h" />
<ClInclude Include="source\toy_parser.h" />
<ClInclude Include="source\toy_refstring.h" />
<ClInclude Include="source\toy_scope.h" />
<ClInclude Include="source\toy_token_types.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+44
View File
@@ -0,0 +1,44 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33213.308
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Toy", "Toy.vcxproj", "{26360002-CC2A-469A-9B28-BA0C1AF41657}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Repl", "Repl.vcxproj", "{97F823E5-3AB8-47EF-B142-C15DD7CADF76}"
ProjectSection(ProjectDependencies) = postProject
{26360002-CC2A-469A-9B28-BA0C1AF41657} = {26360002-CC2A-469A-9B28-BA0C1AF41657}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{26360002-CC2A-469A-9B28-BA0C1AF41657}.Debug|x64.ActiveCfg = Debug|x64
{26360002-CC2A-469A-9B28-BA0C1AF41657}.Debug|x64.Build.0 = Debug|x64
{26360002-CC2A-469A-9B28-BA0C1AF41657}.Debug|x86.ActiveCfg = Debug|Win32
{26360002-CC2A-469A-9B28-BA0C1AF41657}.Debug|x86.Build.0 = Debug|Win32
{26360002-CC2A-469A-9B28-BA0C1AF41657}.Release|x64.ActiveCfg = Release|x64
{26360002-CC2A-469A-9B28-BA0C1AF41657}.Release|x64.Build.0 = Release|x64
{26360002-CC2A-469A-9B28-BA0C1AF41657}.Release|x86.ActiveCfg = Release|Win32
{26360002-CC2A-469A-9B28-BA0C1AF41657}.Release|x86.Build.0 = Release|Win32
{97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Debug|x64.ActiveCfg = Debug|x64
{97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Debug|x64.Build.0 = Debug|x64
{97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Debug|x86.ActiveCfg = Debug|Win32
{97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Debug|x86.Build.0 = Debug|Win32
{97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Release|x64.ActiveCfg = Release|x64
{97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Release|x64.Build.0 = Release|x64
{97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Release|x86.ActiveCfg = Release|Win32
{97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7089F1AD-8EC0-4F27-AFD1-5FD43D91AABC}
EndGlobalSection
EndGlobal
+2 -2
View File
@@ -10,10 +10,10 @@ all: $(TOY_OUTDIR) repl
#repl builds
repl: $(TOY_OUTDIR) library
$(MAKE) -C repl
$(MAKE) -j8 -C repl
repl-static: $(TOY_OUTDIR) static
$(MAKE) -C repl
$(MAKE) -j8 -C repl
repl-release: clean $(TOY_OUTDIR) library-release
$(MAKE) -C repl release
-1468
View File
File diff suppressed because it is too large Load Diff
-6
View File
@@ -1,6 +0,0 @@
#pragma once
#include "toy_interpreter.h"
int Toy_hookCompound(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
+5 -5
View File
@@ -44,7 +44,7 @@ static int nativeLoadScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argu
//use raw types - easier
const char* filePath = Toy_toCString(TOY_AS_STRING(filePathLiteral));
int filePathLength = Toy_lengthRefString(TOY_AS_STRING(filePathLiteral));
size_t filePathLength = Toy_lengthRefString(TOY_AS_STRING(filePathLiteral));
//load and compile the bytecode
size_t fileSize = 0;
@@ -138,7 +138,7 @@ static int nativeLoadScriptBytecode(Toy_Interpreter* interpreter, Toy_LiteralArr
//get the final real file path (concat) TODO: move this concat to refstring library
Toy_RefString* realDrive = Toy_copyRefString(TOY_AS_STRING(realDriveLiteral));
int realLength = Toy_lengthRefString(realDrive) + Toy_lengthRefString(path);
size_t realLength = Toy_lengthRefString(realDrive) + Toy_lengthRefString(path);
char* filePath = TOY_ALLOCATE(char, realLength + 1); //+1 for null
snprintf(filePath, realLength, "%s%s", Toy_toCString(realDrive), Toy_toCString(path));
@@ -159,7 +159,7 @@ static int nativeLoadScriptBytecode(Toy_Interpreter* interpreter, Toy_LiteralArr
}
//check for break-out attempts
for (int i = 0; i < realLength - 1; i++) {
for (size_t i = 0; i < realLength - 1; i++) {
if (filePath[i] == '.' && filePath[i + 1] == '.') {
interpreter->errorOutput("Parent directory access not allowed\n");
TOY_FREE_ARRAY(char, filePath, realLength);
@@ -617,7 +617,7 @@ Toy_Literal Toy_getFilePathLiteral(Toy_Interpreter* interpreter, Toy_Literal* dr
//get the final real file path (concat) TODO: move this concat to refstring library
Toy_RefString* realDrive = Toy_copyRefString(TOY_AS_STRING(realDriveLiteral));
int realLength = Toy_lengthRefString(realDrive) + Toy_lengthRefString(path);
size_t realLength = Toy_lengthRefString(realDrive) + Toy_lengthRefString(path);
char* filePath = TOY_ALLOCATE(char, realLength + 1); //+1 for null
snprintf(filePath, realLength, "%s%s", Toy_toCString(realDrive), Toy_toCString(path));
@@ -630,7 +630,7 @@ Toy_Literal Toy_getFilePathLiteral(Toy_Interpreter* interpreter, Toy_Literal* dr
Toy_deleteRefString(drivePath);
//check for break-out attempts
for (int i = 0; i < realLength - 1; i++) {
for (size_t i = 0; i < realLength - 1; i++) {
if (filePath[i] == '.' && filePath[i + 1] == '.') {
interpreter->errorOutput("Parent directory access not allowed\n");
TOY_FREE_ARRAY(char, filePath, realLength + 1);
+1538 -2
View File
File diff suppressed because it is too large Load Diff
-411
View File
@@ -1,411 +0,0 @@
#include "lib_timer.h"
#include "toy_memory.h"
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
//GOD DAMN IT: https://stackoverflow.com/questions/15846762/timeval-subtract-explanation
static int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) {
//normallize
if (x->tv_usec > 999999) {
x->tv_sec += x->tv_usec / 1000000;
x->tv_usec %= 1000000;
}
if (y->tv_usec > 999999) {
y->tv_sec += y->tv_usec / 1000000;
y->tv_usec %= 1000000;
}
//calc
result->tv_sec = x->tv_sec - y->tv_sec;
if ((result->tv_usec = x->tv_usec - y->tv_usec) < 0) {
if (result->tv_sec != 0) { //only works far from 0
result->tv_usec += 1000000;
result->tv_sec--; // borrow
}
}
return result->tv_sec < 0 || (result->tv_sec == 0 && result->tv_usec < 0);
}
//god damn it
static struct timeval* diff(struct timeval* lhs, struct timeval* rhs) {
struct timeval* d = TOY_ALLOCATE(struct timeval, 1);
//I gave up, copied from SO
timeval_subtract(d, rhs, lhs);
return d;
}
//callbacks
static int nativeStartTimer(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 0) {
interpreter->errorOutput("Incorrect number of arguments to startTimer\n");
return -1;
}
//get the timeinfo from C
struct timeval* timeinfo = TOY_ALLOCATE(struct timeval, 1);
gettimeofday(timeinfo, NULL);
//wrap in an opaque literal for Toy
Toy_Literal timeLiteral = TOY_TO_OPAQUE_LITERAL(timeinfo, -1);
Toy_pushLiteralArray(&interpreter->stack, timeLiteral);
Toy_freeLiteral(timeLiteral);
return 1;
}
static int nativeStopTimer(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _stopTimer\n");
return -1;
}
//get the timeinfo from C
struct timeval timerStop;
gettimeofday(&timerStop, NULL);
//unwrap the opaque literal
Toy_Literal timeLiteral = Toy_popLiteralArray(arguments);
Toy_Literal timeLiteralIdn = timeLiteral;
if (TOY_IS_IDENTIFIER(timeLiteral) && Toy_parseIdentifierToValue(interpreter, &timeLiteral)) {
Toy_freeLiteral(timeLiteralIdn);
}
if (!TOY_IS_OPAQUE(timeLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _stopTimer\n");
Toy_freeLiteral(timeLiteral);
return -1;
}
struct timeval* timerStart = TOY_AS_OPAQUE(timeLiteral);
//determine the difference, and wrap it
struct timeval* d = diff(timerStart, &timerStop);
Toy_Literal diffLiteral = TOY_TO_OPAQUE_LITERAL(d, -1);
Toy_pushLiteralArray(&interpreter->stack, diffLiteral);
//cleanup
Toy_freeLiteral(timeLiteral);
Toy_freeLiteral(diffLiteral);
return 1;
}
static int nativeCreateTimer(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to createTimer\n");
return -1;
}
//get the args
Toy_Literal microsecondLiteral = Toy_popLiteralArray(arguments);
Toy_Literal secondLiteral = Toy_popLiteralArray(arguments);
Toy_Literal secondLiteralIdn = secondLiteral;
if (TOY_IS_IDENTIFIER(secondLiteral) && Toy_parseIdentifierToValue(interpreter, &secondLiteral)) {
Toy_freeLiteral(secondLiteralIdn);
}
Toy_Literal microsecondLiteralIdn = microsecondLiteral;
if (TOY_IS_IDENTIFIER(microsecondLiteral) && Toy_parseIdentifierToValue(interpreter, &microsecondLiteral)) {
Toy_freeLiteral(microsecondLiteralIdn);
}
if (!TOY_IS_INTEGER(secondLiteral) || !TOY_IS_INTEGER(microsecondLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to createTimer\n");
Toy_freeLiteral(secondLiteral);
Toy_freeLiteral(microsecondLiteral);
return -1;
}
if (TOY_AS_INTEGER(microsecondLiteral) <= -1000 * 1000 || TOY_AS_INTEGER(microsecondLiteral) >= 1000 * 1000 || (TOY_AS_INTEGER(secondLiteral) != 0 && TOY_AS_INTEGER(microsecondLiteral) < 0) ) {
interpreter->errorOutput("Microseconds out of range in createTimer\n");
Toy_freeLiteral(secondLiteral);
Toy_freeLiteral(microsecondLiteral);
return -1;
}
//get the timeinfo from toy
struct timeval* timeinfo = TOY_ALLOCATE(struct timeval, 1);
timeinfo->tv_sec = TOY_AS_INTEGER(secondLiteral);
timeinfo->tv_usec = TOY_AS_INTEGER(microsecondLiteral);
//wrap in an opaque literal for Toy
Toy_Literal timeLiteral = TOY_TO_OPAQUE_LITERAL(timeinfo, -1);
Toy_pushLiteralArray(&interpreter->stack, timeLiteral);
Toy_freeLiteral(timeLiteral);
Toy_freeLiteral(secondLiteral);
Toy_freeLiteral(microsecondLiteral);
return 1;
}
static int nativeGetTimerSeconds(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _getTimerSeconds\n");
return -1;
}
//unwrap the opaque literal
Toy_Literal timeLiteral = Toy_popLiteralArray(arguments);
Toy_Literal timeLiteralIdn = timeLiteral;
if (TOY_IS_IDENTIFIER(timeLiteral) && Toy_parseIdentifierToValue(interpreter, &timeLiteral)) {
Toy_freeLiteral(timeLiteralIdn);
}
if (!TOY_IS_OPAQUE(timeLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _getTimerSeconds\n");
Toy_freeLiteral(timeLiteral);
return -1;
}
struct timeval* timer = TOY_AS_OPAQUE(timeLiteral);
//create the result literal
Toy_Literal result = TOY_TO_INTEGER_LITERAL(timer->tv_sec);
Toy_pushLiteralArray(&interpreter->stack, result);
//cleanup
Toy_freeLiteral(timeLiteral);
Toy_freeLiteral(result);
return 1;
}
static int nativeGetTimerMicroseconds(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _getTimerMicroseconds\n");
return -1;
}
//unwrap the opaque literal
Toy_Literal timeLiteral = Toy_popLiteralArray(arguments);
Toy_Literal timeLiteralIdn = timeLiteral;
if (TOY_IS_IDENTIFIER(timeLiteral) && Toy_parseIdentifierToValue(interpreter, &timeLiteral)) {
Toy_freeLiteral(timeLiteralIdn);
}
if (!TOY_IS_OPAQUE(timeLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _getTimerMicroseconds\n");
Toy_freeLiteral(timeLiteral);
return -1;
}
struct timeval* timer = TOY_AS_OPAQUE(timeLiteral);
//create the result literal
Toy_Literal result = TOY_TO_INTEGER_LITERAL(timer->tv_usec);
Toy_pushLiteralArray(&interpreter->stack, result);
//cleanup
Toy_freeLiteral(timeLiteral);
Toy_freeLiteral(result);
return 1;
}
static int nativeCompareTimer(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _compareTimer\n");
return -1;
}
//unwrap the opaque literals
Toy_Literal rhsLiteral = Toy_popLiteralArray(arguments);
Toy_Literal lhsLiteral = Toy_popLiteralArray(arguments);
Toy_Literal lhsLiteralIdn = lhsLiteral;
if (TOY_IS_IDENTIFIER(lhsLiteral) && Toy_parseIdentifierToValue(interpreter, &lhsLiteral)) {
Toy_freeLiteral(lhsLiteralIdn);
}
Toy_Literal rhsLiteralIdn = rhsLiteral;
if (TOY_IS_IDENTIFIER(rhsLiteral) && Toy_parseIdentifierToValue(interpreter, &rhsLiteral)) {
Toy_freeLiteral(rhsLiteralIdn);
}
if (!TOY_IS_OPAQUE(lhsLiteral) || !TOY_IS_OPAQUE(rhsLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _compareTimer\n");
Toy_freeLiteral(lhsLiteral);
Toy_freeLiteral(rhsLiteral);
return -1;
}
struct timeval* lhsTimer = TOY_AS_OPAQUE(lhsLiteral);
struct timeval* rhsTimer = TOY_AS_OPAQUE(rhsLiteral);
//determine the difference, and wrap it
struct timeval* d = diff(lhsTimer, rhsTimer);
Toy_Literal diffLiteral = TOY_TO_OPAQUE_LITERAL(d, -1);
Toy_pushLiteralArray(&interpreter->stack, diffLiteral);
//cleanup
Toy_freeLiteral(lhsLiteral);
Toy_freeLiteral(rhsLiteral);
Toy_freeLiteral(diffLiteral);
return 1;
}
static int nativeTimerToString(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _timerToString\n");
return -1;
}
//unwrap in an opaque literal
Toy_Literal timeLiteral = Toy_popLiteralArray(arguments);
Toy_Literal timeLiteralIdn = timeLiteral;
if (TOY_IS_IDENTIFIER(timeLiteral) && Toy_parseIdentifierToValue(interpreter, &timeLiteral)) {
Toy_freeLiteral(timeLiteralIdn);
}
if (!TOY_IS_OPAQUE(timeLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _timerToString\n");
Toy_freeLiteral(timeLiteral);
return -1;
}
struct timeval* timer = TOY_AS_OPAQUE(timeLiteral);
//create the string literal
Toy_Literal resultLiteral = TOY_TO_NULL_LITERAL;
if (timer->tv_sec == 0 && timer->tv_usec < 0) { //special case, for when the negative sign is encoded in the usec
char buffer[128];
snprintf(buffer, 128, "-%ld.%06ld", timer->tv_sec, -timer->tv_usec);
resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefStringLength(buffer, strlen(buffer)));
}
else { //normal case
char buffer[128];
snprintf(buffer, 128, "%ld.%06ld", timer->tv_sec, timer->tv_usec);
resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefStringLength(buffer, strlen(buffer)));
}
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
//cleanup
Toy_freeLiteral(timeLiteral);
Toy_freeLiteral(resultLiteral);
return 1;
}
static int nativeDestroyTimer(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to _destroyTimer\n");
return -1;
}
//unwrap in an opaque literal
Toy_Literal timeLiteral = Toy_popLiteralArray(arguments);
Toy_Literal timeLiteralIdn = timeLiteral;
if (TOY_IS_IDENTIFIER(timeLiteral) && Toy_parseIdentifierToValue(interpreter, &timeLiteral)) {
Toy_freeLiteral(timeLiteralIdn);
}
if (!TOY_IS_OPAQUE(timeLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to _destroyTimer\n");
Toy_freeLiteral(timeLiteral);
return -1;
}
struct timeval* timer = TOY_AS_OPAQUE(timeLiteral);
TOY_FREE(struct timeval, timer);
Toy_freeLiteral(timeLiteral);
return 0;
}
//call the hook
typedef struct Natives {
char* name;
Toy_NativeFn fn;
} Natives;
int Toy_hookTimer(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
//build the natives list
Natives natives[] = {
{"startTimer", nativeStartTimer},
{"_stopTimer", nativeStopTimer},
{"createTimer", nativeCreateTimer},
{"_getTimerSeconds", nativeGetTimerSeconds},
{"_getTimerMicroseconds", nativeGetTimerMicroseconds},
{"_compareTimer", nativeCompareTimer},
{"_timerToString", nativeTimerToString},
{"_destroyTimer", nativeDestroyTimer},
{NULL, NULL}
};
//store the library in an aliased dictionary
if (!TOY_IS_NULL(alias)) {
//make sure the name isn't taken
if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) {
interpreter->errorOutput("Can't override an existing variable\n");
Toy_freeLiteral(alias);
return -1;
}
//create the dictionary to load up with functions
Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
Toy_initLiteralDictionary(dictionary);
//load the dict with functions
for (int i = 0; natives[i].name; i++) {
Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name));
Toy_Literal func = TOY_TO_FUNCTION_NATIVE_LITERAL(natives[i].fn);
Toy_setLiteralDictionary(dictionary, name, func);
Toy_freeLiteral(name);
Toy_freeLiteral(func);
}
//build the type
Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true);
Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true);
Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true);
TOY_TYPE_PUSH_SUBTYPE(&type, strType);
TOY_TYPE_PUSH_SUBTYPE(&type, fnType);
//set scope
Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary);
Toy_declareScopeVariable(interpreter->scope, alias, type);
Toy_setScopeVariable(interpreter->scope, alias, dict, false);
//cleanup
Toy_freeLiteral(dict);
Toy_freeLiteral(type);
return 0;
}
//default
for (int i = 0; natives[i].name; i++) {
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
}
return 0;
}
-6
View File
@@ -1,6 +0,0 @@
#pragma once
#include "toy_interpreter.h"
int Toy_hookTimer(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
+63 -14
View File
@@ -1,8 +1,6 @@
#include "repl_tools.h"
#include "lib_about.h"
#include "lib_compound.h"
#include "lib_standard.h"
#include "lib_timer.h"
#include "lib_runner.h"
#include "toy_console_colors.h"
@@ -16,31 +14,31 @@
#include <stdlib.h>
#include <string.h>
void repl() {
#define INPUT_BUFFER_SIZE 2048
void repl(const char* initialInput) {
//repl does it's own thing for now
bool error = false;
const int size = 2048;
char input[size];
memset(input, 0, size);
char input[INPUT_BUFFER_SIZE];
memset(input, 0, INPUT_BUFFER_SIZE);
Toy_Interpreter interpreter; //persist the interpreter for the scopes
Toy_initInterpreter(&interpreter);
//inject the libs
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
Toy_injectNativeHook(&interpreter, "compound", Toy_hookCompound);
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
Toy_injectNativeHook(&interpreter, "timer", Toy_hookTimer);
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
for(;;) {
printf("> ");
if (!initialInput) {
//handle EOF for exits
if (!fgets(input, size, stdin)) {
printf("> ");
if (!fgets(input, INPUT_BUFFER_SIZE, stdin)) {
break;
}
}
//escape the repl (length of 5 to accomodate the newline)
if (strlen(input) == 5 && (!strncmp(input, "exit", 4) || !strncmp(input, "quit", 4))) {
@@ -52,8 +50,8 @@ void repl() {
Toy_Parser parser;
Toy_Compiler compiler;
Toy_initLexer(&lexer, input);
Toy_private_setComments(&lexer, false); //BUGFIX: disable comments here
Toy_initLexer(&lexer, initialInput ? initialInput : input);
Toy_private_setComments(&lexer, initialInput != NULL); //BUGFIX: disable comments here
Toy_initParser(&parser, &lexer);
Toy_initCompiler(&compiler);
@@ -88,6 +86,15 @@ void repl() {
Toy_freeCompiler(&compiler);
Toy_freeParser(&parser);
error = false;
if (initialInput) {
free((void*)initialInput);
initialInput = NULL;
if (interpreter.panic) {
break;
}
}
}
Toy_freeInterpreter(&interpreter);
@@ -131,6 +138,14 @@ int main(int argc, const char* argv[]) {
//run source file
if (Toy_commandLine.sourcefile) {
//only works on toy files
const char* s = strrchr(Toy_commandLine.sourcefile, '.');
if (!s || strcmp(s, ".toy")) {
fprintf(stderr, TOY_CC_ERROR "Bad file extension passed to %s (expected '.toy', found '%s')" TOY_CC_RESET, argv[0], s);
return -1;
}
//run the source file
Toy_runSourceFile(Toy_commandLine.sourcefile);
//lib cleanup
@@ -151,6 +166,19 @@ int main(int argc, const char* argv[]) {
//compile source file
if (Toy_commandLine.compilefile && Toy_commandLine.outfile) {
//only works on toy and tb files
const char* c = strrchr(Toy_commandLine.compilefile, '.');
if (!c || strcmp(c, ".toy")) {
fprintf(stderr, TOY_CC_ERROR "Bad file extension passed to %s (expected '.toy', found '%s')" TOY_CC_RESET, argv[0], c);
return -1;
}
const char* o = strrchr(Toy_commandLine.outfile, '.');
if (!o || strcmp(o, ".tb")) {
fprintf(stderr, TOY_CC_ERROR "Bad file extension passed to %s (expected '.tb', found '%s')" TOY_CC_RESET, argv[0], o);
return -1;
}
//compile and save
size_t size = 0;
const char* source = Toy_readFile(Toy_commandLine.compilefile, &size);
if (!source) {
@@ -166,6 +194,14 @@ int main(int argc, const char* argv[]) {
//run binary
if (Toy_commandLine.binaryfile) {
//only works on tb files
const char* c = strrchr(Toy_commandLine.binaryfile, '.');
if (!c || strcmp(c, ".tb")) {
fprintf(stderr, TOY_CC_ERROR "Bad file extension passed to %s (expected '.tb', found '%s')" TOY_CC_RESET, argv[0], c); //this one is never seen
return -1;
}
//run the binary file
Toy_runBinaryFile(Toy_commandLine.binaryfile);
//lib cleanup
@@ -174,7 +210,20 @@ int main(int argc, const char* argv[]) {
return 0;
}
repl();
const char* initialSource = NULL;
if (Toy_commandLine.initialfile) {
//only works on toy files
const char* s = strrchr(Toy_commandLine.initialfile, '.');
if (!s || strcmp(s, ".toy")) {
fprintf(stderr, TOY_CC_ERROR "Bad file extension passed to %s (expected '.toy', found '%s')" TOY_CC_RESET, argv[0], s);
return -1;
}
size_t size;
initialSource = Toy_readFile(Toy_commandLine.initialfile, &size);
}
repl(initialSource);
//lib cleanup
Toy_freeDriveDictionary();
+2 -6
View File
@@ -1,8 +1,6 @@
#include "repl_tools.h"
#include "lib_about.h"
#include "lib_compound.h"
#include "lib_standard.h"
#include "lib_timer.h"
#include "lib_runner.h"
#include "toy_console_colors.h"
@@ -57,7 +55,7 @@ int Toy_writeFile(const char* path, const unsigned char* bytes, size_t size) {
return -1;
}
int written = fwrite(bytes, size, 1, file);
size_t written = fwrite(bytes, size, 1, file);
if (written != 1) {
fprintf(stderr, TOY_CC_ERROR "Could not write file \"%s\"\n" TOY_CC_RESET, path);
@@ -113,12 +111,10 @@ void Toy_runBinary(const unsigned char* tb, size_t size) {
//inject the libs
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
Toy_injectNativeHook(&interpreter, "compound", Toy_hookCompound);
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
Toy_injectNativeHook(&interpreter, "timer", Toy_hookTimer);
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
Toy_runInterpreter(&interpreter, tb, size);
Toy_runInterpreter(&interpreter, tb, (int)size);
Toy_freeInterpreter(&interpreter);
}
+29 -15
View File
@@ -1,19 +1,21 @@
//constants
var WIDTH: int const = 10;
var HEIGHT: int const = 10;
var WIDTH: int const = 12;
var HEIGHT: int const = 12;
//WIDTH * HEIGHT in size
var tiles: [[int]] const = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1],
[1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] //BUG: map is twisted along this diagonal
];
var tileset: [int: string] const = [
@@ -22,8 +24,8 @@ var tileset: [int: string] const = [
];
//variables
var posX: int = 5;
var posY: int = 5;
var posX: int = 4;
var posY: int = 4;
//functions
fn draw() {
@@ -42,7 +44,7 @@ fn draw() {
print "\n";
}
fn move(xrel: int, yrel: int) {
fn moveRelative(xrel: int, yrel: int) {
if (xrel > 1 || xrel < -1 || yrel > 1 || yrel < -1 || (xrel != 0 && yrel != 0)) {
print "too fast!\n";
return;
@@ -59,3 +61,15 @@ fn move(xrel: int, yrel: int) {
draw();
}
//wrap for easy use
var up: [int] const = [0, -1];
var down: [int] const = [0, 1];
var left: [int] const = [-1, 0];
var right: [int] const = [1, 0];
fn move(dir: [int] const) {
return moveRelative(dir[0], dir[1]);
}
//initial display
move([0, 0]);
+24 -7
View File
@@ -1,10 +1,27 @@
import compound;
var xrel: int = 0;
var yrel: int = 0;
fn less(a, b) {
return a < b;
}
if (xrel > 1 || xrel < -1 || yrel > 1 || yrel < -1) {
print "outside";
}
else {
print "inside";
fn greater(a, b) {
return a > b;
}
var a = [7, 2, 1, 8, 6, 3, 5, 4];
var b = [7, 2, 1, 4, 6, 3, 5, 8];
var c = [1, 2, 3, 4, 5, 6, 7, 8];
var d = [7, 2, 1, 8, 6, 3, 5, 4];
a = a.sort(less);
b = b.sort(less);
c = c.sort(less);
d = d.sort(greater);
assert a == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) failed";
assert b == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) with pivot high failed";
assert c == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) pre-sorted array failed";
assert d == [8, 7, 6, 5, 4, 3, 2, 1], "array.sort(greater) failed";
print "All good";
+10 -5
View File
@@ -15,8 +15,6 @@ STATIC_ASSERT(sizeof(unsigned char) == 1);
STATIC_ASSERT(sizeof(unsigned short) == 2);
STATIC_ASSERT(sizeof(unsigned int) == 4);
#ifndef TOY_EXPORT
//declare the singleton
Toy_CommandLine Toy_commandLine;
@@ -30,6 +28,7 @@ void Toy_initCommandLine(int argc, const char* argv[]) {
Toy_commandLine.compilefile = NULL;
Toy_commandLine.outfile = "out.tb";
Toy_commandLine.source = NULL;
Toy_commandLine.initialfile = NULL;
Toy_commandLine.verbose = false;
for (int i = 1; i < argc; i++) { //start at 1 to skip the program name
@@ -81,6 +80,13 @@ void Toy_initCommandLine(int argc, const char* argv[]) {
continue;
}
if ((!strcmp(argv[i], "-t") || !strcmp(argv[i], "--initial")) && i + 1 < argc) {
Toy_commandLine.initialfile = (char*)argv[i + 1];
i++;
Toy_commandLine.error = false;
continue;
}
//option without a flag + ending in .tb = binary input
if (i < argc) {
if (strncmp(&(argv[i][strlen(argv[i]) - 3]), ".tb", 3) == 0) {
@@ -96,7 +102,7 @@ void Toy_initCommandLine(int argc, const char* argv[]) {
}
void Toy_usageCommandLine(int argc, const char* argv[]) {
printf("Usage: %s [<file.tb> | -h | -v | [-d][-f file | -i source | -c file [-o outfile]]]\n\n", argv[0]);
printf("Usage: %s [ file.tb | -h | -v | -d | -f file.toy | -i source | -c file.toy -o out.tb | -t file.toy ]\n\n", argv[0]);
}
void Toy_helpCommandLine(int argc, const char* argv[]) {
@@ -110,6 +116,7 @@ void Toy_helpCommandLine(int argc, const char* argv[]) {
printf("-i\t| --input source\tParse, compile and execute this given string of source code.\n\n");
printf("-c\t| --compile filename\tParse and compile the specified source file into an output file.\n\n");
printf("-o\t| --output outfile\tName of the output file built with --compile (default: out.tb).\n\n");
printf("-t\t| --initial filename\tStart the repl as normal, after first running the given file.\n\n");
}
void Toy_copyrightCommandLine(int argc, const char* argv[]) {
@@ -121,5 +128,3 @@ void Toy_copyrightCommandLine(int argc, const char* argv[]) {
printf("2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n\n");
printf("3. This notice may not be removed or altered from any source distribution.\n\n");
}
#endif
+19 -13
View File
@@ -6,22 +6,28 @@
#define TOY_VERSION_MAJOR 0
#define TOY_VERSION_MINOR 8
#define TOY_VERSION_PATCH 2
#define TOY_VERSION_PATCH 3
#define TOY_VERSION_BUILD __DATE__ " " __TIME__
//platform-specific specifications
#if defined(__linux__)
//platform/compiler-specific instructions
#if defined(__linux__) || defined(__MINGW32__) || defined(__GNUC__)
#define TOY_API extern
#elif defined(_WIN32) || defined(WIN32)
#define TOY_API
#elif defined(_MSC_VER)
#ifndef TOY_EXPORT
#define TOY_API __declspec(dllimport)
#else
#define TOY_API __declspec(dllexport)
#endif
#else
#define TOY_API
#define TOY_API extern
#endif
#ifndef TOY_EXPORT
//for processing the command line arguments
typedef struct {
bool error;
@@ -32,14 +38,14 @@ typedef struct {
char* compilefile;
char* outfile; //defaults to out.tb
char* source;
char* initialfile;
bool verbose;
} Toy_CommandLine;
extern Toy_CommandLine Toy_commandLine;
TOY_API Toy_CommandLine Toy_commandLine;
void Toy_initCommandLine(int argc, const char* argv[]);
TOY_API void Toy_initCommandLine(int argc, const char* argv[]);
void Toy_usageCommandLine(int argc, const char* argv[]);
void Toy_helpCommandLine(int argc, const char* argv[]);
void Toy_copyrightCommandLine(int argc, const char* argv[]);
#endif
TOY_API void Toy_usageCommandLine(int argc, const char* argv[]);
TOY_API void Toy_helpCommandLine(int argc, const char* argv[]);
TOY_API void Toy_copyrightCommandLine(int argc, const char* argv[]);
+8 -2
View File
@@ -302,6 +302,12 @@ static Toy_Opcode Toy_writeCompilerWithJumps(Toy_Compiler* compiler, Toy_ASTNode
//special case for when indexing and assigning
if (override != TOY_OP_EOF && node->binary.opcode >= TOY_OP_VAR_ASSIGN && node->binary.opcode <= TOY_OP_VAR_MODULO_ASSIGN) {
Toy_writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
//Special case if there's an index on both sides of the sign, just set it as indexing
if (node->binary.left->type == TOY_AST_NODE_BINARY && node->binary.right->type == TOY_AST_NODE_BINARY && node->binary.left->binary.opcode == TOY_OP_INDEX && node->binary.right->binary.opcode == TOY_OP_INDEX) {
compiler->bytecode[compiler->count++] = (unsigned char)TOY_OP_INDEX;
}
compiler->bytecode[compiler->count++] = (unsigned char)TOY_OP_INDEX_ASSIGN; //1 byte WARNING: enum trickery
compiler->bytecode[compiler->count++] = (unsigned char)node->binary.opcode; //1 byte
return TOY_OP_EOF;
@@ -315,7 +321,7 @@ static Toy_Opcode Toy_writeCompilerWithJumps(Toy_Compiler* compiler, Toy_ASTNode
//return this if...
Toy_Opcode ret = Toy_writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
if (node->binary.opcode == TOY_OP_INDEX && rootNode->type == TOY_AST_NODE_BINARY && (rootNode->binary.opcode >= TOY_OP_VAR_ASSIGN && rootNode->binary.opcode <= TOY_OP_VAR_MODULO_ASSIGN)) { //range-based check for assignment type
if (node->binary.opcode == TOY_OP_INDEX && rootNode->type == TOY_AST_NODE_BINARY && (rootNode->binary.opcode >= TOY_OP_VAR_ASSIGN && rootNode->binary.opcode <= TOY_OP_VAR_MODULO_ASSIGN) && rootNode->binary.right != node) { //range-based check for assignment type; make sure the index is on the left of the assignment symbol
return TOY_OP_INDEX_ASSIGN_INTERMEDIATE;
}
@@ -1167,7 +1173,7 @@ static unsigned char* collateCompilerHeaderOpt(Toy_Compiler* compiler, int* size
case TOY_LITERAL_FUNCTION_INTERMEDIATE: {
//extract the compiler
Toy_Literal fn = compiler->literalCache.literals[i];
void* fnCompiler = TOY_AS_FUNCTION(fn).bytecode; //store the compiler here for now
void* fnCompiler = TOY_AS_FUNCTION(fn).inner.bytecode; //store the compiler here for now
//collate the function into bytecode (without header)
int size = 0;
+34
View File
@@ -2,6 +2,9 @@
//NOTE: you need both font AND background for these to work
//platform/compiler-specific instructions
#if defined(__linux__) || defined(__MINGW32__) || defined(__GNUC__)
//fonts color
#define TOY_CC_FONT_BLACK "\033[30;"
#define TOY_CC_FONT_RED "\033[31;"
@@ -28,3 +31,34 @@
#define TOY_CC_WARN TOY_CC_FONT_YELLOW TOY_CC_BACK_BLACK
#define TOY_CC_ERROR TOY_CC_FONT_RED TOY_CC_BACK_BLACK
#define TOY_CC_RESET "\033[0m"
#else
//fonts color
#define TOY_CC_FONT_BLACK
#define TOY_CC_FONT_RED
#define TOY_CC_FONT_GREEN
#define TOY_CC_FONT_YELLOW
#define TOY_CC_FONT_BLUE
#define TOY_CC_FONT_PURPLE
#define TOY_CC_FONT_DGREEN
#define TOY_CC_FONT_WHITE
#define TOY_CC_FONT_CYAN
//background color
#define TOY_CC_BACK_BLACK
#define TOY_CC_BACK_RED
#define TOY_CC_BACK_GREEN
#define TOY_CC_BACK_YELLOW
#define TOY_CC_BACK_BLUE
#define TOY_CC_BACK_PURPLE
#define TOY_CC_BACK_DGREEN
#define TOY_CC_BACK_WHITE
//useful
#define TOY_CC_NOTICE TOY_CC_FONT_GREEN TOY_CC_BACK_BLACK
#define TOY_CC_WARN TOY_CC_FONT_YELLOW TOY_CC_BACK_BLACK
#define TOY_CC_ERROR TOY_CC_FONT_RED TOY_CC_BACK_BLACK
#define TOY_CC_RESET
#endif
+4 -4
View File
@@ -1254,8 +1254,8 @@ bool Toy_callLiteralFn(Toy_Interpreter* interpreter, Toy_Literal func, Toy_Liter
//init the inner interpreter manually
Toy_initLiteralArray(&inner.literalCache);
inner.scope = Toy_pushScope(func.as.function.scope);
inner.bytecode = TOY_AS_FUNCTION(func).bytecode;
inner.length = TOY_AS_FUNCTION(func).length;
inner.bytecode = TOY_AS_FUNCTION(func).inner.bytecode;
inner.length = TOY_AS_FUNCTION_BYTECODE_LENGTH(func);
inner.count = 0;
inner.codeStart = -1;
inner.depth = interpreter->depth + 1;
@@ -1507,7 +1507,7 @@ static bool execImport(Toy_Interpreter* interpreter) {
if (!Toy_existsLiteralDictionary(interpreter->hooks, identifier)) {
interpreter->errorOutput("Unknown library name in import statement: ");
Toy_printLiteralCustom(identifier, interpreter->errorOutput);
interpreter->errorOutput("\"\n");
interpreter->errorOutput("\n");
Toy_freeLiteral(alias);
Toy_freeLiteral(identifier);
@@ -2356,7 +2356,7 @@ void Toy_initInterpreter(Toy_Interpreter* interpreter) {
Toy_resetInterpreter(interpreter);
}
void Toy_runInterpreter(Toy_Interpreter* interpreter, const unsigned char* bytecode, int length) {
void Toy_runInterpreter(Toy_Interpreter* interpreter, const unsigned char* bytecode, size_t length) {
//initialize here instead of initInterpreter()
Toy_initLiteralArray(&interpreter->literalCache);
interpreter->bytecode = NULL;
+1 -1
View File
@@ -48,6 +48,6 @@ TOY_API void Toy_setInterpreterError(Toy_Interpreter* interpreter, Toy_PrintFn e
//main access
TOY_API void Toy_initInterpreter(Toy_Interpreter* interpreter); //start of program
TOY_API void Toy_runInterpreter(Toy_Interpreter* interpreter, const unsigned char* bytecode, int length); //run the code
TOY_API void Toy_runInterpreter(Toy_Interpreter* interpreter, const unsigned char* bytecode, size_t length); //run the code
TOY_API void Toy_resetInterpreter(Toy_Interpreter* interpreter); //use this to reset the interpreter's environment between runs
TOY_API void Toy_freeInterpreter(Toy_Interpreter* interpreter); //end of program
+3 -3
View File
@@ -21,9 +21,9 @@ typedef struct {
} Toy_Token;
TOY_API void Toy_initLexer(Toy_Lexer* lexer, const char* source);
Toy_Token Toy_scanLexer(Toy_Lexer* lexer);
TOY_API Toy_Token Toy_scanLexer(Toy_Lexer* lexer);
//for debugging
void Toy_printToken(Toy_Token* token);
TOY_API void Toy_printToken(Toy_Token* token);
void Toy_private_setComments(Toy_Lexer* lexer, bool enabled);
TOY_API void Toy_private_setComments(Toy_Lexer* lexer, bool enabled);
+6 -6
View File
@@ -58,7 +58,7 @@ void Toy_freeLiteral(Toy_Literal literal) {
if (TOY_IS_FUNCTION(literal)) {
Toy_popScope(TOY_AS_FUNCTION(literal).scope);
TOY_AS_FUNCTION(literal).scope = NULL;
TOY_FREE_ARRAY(unsigned char, TOY_AS_FUNCTION(literal).bytecode, TOY_AS_FUNCTION(literal).length);
TOY_FREE_ARRAY(unsigned char, TOY_AS_FUNCTION(literal).inner.bytecode, TOY_AS_FUNCTION_BYTECODE_LENGTH(literal));
}
if (TOY_IS_TYPE(literal)) {
@@ -84,11 +84,11 @@ bool Toy_private_isTruthy(Toy_Literal x) {
}
Toy_Literal Toy_private_toStringLiteral(Toy_RefString* ptr) {
return ((Toy_Literal){TOY_LITERAL_STRING, { .string.ptr = ptr }});
return ((Toy_Literal){{ .string.ptr = ptr },TOY_LITERAL_STRING, 0});
}
Toy_Literal Toy_private_toIdentifierLiteral(Toy_RefString* ptr) {
return ((Toy_Literal){TOY_LITERAL_IDENTIFIER,{ .identifier.ptr = ptr, .identifier.hash = hashString(Toy_toCString(ptr), Toy_lengthRefString(ptr)) }});
return ((Toy_Literal){{ .identifier.ptr = ptr, .identifier.hash = hashString(Toy_toCString(ptr), Toy_lengthRefString(ptr)) },TOY_LITERAL_IDENTIFIER, 0});
}
Toy_Literal* Toy_private_typePushSubtype(Toy_Literal* lit, Toy_Literal subtype) {
@@ -145,10 +145,10 @@ Toy_Literal Toy_copyLiteral(Toy_Literal original) {
}
case TOY_LITERAL_FUNCTION: {
unsigned char* buffer = TOY_ALLOCATE(unsigned char, TOY_AS_FUNCTION(original).length);
memcpy(buffer, TOY_AS_FUNCTION(original).bytecode, TOY_AS_FUNCTION(original).length);
unsigned char* buffer = TOY_ALLOCATE(unsigned char, TOY_AS_FUNCTION_BYTECODE_LENGTH(original));
memcpy(buffer, TOY_AS_FUNCTION(original).inner.bytecode, TOY_AS_FUNCTION_BYTECODE_LENGTH(original));
Toy_Literal literal = TOY_TO_FUNCTION_LITERAL(buffer, TOY_AS_FUNCTION(original).length);
Toy_Literal literal = TOY_TO_FUNCTION_LITERAL(buffer, TOY_AS_FUNCTION_BYTECODE_LENGTH(original));
TOY_AS_FUNCTION(literal).scope = Toy_copyScope(TOY_AS_FUNCTION(original).scope);
return literal;
+47 -41
View File
@@ -39,45 +39,49 @@ typedef enum {
} Toy_LiteralType;
typedef struct Toy_Literal {
Toy_LiteralType type;
union {
bool boolean;
int integer;
float number;
bool boolean; //1
int integer; //4
float number;//4
struct {
Toy_RefString* ptr;
Toy_RefString* ptr; //8
//string hash?
} string;
} string; //8
void* array;
void* dictionary;
void* array; //8
void* dictionary; //8
struct {
void* bytecode;
Toy_NativeFn native; //already a pointer
Toy_HookFn hook; //already a pointer
void* scope;
int length;
} function;
union {
void* bytecode; //8
Toy_NativeFn native; //8
Toy_HookFn hook; //8
} inner; //8
void* scope; //8
} function; //16
struct { //for variable names
Toy_RefString* ptr;
int hash;
} identifier;
Toy_RefString* ptr; //8
int hash; //4
} identifier; //16
struct {
Toy_LiteralType typeOf;
bool constant;
void* subtypes; //for nested types caused by compounds
int capacity;
int count;
} type;
void* subtypes; //8
Toy_LiteralType typeOf; //4
unsigned char capacity; //1
unsigned char count; //1
bool constant; //1
} type; //16
struct {
void* ptr;
int tag;
} opaque;
} as;
void* ptr; //8
int tag; //4
} opaque; //16
} as; //16
Toy_LiteralType type; //4
int bytecodeLength; //4 - shenanigans with byte alignment reduces the size of Toy_Literal
} Toy_Literal;
#define TOY_IS_NULL(value) ((value).type == TOY_LITERAL_NULL)
@@ -101,34 +105,36 @@ typedef struct Toy_Literal {
#define TOY_AS_ARRAY(value) ((Toy_LiteralArray*)((value).as.array))
#define TOY_AS_DICTIONARY(value) ((Toy_LiteralDictionary*)((value).as.dictionary))
#define TOY_AS_FUNCTION(value) ((value).as.function)
#define TOY_AS_FUNCTION_NATIVE(value) ((value).as.function.native)
#define TOY_AS_FUNCTION_HOOK(value) ((value).as.function.hook)
#define TOY_AS_FUNCTION_NATIVE(value) ((value).as.function.inner.native)
#define TOY_AS_FUNCTION_HOOK(value) ((value).as.function.inner.hook)
#define TOY_AS_IDENTIFIER(value) ((value).as.identifier.ptr)
#define TOY_AS_TYPE(value) ((value).as.type)
#define TOY_AS_OPAQUE(value) ((value).as.opaque.ptr)
#define TOY_TO_NULL_LITERAL ((Toy_Literal){TOY_LITERAL_NULL, { .integer = 0 }})
#define TOY_TO_BOOLEAN_LITERAL(value) ((Toy_Literal){TOY_LITERAL_BOOLEAN, { .boolean = value }})
#define TOY_TO_INTEGER_LITERAL(value) ((Toy_Literal){TOY_LITERAL_INTEGER, { .integer = value }})
#define TOY_TO_FLOAT_LITERAL(value) ((Toy_Literal){TOY_LITERAL_FLOAT, { .number = value }})
#define TOY_TO_NULL_LITERAL ((Toy_Literal){{ .integer = 0 }, TOY_LITERAL_NULL, 0})
#define TOY_TO_BOOLEAN_LITERAL(value) ((Toy_Literal){{ .boolean = value }, TOY_LITERAL_BOOLEAN, 0})
#define TOY_TO_INTEGER_LITERAL(value) ((Toy_Literal){{ .integer = value }, TOY_LITERAL_INTEGER, 0})
#define TOY_TO_FLOAT_LITERAL(value) ((Toy_Literal){{ .number = value }, TOY_LITERAL_FLOAT, 0})
#define TOY_TO_STRING_LITERAL(value) Toy_private_toStringLiteral(value)
#define TOY_TO_ARRAY_LITERAL(value) ((Toy_Literal){TOY_LITERAL_ARRAY, { .array = value }})
#define TOY_TO_DICTIONARY_LITERAL(value) ((Toy_Literal){TOY_LITERAL_DICTIONARY, { .dictionary = value }})
#define TOY_TO_FUNCTION_LITERAL(value, l) ((Toy_Literal){TOY_LITERAL_FUNCTION, { .function.bytecode = value, .function.scope = NULL, .function.length = l }})
#define TOY_TO_FUNCTION_NATIVE_LITERAL(value) ((Toy_Literal){TOY_LITERAL_FUNCTION_NATIVE, { .function.native = value, .function.scope = NULL, .function.length = 0 }})
#define TOY_TO_FUNCTION_HOOK_LITERAL(value) ((Toy_Literal){TOY_LITERAL_FUNCTION_HOOK, { .function.hook = value, .function.scope = NULL, .function.length = 0 }})
#define TOY_TO_ARRAY_LITERAL(value) ((Toy_Literal){{ .array = value }, TOY_LITERAL_ARRAY, 0})
#define TOY_TO_DICTIONARY_LITERAL(value) ((Toy_Literal){{ .dictionary = value }, TOY_LITERAL_DICTIONARY, 0})
#define TOY_TO_FUNCTION_LITERAL(value, l) ((Toy_Literal){{ .function.inner.bytecode = value, .function.scope = NULL }, TOY_LITERAL_FUNCTION, l})
#define TOY_TO_FUNCTION_NATIVE_LITERAL(value) ((Toy_Literal){{ .function.inner.native = value, .function.scope = NULL }, TOY_LITERAL_FUNCTION_NATIVE, 0})
#define TOY_TO_FUNCTION_HOOK_LITERAL(value) ((Toy_Literal){{ .function.inner.hook = value, .function.scope = NULL }, TOY_LITERAL_FUNCTION_HOOK, 0})
#define TOY_TO_IDENTIFIER_LITERAL(value) Toy_private_toIdentifierLiteral(value)
#define TOY_TO_TYPE_LITERAL(value, c) ((Toy_Literal){ TOY_LITERAL_TYPE, { .type.typeOf = value, .type.constant = c, .type.subtypes = NULL, .type.capacity = 0, .type.count = 0 }})
#define TOY_TO_OPAQUE_LITERAL(value, t) ((Toy_Literal){ TOY_LITERAL_OPAQUE, { .opaque.ptr = value, .opaque.tag = t }})
#define TOY_TO_TYPE_LITERAL(value, c) ((Toy_Literal){{ .type.typeOf = value, .type.constant = c, .type.subtypes = NULL, .type.capacity = 0, .type.count = 0 }, TOY_LITERAL_TYPE, 0})
#define TOY_TO_OPAQUE_LITERAL(value, t) ((Toy_Literal){{ .opaque.ptr = value, .opaque.tag = t }, TOY_LITERAL_OPAQUE, 0})
//BUGFIX: For blank indexing
#define TOY_IS_INDEX_BLANK(value) ((value).type == TOY_LITERAL_INDEX_BLANK)
#define TOY_TO_INDEX_BLANK_LITERAL ((Toy_Literal){TOY_LITERAL_INDEX_BLANK, { .integer = 0 }})
#define TOY_TO_INDEX_BLANK_LITERAL ((Toy_Literal){{ .integer = 0 }, TOY_LITERAL_INDEX_BLANK, 0})
TOY_API void Toy_freeLiteral(Toy_Literal literal);
#define TOY_IS_TRUTHY(x) Toy_private_isTruthy(x)
#define TOY_AS_FUNCTION_BYTECODE_LENGTH(lit) ((lit).bytecodeLength)
#define TOY_MAX_STRING_LENGTH 4096
#define TOY_HASH_I(lit) ((lit).as.identifier.hash)
#define TOY_TYPE_PUSH_SUBTYPE(lit, subtype) Toy_private_typePushSubtype(lit, subtype)
+1 -1
View File
@@ -11,7 +11,7 @@
#define TOY_FREE_ARRAY(type, pointer, oldCount) Toy_reallocate((type*)pointer, sizeof(type) * (oldCount), 0)
//implementation details
void* Toy_reallocate(void* pointer, size_t oldSize, size_t newSize);
TOY_API void* Toy_reallocate(void* pointer, size_t oldSize, size_t newSize);
//assign the memory allocator
typedef void* (*Toy_MemoryAllocatorFn)(void* pointer, size_t oldSize, size_t newSize);
+12 -10
View File
@@ -3,6 +3,8 @@
#include <stdbool.h>
#include <stddef.h>
#include "toy_common.h"
//memory allocation hook
typedef void* (*Toy_RefStringAllocatorFn)(void* pointer, size_t oldSize, size_t newSize);
void Toy_setRefStringAllocatorFn(Toy_RefStringAllocatorFn);
@@ -15,13 +17,13 @@ typedef struct Toy_RefString {
} Toy_RefString;
//API
Toy_RefString* Toy_createRefString(const char* cstring);
Toy_RefString* Toy_createRefStringLength(const char* cstring, size_t length);
void Toy_deleteRefString(Toy_RefString* refString);
int Toy_countRefString(Toy_RefString* refString);
size_t Toy_lengthRefString(Toy_RefString* refString);
Toy_RefString* Toy_copyRefString(Toy_RefString* refString);
Toy_RefString* Toy_deepCopyRefString(Toy_RefString* refString);
const char* Toy_toCString(Toy_RefString* refString);
bool Toy_equalsRefString(Toy_RefString* lhs, Toy_RefString* rhs);
bool Toy_equalsRefStringCString(Toy_RefString* lhs, char* cstring);
TOY_API Toy_RefString* Toy_createRefString(const char* cstring);
TOY_API Toy_RefString* Toy_createRefStringLength(const char* cstring, size_t length);
TOY_API void Toy_deleteRefString(Toy_RefString* refString);
TOY_API int Toy_countRefString(Toy_RefString* refString);
TOY_API size_t Toy_lengthRefString(Toy_RefString* refString);
TOY_API Toy_RefString* Toy_copyRefString(Toy_RefString* refString);
TOY_API Toy_RefString* Toy_deepCopyRefString(Toy_RefString* refString);
TOY_API const char* Toy_toCString(Toy_RefString* refString);
TOY_API bool Toy_equalsRefString(Toy_RefString* lhs, Toy_RefString* rhs);
TOY_API bool Toy_equalsRefStringCString(Toy_RefString* lhs, char* cstring);
+8 -8
View File
@@ -10,16 +10,16 @@ typedef struct Toy_Scope {
int references; //how many scopes point here
} Toy_Scope;
Toy_Scope* Toy_pushScope(Toy_Scope* scope);
Toy_Scope* Toy_popScope(Toy_Scope* scope);
Toy_Scope* Toy_copyScope(Toy_Scope* original);
TOY_API Toy_Scope* Toy_pushScope(Toy_Scope* scope);
TOY_API Toy_Scope* Toy_popScope(Toy_Scope* scope);
TOY_API Toy_Scope* Toy_copyScope(Toy_Scope* original);
//returns false if error
bool Toy_declareScopeVariable(Toy_Scope* scope, Toy_Literal key, Toy_Literal type);
bool Toy_isDelcaredScopeVariable(Toy_Scope* scope, Toy_Literal key);
TOY_API bool Toy_declareScopeVariable(Toy_Scope* scope, Toy_Literal key, Toy_Literal type);
TOY_API bool Toy_isDelcaredScopeVariable(Toy_Scope* scope, Toy_Literal key);
//return false if undefined
bool Toy_setScopeVariable(Toy_Scope* scope, Toy_Literal key, Toy_Literal value, bool constCheck);
bool Toy_getScopeVariable(Toy_Scope* scope, Toy_Literal key, Toy_Literal* value);
TOY_API bool Toy_setScopeVariable(Toy_Scope* scope, Toy_Literal key, Toy_Literal value, bool constCheck);
TOY_API bool Toy_getScopeVariable(Toy_Scope* scope, Toy_Literal key, Toy_Literal* value);
Toy_Literal Toy_getScopeType(Toy_Scope* scope, Toy_Literal key);
TOY_API Toy_Literal Toy_getScopeType(Toy_Scope* scope, Toy_Literal key);
@@ -0,0 +1,15 @@
/*
This ensures that when indexing on both sides of an assignment,
it works correctly.
*/
var a = [1, 2, 3];
var b = [4, 5, 6];
a[1] = b[1];
assert a == [1, 5, 3], "index assignment both failed";
print "All good";
@@ -0,0 +1,19 @@
/*
Compiler note:
This is also to test a specific element in the compiler.
It ensures that when doing indexing and assignment in one statement,
the index is NOT on the right. If it is, then it is treated like a normal
assignment.
*/
//polyfill the _insert function
var a = [1, 2, 3];
var b = a[1];
assert b == 2, "index assignment left failed";
print "All good";
-280
View File
@@ -1,280 +0,0 @@
import compound;
//test concat
{
//test array concat
{
var a = [1, 2, 3];
var b = [4, 5, 6];
var c = a.concat(b).concat(b);
assert c == [1, 2, 3, 4, 5, 6, 4, 5, 6], "array.concat() failed";
}
//test dictionary concat
{
var a = ["one" : 1, "two": 2, "three": 3];
var b = ["four" : 4, "five": 5, "six": 6];
var c = a.concat(b);
assert c.length() == 6, "dictionary.concat().length() failed";
assert c == ["one" : 1, "two": 2, "three": 3, "four" : 4, "five": 5, "six": 6], "dictionary.concat() comparison failed";
}
//test dictionary concat with clashing keys
{
var a = ["one" : 1, "two": 2, "three": 3, "random": 1];
var b = ["four" : 4, "five": 5, "six": 6, "random": 2];
var c = a.concat(b);
assert c["random"] == 1, "dictionary.concat() clashing keys failed";
}
//test string concat
{
var a = "foo";
var b = "bar";
var c = a.concat(b);
assert c == "foobar", "string.concat() failed";
}
}
//test containsKey
{
var d = ["one": 1, "two": 2];
assert d.containsKey("one") == true, "dictionary.containsKey() == true failed";
assert d.containsKey("three") == false, "dictionary.containsKey() == false failed";
}
//test containsValue
{
var a = [1, 2, 3];
var d = ["one": 1, "two": 2];
assert a.containsValue(1) == true, "array.containsValue() == true failed";
assert a.containsValue(5) == false, "array.containsValue() == false failed";
assert d.containsValue(1) == true, "dictionary.containsValue() == true failed";
assert d.containsValue(3) == false, "dictionary.containsValue() == false failed";
}
//test every
{
var a = [1, 2, 3];
var d = ["one": 1, "two": 2];
var counter = 0;
fn f(k, v) {
counter++;
return v;
}
assert a.every(f) == true, "array.every() == true failed";
assert d.every(f) == true, "dictionary.every() == true failed";
assert counter == 5, "Unexpected number of calls for _every() == true";
counter = 0;
a[1] = false;
d["two"] = false;
assert a.every(f) == false, "array.every() == false failed";
assert d.every(f) == false, "dictionary.every() == false failed";
assert counter == 4, "Unexpected number of calls for _every() == false";
}
//test filter
{
var a = [1, 2, 3, 4];
var d = ["one": 1, "two": 2, "three": 3, "four": 4];
fn f(k, v) {
return v % 2 == 0;
}
assert a.filter(f) == [2, 4], "array.filter() failed";
assert d.filter(f) == ["two": 2, "four": 4], "dictionary.filter() failed";
}
//test forEach
{
var counter = 0;
fn p(k, v) {
counter++;
print string k + ": " + string v;
}
var a = ["a", "b"];
var d = ["foo": 1, "bar": 2, "bazz": 3, "fizz": 4];
a.forEach(p);
assert counter == 2, "forEach ran an unusual number of times";
counter = 0;
d.forEach(p);
assert counter == 4, "forEach ran an unusual number of times";
}
//test getKeys
{
var d = ["foo": 1, "bar": 2];
var a = d.getKeys();
assert a.length() == 2, "_getKeys() length failed";
//NOTE: dependant on hash algorithm
assert a == ["bar", "foo"], "_getKeys() result failed";
}
//test getValues
{
var d = ["foo": 1, "bar": 2];
var a = d.getValues();
assert a.length() == 2, "_getValues() length failed";
//NOTE: dependant on hash algorithm
assert a == [2, 1], "_getValues() result failed";
}
//test map
{
//test map with toy functions
{
fn increment(k, v) {
return v + 1;
}
var a = [1, 2, 3];
var d = ["four": 4, "five": 5, "six": 6];
assert a.map(increment).map(increment).map(increment) == [4,5,6], "array.map() failed";
assert d.map(increment).map(increment).map(increment) == [8,9,7], "dictionary.map() failed";
}
//test map with native functions
{
//TODO: write some native functions for use with map
}
}
//test reduce
{
var a = [1, 2, 3, 4];
var d = ["one": 1, "two": 2, "three": 3, "four": 4];
fn f(acc, k, v) {
return acc + v;
}
assert a.reduce(0, f) == 10, "array.reduce() failed";
assert d.reduce(0, f) == 10, "dictionary.reduce() failed";
}
//test some
{
var a = [false, false, false];
var d = ["one": false, "two": false];
var counter = 0;
fn f(k, v) {
counter++;
return v;
}
assert a.some(f) == false, "array.some() == false failed";
assert d.some(f) == false, "dictionary.some() == false failed";
assert counter == 5, "Unexpected number of calls for _some() == false";
counter = 0;
a[1] = true;
d["two"] = true;
assert a.some(f) == true, "array.some() == true failed";
assert d.some(f) == true, "dictionary.some() == true failed";
assert counter == 4, "Unexpected number of calls for _some() == true";
}
//test toLower
{
assert "Hello World".toLower() == "hello world", "_toLower() failed";
}
//test toString
{
var a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
var s = a.toString();
assert s == "[[1,2,3],[4,5,6],[7,8,9]]", "array._toString() failed";
}
//test toUpper
{
assert "Hello World".toUpper() == "HELLO WORLD", "_toUpper() failed";
}
//test trim defaults
{
{
//test a bunch
fn test(s, pass) {
var result = s.trim();
assert result == pass, "_trim(" + result + ") failed";
}
test("hello world", "hello world");
test(" hello world", "hello world");
test("hello world ", "hello world");
test(" hello world ", "hello world");
test(" hello world", "hello world");
test("hello world ", "hello world");
test(" hello world ", "hello world");
test(" hello world", "hello world");
test("hello world ", "hello world");
test(" hello world ", "hello world");
//one for goot luck
assert " hello world ".trim() == "hello world", "hello world.trim() failed";
}
//test trim custom values
{
var chars = "heliod";
assert "hello world".trim(chars) == " wor", "custom _trim() failed";
}
//test trimBegin() & trimEnd()
assert " foo ".trimBegin() == "foo ", "string.trimBegin() failed";
assert " foo ".trimEnd() == " foo", "string.trimBegin() failed";
}
print "All good";
-40
View File
@@ -1,40 +0,0 @@
//test this logic for memory leaks
{
import compound;
import timer;
fn start(k, v) {
return startTimer();
}
fn check(k, v) {
var l = v.stopTimer();
print l.timerToString();
l.destroyTimer();
return v;
}
fn destroy(k, v) {
v.destroyTimer();
}
var arr = [1];
arr
.map(start)
.map(check)
.map(check)
.map(check)
.map(check)
.map(check)
.map(check)
.map(check)
.map(check)
.map(check)
.map(check)
.map(destroy)
;
}
print "All good";
+318 -4
View File
@@ -1,9 +1,323 @@
//test the standard library
{
import standard;
import standard;
//test clock
{
//this depends on external factors, so only check the length
assert clock().length() == 24, "clock() import failed";
assert clock().length() == 24, "clock().length() failed";
}
//test concat
{
//test array concat
{
var a = [1, 2, 3];
var b = [4, 5, 6];
var c = a.concat(b).concat(b);
assert c == [1, 2, 3, 4, 5, 6, 4, 5, 6], "array.concat() failed";
}
//test dictionary concat
{
var a = ["one" : 1, "two": 2, "three": 3];
var b = ["four" : 4, "five": 5, "six": 6];
var c = a.concat(b);
assert c.length() == 6, "dictionary.concat().length() failed";
assert c == ["one" : 1, "two": 2, "three": 3, "four" : 4, "five": 5, "six": 6], "dictionary.concat() comparison failed";
}
//test dictionary concat with clashing keys
{
var a = ["one" : 1, "two": 2, "three": 3, "random": 1];
var b = ["four" : 4, "five": 5, "six": 6, "random": 2];
var c = a.concat(b);
assert c["random"] == 1, "dictionary.concat() clashing keys failed";
}
//test string concat
{
var a = "foo";
var b = "bar";
var c = a.concat(b);
assert c == "foobar", "string.concat() failed";
}
}
//test containsKey
{
var d = ["one": 1, "two": 2];
assert d.containsKey("one") == true, "dictionary.containsKey() == true failed";
assert d.containsKey("three") == false, "dictionary.containsKey() == false failed";
}
//test containsValue
{
var a = [1, 2, 3];
var d = ["one": 1, "two": 2];
assert a.containsValue(1) == true, "array.containsValue() == true failed";
assert a.containsValue(5) == false, "array.containsValue() == false failed";
assert d.containsValue(1) == true, "dictionary.containsValue() == true failed";
assert d.containsValue(3) == false, "dictionary.containsValue() == false failed";
}
//test every
{
var a = [1, 2, 3];
var d = ["one": 1, "two": 2];
var counter = 0;
fn f(k, v) {
counter++;
return v;
}
assert a.every(f) == true, "array.every() == true failed";
assert d.every(f) == true, "dictionary.every() == true failed";
assert counter == 5, "Unexpected number of calls for _every() == true";
counter = 0;
a[1] = false;
d["two"] = false;
assert a.every(f) == false, "array.every() == false failed";
assert d.every(f) == false, "dictionary.every() == false failed";
assert counter == 4, "Unexpected number of calls for _every() == false";
}
//test filter
{
var a = [1, 2, 3, 4];
var d = ["one": 1, "two": 2, "three": 3, "four": 4];
fn f(k, v) {
return v % 2 == 0;
}
assert a.filter(f) == [2, 4], "array.filter() failed";
assert d.filter(f) == ["two": 2, "four": 4], "dictionary.filter() failed";
}
//test forEach
{
var counter = 0;
fn p(k, v) {
counter++;
print string k + ": " + string v;
}
var a = ["a", "b"];
var d = ["foo": 1, "bar": 2, "bazz": 3, "fizz": 4];
a.forEach(p);
assert counter == 2, "forEach ran an unusual number of times";
counter = 0;
d.forEach(p);
assert counter == 4, "forEach ran an unusual number of times";
}
//test getKeys
{
var d = ["foo": 1, "bar": 2];
var a = d.getKeys();
assert a.length() == 2, "_getKeys() length failed";
//NOTE: dependant on hash algorithm
assert a == ["bar", "foo"], "_getKeys() result failed";
}
//test getValues
{
var d = ["foo": 1, "bar": 2];
var a = d.getValues();
assert a.length() == 2, "_getValues() length failed";
//NOTE: dependant on hash algorithm
assert a == [2, 1], "_getValues() result failed";
}
//test indexOf
{
var a = [1, 2, 42, 3];
//results are zero-indexed
assert a.indexOf(42) == 2, "_indexOf() failed";
assert a.indexOf(4) == null, "_indexOf() == null failed";
}
//test map
{
//test map with toy functions
{
fn increment(k, v) {
return v + 1;
}
var a = [1, 2, 3];
var d = ["four": 4, "five": 5, "six": 6];
assert a.map(increment).map(increment).map(increment) == [4,5,6], "array.map() failed";
assert d.map(increment).map(increment).map(increment) == [8,9,7], "dictionary.map() failed";
}
//test map with native functions
{
//TODO: write some native functions for use with map
}
}
//test reduce
{
var a = [1, 2, 3, 4];
var d = ["one": 1, "two": 2, "three": 3, "four": 4];
fn f(acc, k, v) {
return acc + v;
}
assert a.reduce(0, f) == 10, "array.reduce() failed";
assert d.reduce(0, f) == 10, "dictionary.reduce() failed";
}
//test some
{
var a = [false, false, false];
var d = ["one": false, "two": false];
var counter = 0;
fn f(k, v) {
counter++;
return v;
}
assert a.some(f) == false, "array.some() == false failed";
assert d.some(f) == false, "dictionary.some() == false failed";
assert counter == 5, "Unexpected number of calls for _some() == false";
counter = 0;
a[1] = true;
d["two"] = true;
assert a.some(f) == true, "array.some() == true failed";
assert d.some(f) == true, "dictionary.some() == true failed";
assert counter == 4, "Unexpected number of calls for _some() == true";
}
//test sort
{
fn less(a, b) {
return a < b;
}
fn greater(a, b) {
return a > b;
}
var a = [7, 2, 1, 8, 6, 3, 5, 4];
var b = [7, 2, 1, 4, 6, 3, 5, 8];
var c = [1, 2, 3, 4, 5, 6, 7, 8];
var d = [7, 2, 1, 8, 6, 3, 5, 4];
a = a.sort(less);
b = b.sort(less);
c = c.sort(less);
d = d.sort(greater);
assert a == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) failed";
assert b == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) with pivot high failed";
assert c == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) pre-sorted array failed";
assert d == [8, 7, 6, 5, 4, 3, 2, 1], "array.sort(greater) failed";
}
//test toLower
{
assert "Hello World".toLower() == "hello world", "_toLower() failed";
}
//test toString
{
var a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
var s = a.toString();
assert s == "[[1,2,3],[4,5,6],[7,8,9]]", "array._toString() failed";
}
//test toUpper
{
assert "Hello World".toUpper() == "HELLO WORLD", "_toUpper() failed";
}
//test trim defaults
{
{
//test a bunch
fn test(s, pass) {
var result = s.trim();
assert result == pass, "_trim(" + result + ") failed";
}
test("hello world", "hello world");
test(" hello world", "hello world");
test("hello world ", "hello world");
test(" hello world ", "hello world");
test(" hello world", "hello world");
test("hello world ", "hello world");
test(" hello world ", "hello world");
test(" hello world", "hello world");
test("hello world ", "hello world");
test(" hello world ", "hello world");
//one for goot luck
assert " hello world ".trim() == "hello world", "hello world.trim() failed";
}
//test trim custom values
{
var chars = "heliod";
assert "hello world".trim(chars) == " wor", "custom _trim() failed";
}
//test trimBegin() & trimEnd()
assert " foo ".trimBegin() == "foo ", "string.trimBegin() failed";
assert " foo ".trimEnd() == " foo", "string.trimBegin() failed";
}
+22
View File
@@ -0,0 +1,22 @@
//polyfill the _insert function
fn _insert(self, k, v) {
var tmp1 = v;
var tmp2;
for (var i = k; i < self.length(); i++) {
tmp2 = self[i];
self[i] = tmp1;
tmp1 = tmp2;
}
self.push(tmp1);
return self;
}
var a = [1, 2, 3];
a = a.insert(1, 42);
assert a == [1, 42, 2, 3], "polyfill insert failed";
print "All good";
+23
View File
@@ -0,0 +1,23 @@
//polyfill the remove function
fn _remove(self, k) {
var result = [];
for (var i = 0; i <= k - 1; i++) {
result.push( self[i] );
}
for (var i = k + 1; i < self.length(); i++) {
result.push( self[i] );
}
return result;
}
var a = [1, 2, 3];
assert a.remove(0) == [2, 3], "polyfill remove(start) failed";
assert a.remove(1) == [1, 3], "polyfill remove(middle) failed";
assert a.remove(2) == [1, 2], "polyfill remove(end) failed";
print "All good";
+4
View File
@@ -117,6 +117,8 @@ int main() {
"dottify-bugfix.toy",
"functions.toy",
"index-arrays.toy",
"index-assignment-both-bugfix.toy",
"index-assignment-left-bugfix.toy",
"index-dictionaries.toy",
"index-strings.toy",
"jumps.toy",
@@ -128,6 +130,8 @@ int main() {
"native-functions.toy",
"or-chaining-bugfix.toy",
"panic-within-functions.toy",
"polyfill-insert.toy",
"polyfill-remove.toy",
"ternary-expressions.toy",
"types.toy",
NULL
+1 -7
View File
@@ -14,10 +14,8 @@
#include "../repl/repl_tools.h"
#include "../repl/lib_about.h"
#include "../repl/lib_compound.h"
#include "../repl/lib_runner.h"
#include "../repl/lib_standard.h"
#include "../repl/lib_timer.h"
//supress the print output
static void noPrintFn(const char* output) {
@@ -64,9 +62,7 @@ void runBinaryQuietly(const unsigned char* tb, size_t size) {
//inject the libs
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
Toy_injectNativeHook(&interpreter, "compound", Toy_hookCompound);
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
Toy_injectNativeHook(&interpreter, "timer", Toy_hookTimer);
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
Toy_runInterpreter(&interpreter, tb, size);
@@ -96,10 +92,8 @@ int main() {
Payload payloads[] = {
{"interactions.toy", "standard", Toy_hookStandard}, //interactions needs standard
{"about.toy", "about", Toy_hookAbout},
{"compound.toy", "compound", Toy_hookCompound},
{"runner.toy", "runner", Toy_hookRunner},
{"standard.toy", "standard", Toy_hookStandard},
{"timer.toy", "timer", Toy_hookTimer},
{"runner.toy", "runner", Toy_hookRunner},
{NULL, NULL, NULL}
};