diff options
| Commit | 9a7a8a31e75d1b85274ef46ca29714270062809e (patch) | |
|---|---|---|
| Author | 2018-11-14 19:47:37 +0200 | |
| Committer | 2018-11-14 19:47:37 +0200 | |
| Files | 587a120e78e7c0d50c381d8f38bf0665ed8733a7 | |
| IPL-9a7a8a31e75d1b85274ef46ca29714270062809e.tar IPL-9a7a8a31e75d1b85274ef46ca29714270062809e.tar.gz IPL-9a7a8a31e75d1b85274ef46ca29714270062809e.zip | ||
| Parent | 990a8f5e2c2d6e246acfd8b7a99ac1cbf4fb1675 (diff) | |
| Parent | e7c2a14f3e424f1ef1109d7634ece820a058e862 (diff) | |
Merge pull request #45 from SofiaCPP/feature/spasm_improvements
Feature/spasm improvements
25 files changed, 2788 insertions, 2430 deletions
| -rw-r--r-- | JSImpl/solution/JSImpl.sln | 1 | ||||
| -rw-r--r-- | JSImpl/solution/Makefile | 2 | ||||
| -rw-r--r-- | JSImpl/test/Test.make | 14 | ||||
| -rw-r--r-- | JSImpl/test/Test.vcxproj | 15 | ||||
| -rw-r--r-- | JSImpl/test/Test.vcxproj.filters | 1 | ||||
| -rw-r--r-- | JSImpl/test/genie.lua | 2 | ||||
| -rw-r--r-- | JSImpl/test/sprtTests.cpp | 220 | ||||
| -rw-r--r-- | spasm/solution/Makefile | 46 | ||||
| -rw-r--r-- | spasm/solution/spasm.sln | 37 | ||||
| -rw-r--r-- | spasm/solution/sprt.make | 12 | ||||
| -rw-r--r-- | spasm/solution/sprt.vcxproj | 4 | ||||
| -rw-r--r-- | spasm/solution/sprt.vcxproj.filters | 6 | ||||
| -rw-r--r-- | spasm/src/asm/lexer.cpp | 3853 | ||||
| -rw-r--r-- | spasm/src/asm/lexer.re | 33 | ||||
| -rw-r--r-- | spasm/src/asm/token.hpp | 8 | ||||
| -rw-r--r-- | spasm/src/dstack.cpp | 172 | ||||
| -rw-r--r-- | spasm/src/dstack.hpp | 46 | ||||
| -rw-r--r-- | spasm/src/frames.cpp | 130 | ||||
| -rw-r--r-- | spasm/src/frames.hpp | 51 | ||||
| -rw-r--r-- | spasm/src/main.cpp | 3 | ||||
| -rw-r--r-- | spasm/src/program.spa | 4 | ||||
| -rw-r--r-- | spasm/src/spasm.cpp | 427 | ||||
| -rw-r--r-- | spasm/src/spasm.hpp | 1 | ||||
| -rw-r--r-- | spasm/src/spasm_impl.hpp | 121 | ||||
| -rw-r--r-- | spasm/src/types.hpp | 9 |
diff --git a/JSImpl/solution/JSImpl.sln b/JSImpl/solution/JSImpl.sln index d4acff7..9915cf9 100644 --- a/JSImpl/solution/JSImpl.sln +++ b/JSImpl/solution/JSImpl.sln @@ -3,6 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "..\test\Test.vcxproj", "{45DC8C7C-3113-8E0D-DAFF-7310C6150A0F}"
ProjectSection(ProjectDependencies) = postProject
+ {AE0A9E7C-9A41-9F0D-432E-85102F441B0F} = {AE0A9E7C-9A41-9F0D-432E-85102F441B0F}
{19EA680D-85FE-90BE-4E80-341EBA538DEF} = {19EA680D-85FE-90BE-4E80-341EBA538DEF}
{EC34880F-5849-B0C0-21CB-53208D9EACF1} = {EC34880F-5849-B0C0-21CB-53208D9EACF1}
{B686840F-229B-ACC0-EB1C-502057F0A8F1} = {B686840F-229B-ACC0-EB1C-502057F0A8F1}
diff --git a/JSImpl/solution/Makefile b/JSImpl/solution/Makefile index 37c7a63..b920fc7 100644 --- a/JSImpl/solution/Makefile +++ b/JSImpl/solution/Makefile @@ -20,7 +20,7 @@ JSImpl: JSLib @echo "==== Building JSImpl ($(config)) ====" @${MAKE} --no-print-directory -C . -f JSImpl.make -Test: JSLib gtest gmock gtest_main +Test: sprt JSLib gtest gmock gtest_main @echo "==== Building Test ($(config)) ====" @${MAKE} --no-print-directory -C ../test -f Test.make diff --git a/JSImpl/test/Test.make b/JSImpl/test/Test.make index 4836496..4540d2d 100644 --- a/JSImpl/test/Test.make +++ b/JSImpl/test/Test.make @@ -47,7 +47,7 @@ ifeq ($(config),debug64) TARGETDIR = ../build/bin/Debug TARGET = $(TARGETDIR)/Test DEFINES += -D_SCL_SECURE_NO_WARNINGS - INCLUDES += -I"googletest/googletest/include" -I"googletest/googlemock/include" -I".." + INCLUDES += -I"googletest/googletest/include" -I"googletest/googlemock/include" -I".." -I"../../spasm/src" ALL_CPPFLAGS += $(CPPFLAGS) -MMD -MP -MP $(DEFINES) $(INCLUDES) ALL_ASMFLAGS += $(ASMFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Werror -Wall -Wextra -g -m64 ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Werror -Wall -Wextra -g -m64 @@ -56,7 +56,7 @@ ifeq ($(config),debug64) ALL_OBJCPPFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Werror -Wall -Wextra -g -m64 -std=c++14 ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES) ALL_LDFLAGS += $(LDFLAGS) -L"../build/bin/Debug" -L"." -m64 - LDDEPS += ../build/bin/Debug/libJSLib.a ../build/bin/Debug/libgtest.a ../build/bin/Debug/libgmock.a ../build/bin/Debug/libgtest_main.a + LDDEPS += ../build/bin/Debug/libsprt.a ../build/bin/Debug/libJSLib.a ../build/bin/Debug/libgtest.a ../build/bin/Debug/libgmock.a ../build/bin/Debug/libgtest_main.a LIBS += $(LDDEPS) -lpthread EXTERNAL_LIBS += LINKOBJS = $(OBJECTS) @@ -65,6 +65,7 @@ ifeq ($(config),debug64) $(OBJDIR)/LexerTests.o \ $(OBJDIR)/ParserTests.o \ $(OBJDIR)/empty.o \ + $(OBJDIR)/sprtTests.o \ define PREBUILDCMDS endef @@ -79,7 +80,7 @@ ifeq ($(config),release64) TARGETDIR = ../build/bin/Release TARGET = $(TARGETDIR)/Test DEFINES += -D_SCL_SECURE_NO_WARNINGS - INCLUDES += -I"googletest/googletest/include" -I"googletest/googlemock/include" -I".." + INCLUDES += -I"googletest/googletest/include" -I"googletest/googlemock/include" -I".." -I"../../spasm/src" ALL_CPPFLAGS += $(CPPFLAGS) -MMD -MP -MP $(DEFINES) $(INCLUDES) ALL_ASMFLAGS += $(ASMFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Werror -Wall -Wextra -g -O3 -m64 ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Werror -Wall -Wextra -g -O3 -m64 @@ -88,7 +89,7 @@ ifeq ($(config),release64) ALL_OBJCPPFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Werror -Wall -Wextra -g -O3 -m64 -std=c++14 ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES) ALL_LDFLAGS += $(LDFLAGS) -L"../build/bin/Release" -L"." -m64 - LDDEPS += ../build/bin/Release/libJSLib.a ../build/bin/Release/libgtest.a ../build/bin/Release/libgmock.a ../build/bin/Release/libgtest_main.a + LDDEPS += ../build/bin/Release/libsprt.a ../build/bin/Release/libJSLib.a ../build/bin/Release/libgtest.a ../build/bin/Release/libgmock.a ../build/bin/Release/libgtest_main.a LIBS += $(LDDEPS) -lpthread EXTERNAL_LIBS += LINKOBJS = $(OBJECTS) @@ -97,6 +98,7 @@ ifeq ($(config),release64) $(OBJDIR)/LexerTests.o \ $(OBJDIR)/ParserTests.o \ $(OBJDIR)/empty.o \ + $(OBJDIR)/sprtTests.o \ define PREBUILDCMDS endef @@ -168,6 +170,10 @@ $(OBJDIR)/empty.o: empty.cpp $(GCH) $(MAKEFILE) | $(OBJDIR)/. @echo $(notdir $<) $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -c "$<" +$(OBJDIR)/sprtTests.o: sprtTests.cpp $(GCH) $(MAKEFILE) | $(OBJDIR)/. + @echo $(notdir $<) + $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -c "$<" + -include $(OBJECTS:%.o=%.d) ifneq (,$(PCH)) -include $(OBJDIR)/$(notdir $(PCH)).d diff --git a/JSImpl/test/Test.vcxproj b/JSImpl/test/Test.vcxproj index 6bf7d68..3a7058a 100644 --- a/JSImpl/test/Test.vcxproj +++ b/JSImpl/test/Test.vcxproj @@ -21,11 +21,13 @@ <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
+ <PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
+ <PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -55,7 +57,7 @@ <ClCompile>
<AdditionalOptions> %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>googletest\googletest\include;googletest\googlemock\include;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>googletest\googletest\include;googletest\googlemock\include;..;..\..\spasm\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@@ -70,7 +72,7 @@ </ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>googletest\googletest\include;googletest\googlemock\include;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>googletest\googletest\include;googletest\googlemock\include;..;..\..\spasm\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -85,7 +87,7 @@ <ClCompile>
<AdditionalOptions> %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
- <AdditionalIncludeDirectories>googletest\googletest\include;googletest\googlemock\include;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>googletest\googletest\include;googletest\googlemock\include;..;..\..\spasm\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<StringPooling>true</StringPooling>
@@ -100,7 +102,7 @@ </ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>googletest\googletest\include;googletest\googlemock\include;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>googletest\googletest\include;googletest\googlemock\include;..;..\..\spasm\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -120,8 +122,13 @@ </ClCompile>
<ClCompile Include="ParserTests.cpp">
</ClCompile>
+ <ClCompile Include="sprtTests.cpp">
+ </ClCompile>
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\..\spasm\solution\sprt.vcxproj">
+ <Project>{AE0A9E7C-9A41-9F0D-432E-85102F441B0F}</Project>
+ </ProjectReference>
<ProjectReference Include="..\solution\JSLib.vcxproj">
<Project>{19EA680D-85FE-90BE-4E80-341EBA538DEF}</Project>
</ProjectReference>
diff --git a/JSImpl/test/Test.vcxproj.filters b/JSImpl/test/Test.vcxproj.filters index e1968c9..b7e0456 100644 --- a/JSImpl/test/Test.vcxproj.filters +++ b/JSImpl/test/Test.vcxproj.filters @@ -4,5 +4,6 @@ <ClCompile Include="empty.cpp" />
<ClCompile Include="LexerTests.cpp" />
<ClCompile Include="ParserTests.cpp" />
+ <ClCompile Include="sprtTests.cpp" />
</ItemGroup>
</Project>
diff --git a/JSImpl/test/genie.lua b/JSImpl/test/genie.lua index 262ed18..ba0f0c2 100644 --- a/JSImpl/test/genie.lua +++ b/JSImpl/test/genie.lua @@ -9,8 +9,10 @@ project 'Test' 'googletest/googletest/include', 'googletest/googlemock/include', '..', + '../../spasm/src', } links { + 'sprt', 'JSLib', 'gtest', 'gmock', diff --git a/JSImpl/test/sprtTests.cpp b/JSImpl/test/sprtTests.cpp new file mode 100644 index 0000000..7621ca3 --- /dev/null +++ b/JSImpl/test/sprtTests.cpp @@ -0,0 +1,220 @@ +#include <gtest/gtest.h> + +#include <spasm.hpp> +#include <sstream> + +using Spasm::OpCodes; + +struct SPRTTest : public ::testing::Test +{ + typedef std::vector<Spasm::byte> ByteCode; + + void Run(ByteCode& code) + { + Run(code.data(), code.size()); + } + + void Run(Spasm::byte* bytecode, size_t size) + { + VM.Initialize(size, bytecode, Input, Output); + ASSERT_EQ(Spasm::Spasm::RunResult::Success, VM.run()); + } + Spasm::byte Label(Spasm::byte label) const { + return 0x80 + label; + } + Spasm::Spasm VM; + std::istringstream Input; + std::ostringstream Output; +}; + +TEST_F(SPRTTest, Empty) +{ +} + +TEST_F(SPRTTest, Add) +{ + Spasm::byte bytecode[] = { + OpCodes::Const, 1, 6, + OpCodes::Const, 2, 7, + OpCodes::Add, 3, 1, 2, + OpCodes::Print, 3, + }; + + Run(bytecode, sizeof(bytecode)); + ASSERT_EQ(Output.str(), "13"); +} + +TEST_F(SPRTTest, Sub) +{ + Spasm::byte bytecode[] = { + OpCodes::Const, 1, 6, + OpCodes::Const, 2, 7, + OpCodes::Sub, 3, 1, 2, + OpCodes::Print, 3, + }; + + Run(bytecode, sizeof(bytecode)); + ASSERT_EQ(Output.str(), "-1"); +} + +TEST_F(SPRTTest, Div) +{ + Spasm::byte bytecode[] = { + OpCodes::Const, 1, 6, + OpCodes::Const, 2, 7, + OpCodes::Div, 3, 1, 2, + OpCodes::Print, 3, + }; + + Run(bytecode, sizeof(bytecode)); + ASSERT_EQ(Output.str(), "0"); +} + +TEST_F(SPRTTest, Mod) +{ + Spasm::byte bytecode[] = { + OpCodes::Const, 1, 6, + OpCodes::Const, 2, 7, + OpCodes::Mod, 3, 1, 2, + OpCodes::Print, 3, + }; + + Run(bytecode, sizeof(bytecode)); + ASSERT_EQ(Output.str(), "6"); +} + +TEST_F(SPRTTest, Mutliply) +{ + Spasm::byte bytecode[] = { + OpCodes::Const, 1, 6, + OpCodes::Const, 2, 7, + OpCodes::Mul, 3, 1, 2, + OpCodes::Print, 3, + }; + + Run(bytecode, sizeof(bytecode)); + ASSERT_EQ(Output.str(), "42"); +} + +TEST_F(SPRTTest, Less) +{ + Spasm::byte bytecode[] = { + OpCodes::Const, 1, 6, + OpCodes::Const, 2, 7, + OpCodes::Less, 3, 1, 2, + OpCodes::Less, 4, 2, 1, + OpCodes::Less, 5, 2, 2, + OpCodes::Print, 3, + OpCodes::Print, 4, + OpCodes::Print, 5, + }; + + Run(bytecode, sizeof(bytecode)); + ASSERT_EQ(Output.str(), "100"); +} + + +TEST_F(SPRTTest, LessEq) +{ + Spasm::byte bytecode[] = { + OpCodes::Const, 1, 6, + OpCodes::Const, 2, 7, + OpCodes::LessEq, 3, 1, 2, + OpCodes::LessEq, 4, 2, 1, + OpCodes::LessEq, 5, 2, 2, + OpCodes::Print, 3, + OpCodes::Print, 4, + OpCodes::Print, 5, + }; + + Run(bytecode, sizeof(bytecode)); + ASSERT_EQ(Output.str(), "101"); +} + +TEST_F(SPRTTest, Jump) +{ + Spasm::byte bytecode[] = { + OpCodes::Const, 1, 6, + OpCodes::Const, 2, 7, + OpCodes::LessEq, 3, 1, 2, + OpCodes::LessEq, 4, 2, 1, + OpCodes::Jump, 18, + OpCodes::Print, 5, + OpCodes::Print, 3, + }; + + Run(bytecode, sizeof(bytecode)); + ASSERT_EQ(Output.str(), "1"); +} + +TEST_F(SPRTTest, JumpTrue) +{ + Spasm::byte bytecode[] = { + OpCodes::Const, 1, 6, // 3 + OpCodes::Const, 2, 7, // 6 + OpCodes::Less, 3, 1, 2, // 10 + OpCodes::JumpT, 3, 17, // 13 + OpCodes::Print, 2, // 15 + OpCodes::Jump, 19, // 17 + OpCodes::Print, 1, // 19 + OpCodes::Halt, + }; + + Run(bytecode, sizeof(bytecode)); + ASSERT_EQ(Output.str(), "6"); +} + +TEST_F(SPRTTest, JumpFalse) +{ + Spasm::byte bytecode[] = { + OpCodes::Const, 1, 6, // 3 + OpCodes::Const, 2, 7, // 6 + OpCodes::Less, 3, 1, 2, // 10 + OpCodes::JumpF, 3, 17, // 13 + OpCodes::Print, 2, // 15 + OpCodes::Jump, 19, // 17 + OpCodes::Print, 1, // 19 + OpCodes::Halt, + }; + + Run(bytecode, sizeof(bytecode)); + ASSERT_EQ(Output.str(), "7"); +} + +TEST_F(SPRTTest, Call) +{ + Spasm::byte bytecode[] = { + OpCodes::Alloc, 5, // 2 + OpCodes::Const, 1, 0, // 5 + OpCodes::Const, 2, 6, // 8 + OpCodes::Const, 3, 7, // 11 + OpCodes::Const, 4, 2, // 14 + OpCodes::Push, 3, // 16 + OpCodes::Push, 2, // 18 + OpCodes::Push, 4, // 20 + OpCodes::Call, 25, // 22 + OpCodes::Print, 4, // 24 + OpCodes::Halt, // 25 + OpCodes::Print, 0, // 27 + OpCodes::Print, -1, // 29 + OpCodes::Print, -2, // 31 + OpCodes::Mul, 1, -2, -1,// 33 + OpCodes::Ret, 1, // 35 + }; + + Run(bytecode, sizeof(bytecode)); + ASSERT_EQ(Output.str(), "26742"); +} + +TEST_F(SPRTTest, Read) +{ + Spasm::byte bytecode[] = { + OpCodes::Read, 1, + OpCodes::Print, 1, + }; + + Input.str("42"); + Run(bytecode, sizeof(bytecode)); + ASSERT_EQ(Output.str(), "42"); +} + diff --git a/spasm/solution/Makefile b/spasm/solution/Makefile deleted file mode 100644 index 665d251..0000000 --- a/spasm/solution/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# GNU Make solution makefile autogenerated by GENie -# Type "make help" for usage help - -ifndef config - config=debug64 -endif -export config - -PROJECTS := spasm sprt sprun - -.PHONY: all clean help $(PROJECTS) - -all: $(PROJECTS) - -sprt: - @echo "==== Building sprt ($(config)) ====" - @${MAKE} --no-print-directory -C . -f sprt.make - -spasm: - @echo "==== Building spasm ($(config)) ====" - @${MAKE} --no-print-directory -C . -f spasm.make - -sprun: sprt - @echo "==== Building sprun ($(config)) ====" - @${MAKE} --no-print-directory -C . -f sprun.make - -clean: - @${MAKE} --no-print-directory -C . -f sprt.make clean - @${MAKE} --no-print-directory -C . -f spasm.make clean - @${MAKE} --no-print-directory -C . -f sprun.make clean - -help: - @echo "Usage: make [config=name] [target]" - @echo "" - @echo "CONFIGURATIONS:" - @echo " debug64" - @echo " release64" - @echo "" - @echo "TARGETS:" - @echo " all (default)" - @echo " clean" - @echo " sprt" - @echo " spasm" - @echo " sprun" - @echo "" - @echo "For more information, see https://github.com/bkaradzic/genie" diff --git a/spasm/solution/spasm.sln b/spasm/solution/spasm.sln deleted file mode 100644 index 1f36001..0000000 --- a/spasm/solution/spasm.sln +++ /dev/null @@ -1,37 +0,0 @@ -
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sprun", "sprun.vcxproj", "{FD605F10-6975-87C1-32F7-2A219ECA83F2}"
- ProjectSection(ProjectDependencies) = postProject
- {AE0A9E7C-9A41-9F0D-432E-85102F441B0F} = {AE0A9E7C-9A41-9F0D-432E-85102F441B0F}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sprt", "sprt.vcxproj", "{AE0A9E7C-9A41-9F0D-432E-85102F441B0F}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spasm", "spasm.vcxproj", "{69185F10-D52C-87C1-9EAE-2A210A8283F2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|x64 = Debug|x64
- Release|x64 = Release|x64
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {FD605F10-6975-87C1-32F7-2A219ECA83F2}.Debug|x64.ActiveCfg = Debug|x64
- {FD605F10-6975-87C1-32F7-2A219ECA83F2}.Debug|x64.Build.0 = Debug|x64
- {FD605F10-6975-87C1-32F7-2A219ECA83F2}.Release|x64.ActiveCfg = Release|x64
- {FD605F10-6975-87C1-32F7-2A219ECA83F2}.Release|x64.Build.0 = Release|x64
- {AE0A9E7C-9A41-9F0D-432E-85102F441B0F}.Debug|x64.ActiveCfg = Debug|x64
- {AE0A9E7C-9A41-9F0D-432E-85102F441B0F}.Debug|x64.Build.0 = Debug|x64
- {AE0A9E7C-9A41-9F0D-432E-85102F441B0F}.Release|x64.ActiveCfg = Release|x64
- {AE0A9E7C-9A41-9F0D-432E-85102F441B0F}.Release|x64.Build.0 = Release|x64
- {69185F10-D52C-87C1-9EAE-2A210A8283F2}.Debug|x64.ActiveCfg = Debug|x64
- {69185F10-D52C-87C1-9EAE-2A210A8283F2}.Debug|x64.Build.0 = Debug|x64
- {69185F10-D52C-87C1-9EAE-2A210A8283F2}.Release|x64.ActiveCfg = Release|x64
- {69185F10-D52C-87C1-9EAE-2A210A8283F2}.Release|x64.Build.0 = Release|x64
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- EndGlobalSection
-EndGlobal
diff --git a/spasm/solution/sprt.make b/spasm/solution/sprt.make index 5607193..10f5b52 100644 --- a/spasm/solution/sprt.make +++ b/spasm/solution/sprt.make @@ -61,8 +61,6 @@ ifeq ($(config),debug64) LINKOBJS = $(OBJECTS) LINKCMD = $(AR) -rcs $(TARGET) OBJECTS := \ - $(OBJDIR)/src/dstack.o \ - $(OBJDIR)/src/frames.o \ $(OBJDIR)/src/spasm.o \ define PREBUILDCMDS @@ -92,8 +90,6 @@ ifeq ($(config),release64) LINKOBJS = $(OBJECTS) LINKCMD = $(AR) -rcs $(TARGET) OBJECTS := \ - $(OBJDIR)/src/dstack.o \ - $(OBJDIR)/src/frames.o \ $(OBJDIR)/src/spasm.o \ define PREBUILDCMDS @@ -159,14 +155,6 @@ $(GCH_OBJC): $(PCH) $(MAKEFILE) | $(OBJDIR) $(SILENT) $(CXX) $(ALL_OBJCPPFLAGS) -x objective-c++-header $(DEFINES) $(INCLUDES) -o "$@" -c "$<" endif -$(OBJDIR)/src/dstack.o: ../src/dstack.cpp $(GCH) $(MAKEFILE) | $(OBJDIR)/src - @echo $(notdir $<) - $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -c "$<" - -$(OBJDIR)/src/frames.o: ../src/frames.cpp $(GCH) $(MAKEFILE) | $(OBJDIR)/src - @echo $(notdir $<) - $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -c "$<" - $(OBJDIR)/src/spasm.o: ../src/spasm.cpp $(GCH) $(MAKEFILE) | $(OBJDIR)/src @echo $(notdir $<) $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -c "$<" diff --git a/spasm/solution/sprt.vcxproj b/spasm/solution/sprt.vcxproj index 5d4d050..2698c10 100644 --- a/spasm/solution/sprt.vcxproj +++ b/spasm/solution/sprt.vcxproj @@ -110,12 +110,8 @@ </Link>
</ItemDefinitionGroup>
<ItemGroup>
- <ClCompile Include="..\src\dstack.cpp">
- </ClCompile>
<ClCompile Include="..\src\spasm.cpp">
</ClCompile>
- <ClCompile Include="..\src\frames.cpp">
- </ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/spasm/solution/sprt.vcxproj.filters b/spasm/solution/sprt.vcxproj.filters index 5ed0d15..d9f8e3a 100644 --- a/spasm/solution/sprt.vcxproj.filters +++ b/spasm/solution/sprt.vcxproj.filters @@ -6,14 +6,8 @@ </Filter>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="..\src\dstack.cpp">
- <Filter>src</Filter>
- </ClCompile>
<ClCompile Include="..\src\spasm.cpp">
<Filter>src</Filter>
</ClCompile>
- <ClCompile Include="..\src\frames.cpp">
- <Filter>src</Filter>
- </ClCompile>
</ItemGroup>
</Project>
diff --git a/spasm/src/asm/lexer.cpp b/spasm/src/asm/lexer.cpp index 659beae..86384b3 100644 --- a/spasm/src/asm/lexer.cpp +++ b/spasm/src/asm/lexer.cpp @@ -1,1664 +1,2189 @@ -/* Generated by re2c 1.1.1 on Tue Nov 06 22:08:59 2018 */
-#line 1 "lexer.re"
-#include <iostream>
-
-#include "lexer.hpp"
-
-#include "token.hpp"
-
-namespace SpasmImpl
-{
- namespace ASM
- {
- //! Namespace for all lexical analisys classes
- namespace Lexer
- {
-
- Lexer::Lexer (std::istream & _file, size_t _buffer_size)
- : file (&_file), buffer_size (_buffer_size), state (unsigned(-1)),
- lineno (0)
- {
- buffer = new char[buffer_size];
- cursor = limit = marker = token_start = NULL;
- }
-
- Lexer::~Lexer ()
- {
- delete [] buffer;
- }
-
- bool Lexer::tokenize (TokenStream &ts)
- {
-#line 43 "lexer.re"
-
-
-
-
- while (1) {
-
-
-#line 41 "lexer.cpp"
- {
- char yych;
- if ((limit - cursor) < 6) return true;
- yych = *cursor;
- switch (yych) {
- case 0x00: goto yy2;
- case '\t':
- case ' ': goto yy6;
- case '\n': goto yy9;
- case '%': goto yy11;
- case '*': goto yy13;
- case '+': goto yy15;
- case '-': goto yy17;
- case '/': goto yy19;
- case '0': goto yy21;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy23;
- case '<': goto yy25;
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'k':
- case 'm':
- case 'n':
- case 'o':
- case 'q':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- case 'c': goto yy30;
- case 'd': goto yy31;
- case 'j': goto yy32;
- case 'l': goto yy33;
- case 'p': goto yy34;
- case 'r': goto yy35;
- case 's': goto yy36;
- default: goto yy4;
- }
-yy2:
- ++cursor;
-#line 233 "lexer.re"
- {
- ts.push_token (Token (Token::endinput, lineno));
-
- break;
- }
-#line 130 "lexer.cpp"
-yy4:
- ++cursor;
-#line 239 "lexer.re"
- {
- return false;
- }
-#line 137 "lexer.cpp"
-yy6:
- ++cursor;
- if (limit <= cursor) return true;
- yych = *cursor;
- switch (yych) {
- case '\t':
- case ' ': goto yy6;
- default: goto yy8;
- }
-yy8:
-#line 220 "lexer.re"
- {
- token_start = cursor;
-
- continue;
- }
-#line 154 "lexer.cpp"
-yy9:
- ++cursor;
-#line 226 "lexer.re"
- {
- ++lineno;
- token_start = cursor;
-
- continue;
- }
-#line 164 "lexer.cpp"
-yy11:
- ++cursor;
-#line 137 "lexer.re"
- {
- ts.push_token (Token (Token::modulus, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 174 "lexer.cpp"
-yy13:
- ++cursor;
-#line 123 "lexer.re"
- {
- ts.push_token (Token (Token::multiply, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 184 "lexer.cpp"
-yy15:
- ++cursor;
-#line 109 "lexer.re"
- {
- ts.push_token (Token (Token::plus, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 194 "lexer.cpp"
-yy17:
- yych = *++cursor;
- switch (yych) {
- case '0': goto yy37;
- default: goto yy18;
- }
-yy18:
-#line 116 "lexer.re"
- {
- ts.push_token (Token (Token::minus, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 209 "lexer.cpp"
-yy19:
- ++cursor;
-#line 130 "lexer.re"
- {
- ts.push_token (Token (Token::divide, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 219 "lexer.cpp"
-yy21:
- yych = *(marker = ++cursor);
- switch (yych) {
- case 'X':
- case 'x': goto yy38;
- default: goto yy22;
- }
-yy22:
-#line 58 "lexer.re"
- {
- ts.push_token (Token (Token::integer, lineno,
- token_start, cursor));
- token_start = cursor;
-
- continue;
- }
-#line 236 "lexer.cpp"
-yy23:
- ++cursor;
- if (limit <= cursor) return true;
- yych = *cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy23;
- default: goto yy22;
- }
-yy25:
- yych = *++cursor;
- switch (yych) {
- case '=': goto yy40;
- default: goto yy26;
- }
-yy26:
-#line 198 "lexer.re"
- {
- ts.push_token (Token (Token::less, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 268 "lexer.cpp"
-yy27:
- ++cursor;
- if (limit <= cursor) return true;
- yych = *cursor;
-yy28:
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy29;
- }
-yy29:
-#line 212 "lexer.re"
- {
- ts.push_token (Token (Token::ident, lineno, token_start,
- cursor));
- token_start = cursor;
-
- continue;
- }
-#line 349 "lexer.cpp"
-yy30:
- yych = *++cursor;
- switch (yych) {
- case 'a': goto yy42;
- default: goto yy28;
- }
-yy31:
- yych = *++cursor;
- switch (yych) {
- case 'u': goto yy43;
- default: goto yy28;
- }
-yy32:
- yych = *++cursor;
- switch (yych) {
- case 'm': goto yy44;
- default: goto yy28;
- }
-yy33:
- yych = *++cursor;
- switch (yych) {
- case 'a': goto yy45;
- case 'o': goto yy46;
- default: goto yy28;
- }
-yy34:
- yych = *++cursor;
- switch (yych) {
- case 'o': goto yy47;
- case 'r': goto yy48;
- case 'u': goto yy49;
- default: goto yy28;
- }
-yy35:
- yych = *++cursor;
- switch (yych) {
- case 'e': goto yy50;
- default: goto yy28;
- }
-yy36:
- yych = *++cursor;
- switch (yych) {
- case 't': goto yy51;
- default: goto yy28;
- }
-yy37:
- ++cursor;
- goto yy22;
-yy38:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f': goto yy52;
- default: goto yy39;
- }
-yy39:
- cursor = marker;
- goto yy22;
-yy40:
- ++cursor;
-#line 192 "lexer.re"
- {
- ts.push_token (Token (Token::lesseq, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 437 "lexer.cpp"
-yy42:
- yych = *++cursor;
- switch (yych) {
- case 'l': goto yy55;
- default: goto yy28;
- }
-yy43:
- yych = *++cursor;
- switch (yych) {
- case 'p': goto yy56;
- default: goto yy28;
- }
-yy44:
- yych = *++cursor;
- switch (yych) {
- case 'p': goto yy58;
- default: goto yy28;
- }
-yy45:
- yych = *++cursor;
- switch (yych) {
- case 'b': goto yy60;
- default: goto yy28;
- }
-yy46:
- yych = *++cursor;
- switch (yych) {
- case 'a': goto yy61;
- default: goto yy28;
- }
-yy47:
- yych = *++cursor;
- switch (yych) {
- case 'p': goto yy62;
- default: goto yy28;
- }
-yy48:
- yych = *++cursor;
- switch (yych) {
- case 'i': goto yy64;
- default: goto yy28;
- }
-yy49:
- yych = *++cursor;
- switch (yych) {
- case 's': goto yy65;
- default: goto yy28;
- }
-yy50:
- yych = *++cursor;
- switch (yych) {
- case 'a': goto yy66;
- case 't': goto yy67;
- default: goto yy28;
- }
-yy51:
- yych = *++cursor;
- switch (yych) {
- case 'o': goto yy69;
- default: goto yy28;
- }
-yy52:
- ++cursor;
- if (limit <= cursor) return true;
- yych = *cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f': goto yy52;
- default: goto yy54;
- }
-yy54:
-#line 66 "lexer.re"
- {
- ts.push_token (Token (Token::xinteger, lineno,
- token_start, cursor));
- token_start = cursor;
-
- continue;
- }
-#line 537 "lexer.cpp"
-yy55:
- yych = *++cursor;
- switch (yych) {
- case 'l': goto yy70;
- default: goto yy28;
- }
-yy56:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy57;
- }
-yy57:
-#line 88 "lexer.re"
- {
- ts.push_token (Token (Token::dup, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 620 "lexer.cpp"
-yy58:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- case 'f': goto yy72;
- case 't': goto yy74;
- default: goto yy59;
- }
-yy59:
-#line 158 "lexer.re"
- {
- ts.push_token (Token (Token::go, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 697 "lexer.cpp"
-yy60:
- yych = *++cursor;
- switch (yych) {
- case 'e': goto yy76;
- default: goto yy28;
- }
-yy61:
- yych = *++cursor;
- switch (yych) {
- case 'd': goto yy77;
- default: goto yy28;
- }
-yy62:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy63;
- }
-yy63:
-#line 81 "lexer.re"
- {
- ts.push_token (Token (Token::pop, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 786 "lexer.cpp"
-yy64:
- yych = *++cursor;
- switch (yych) {
- case 'n': goto yy79;
- default: goto yy28;
- }
-yy65:
- yych = *++cursor;
- switch (yych) {
- case 'h': goto yy80;
- default: goto yy28;
- }
-yy66:
- yych = *++cursor;
- switch (yych) {
- case 'd': goto yy82;
- default: goto yy28;
- }
-yy67:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy68;
- }
-yy68:
-#line 172 "lexer.re"
- {
- ts.push_token (Token (Token::ret, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 881 "lexer.cpp"
-yy69:
- yych = *++cursor;
- switch (yych) {
- case 'r': goto yy84;
- default: goto yy28;
- }
-yy70:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy71;
- }
-yy71:
-#line 165 "lexer.re"
- {
- ts.push_token (Token (Token::call, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 964 "lexer.cpp"
-yy72:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy73;
- }
-yy73:
-#line 151 "lexer.re"
- {
- ts.push_token (Token (Token::gofalse, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 1041 "lexer.cpp"
-yy74:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy75;
- }
-yy75:
-#line 144 "lexer.re"
- {
- ts.push_token (Token (Token::gotrue, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 1118 "lexer.cpp"
-yy76:
- yych = *++cursor;
- switch (yych) {
- case 'l': goto yy85;
- default: goto yy28;
- }
-yy77:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy78;
- }
-yy78:
-#line 179 "lexer.re"
- {
- ts.push_token (Token (Token::load, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 1201 "lexer.cpp"
-yy79:
- yych = *++cursor;
- switch (yych) {
- case 't': goto yy87;
- default: goto yy28;
- }
-yy80:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy81;
- }
-yy81:
-#line 74 "lexer.re"
- {
- ts.push_token (Token (Token::push, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 1284 "lexer.cpp"
-yy82:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy83;
- }
-yy83:
-#line 95 "lexer.re"
- {
- ts.push_token (Token (Token::read, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 1361 "lexer.cpp"
-yy84:
- yych = *++cursor;
- switch (yych) {
- case 'e': goto yy89;
- default: goto yy28;
- }
-yy85:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy86;
- }
-yy86:
-#line 205 "lexer.re"
- {
- ts.push_token (Token (Token::label, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 1444 "lexer.cpp"
-yy87:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy88;
- }
-yy88:
-#line 102 "lexer.re"
- {
- ts.push_token (Token (Token::print, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 1521 "lexer.cpp"
-yy89:
- yych = *++cursor;
- switch (yych) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy27;
- default: goto yy90;
- }
-yy90:
-#line 186 "lexer.re"
- {
- ts.push_token (Token (Token::store, lineno));
- token_start = cursor;
-
- continue;
- }
-#line 1598 "lexer.cpp"
- }
-#line 243 "lexer.re"
-
- }
- return true;
- }
-
- /*!
- ** Fills up the buffer when neccessary.
- ** Note the buffer is always filled to the maximum, not just the
- ** number of bytes neccessary for the lexer to continue.
- **
- ** \param nbytes - the number of bytes
- */
-
- void Lexer::buffer_grow (size_t new_size)
- {
- char *new_buffer = new char[new_size];
-
- std::copy (buffer, limit, new_buffer);
-
- token_start = new_buffer + (token_start - buffer);
- cursor = new_buffer + (cursor - buffer);
- limit = new_buffer + new_size;
-
- buffer_size = new_size;
-
- delete [] buffer;
- buffer = new_buffer;
- }
-
- void Lexer::read (size_t nbytes)
- {
- if (token_start + nbytes > limit) { // we need larger buffer
- buffer_grow (token_start - buffer + nbytes);
- }
-
- std::copy (token_start, limit, buffer);
- cursor -= token_start - buffer;
- char *old_limit = limit - (token_start - buffer);
- token_start = buffer;
-
- file->read (old_limit, limit - old_limit);
- if (file->eof ()) {
- size_t bytes = file->gcount ();
- std::fill (old_limit + bytes, limit, '\0');
- }
- }
-
- void Lexer::buffer_init ()
- {
- file->read (buffer, buffer_size);
- if (file->eof ()) {
- size_t bytes = file->gcount ();
- std::fill (buffer + bytes, buffer + buffer_size, '\0');
- }
-
- cursor = marker = token_start = buffer;
- limit = buffer + buffer_size;
- }
-
-
- } // namespace Lexer
-
- } // namespace ASM
-} // namespace SpasmImpl
-
+/* Generated by re2c 1.1.1 on Mon Nov 12 23:00:12 2018 */ +#line 1 "spasm/src/asm/lexer.re" +#include <iostream> + +#include "lexer.hpp" + +#include "token.hpp" + +namespace SpasmImpl +{ +namespace ASM +{ +//! Namespace for all lexical analisys classes +namespace Lexer +{ +Lexer::Lexer(std::istream& _file, size_t _buffer_size) + : file(&_file), buffer_size(_buffer_size), state(unsigned(-1)), lineno(0) +{ + buffer = new char[buffer_size]; + cursor = limit = marker = token_start = NULL; +} + +Lexer::~Lexer() +{ + delete[] buffer; +} + +bool Lexer::tokenize(TokenStream& ts) +{ +#line 43 "spasm/src/asm/lexer.re" + + while (1) + { +#line 41 "spasm/src/asm/lexer.cpp" + { + char yych; + if ((limit - cursor) < 6) + return true; + yych = *cursor; + switch (yych) + { + case 0x00: + goto yy2; + case '\t': + case ' ': + goto yy6; + case '\n': + goto yy9; + case '-': + goto yy11; + case '0': + goto yy12; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + goto yy14; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'b': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'k': + case 'n': + case 'o': + case 'q': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + case 'a': + goto yy19; + case 'c': + goto yy20; + case 'd': + goto yy21; + case 'j': + goto yy22; + case 'l': + goto yy23; + case 'm': + goto yy24; + case 'p': + goto yy25; + case 'r': + goto yy26; + case 's': + goto yy27; + default: + goto yy4; + } + yy2: + ++cursor; +#line 220 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::endinput, lineno)); + + break; + } +#line 125 "spasm/src/asm/lexer.cpp" + yy4: + ++cursor; + yy5: +#line 226 "spasm/src/asm/lexer.re" + { + return false; + } +#line 133 "spasm/src/asm/lexer.cpp" + yy6: + ++cursor; + if (limit <= cursor) + return true; + yych = *cursor; + switch (yych) + { + case '\t': + case ' ': + goto yy6; + default: + goto yy8; + } + yy8: +#line 207 "spasm/src/asm/lexer.re" + { + token_start = cursor; + + continue; + } +#line 150 "spasm/src/asm/lexer.cpp" + yy9: + ++cursor; +#line 213 "spasm/src/asm/lexer.re" + { + ++lineno; + token_start = cursor; + + continue; + } +#line 160 "spasm/src/asm/lexer.cpp" + yy11: + yych = *++cursor; + switch (yych) + { + case '0': + goto yy28; + default: + goto yy5; + } + yy12: + yych = *(marker = ++cursor); + switch (yych) + { + case 'X': + case 'x': + goto yy29; + default: + goto yy13; + } + yy13: +#line 58 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::integer, lineno, token_start, cursor)); + token_start = cursor; + + continue; + } +#line 183 "spasm/src/asm/lexer.cpp" + yy14: + ++cursor; + if (limit <= cursor) + return true; + yych = *cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + goto yy14; + default: + goto yy13; + } + yy16: + ++cursor; + if (limit <= cursor) + return true; + yych = *cursor; + yy17: + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy18; + } + yy18: +#line 199 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::ident, lineno, token_start, cursor)); + token_start = cursor; + + continue; + } +#line 281 "spasm/src/asm/lexer.cpp" + yy19: + yych = *++cursor; + switch (yych) + { + case 'd': + goto yy31; + default: + goto yy17; + } + yy20: + yych = *++cursor; + switch (yych) + { + case 'a': + goto yy32; + default: + goto yy17; + } + yy21: + yych = *++cursor; + switch (yych) + { + case 'i': + goto yy33; + case 'u': + goto yy34; + default: + goto yy17; + } + yy22: + yych = *++cursor; + switch (yych) + { + case 'm': + goto yy35; + default: + goto yy17; + } + yy23: + yych = *++cursor; + switch (yych) + { + case 'a': + goto yy36; + case 'e': + goto yy37; + default: + goto yy17; + } + yy24: + yych = *++cursor; + switch (yych) + { + case 'o': + goto yy38; + case 'u': + goto yy39; + default: + goto yy17; + } + yy25: + yych = *++cursor; + switch (yych) + { + case 'o': + goto yy40; + case 'r': + goto yy41; + case 'u': + goto yy42; + default: + goto yy17; + } + yy26: + yych = *++cursor; + switch (yych) + { + case 'e': + goto yy43; + default: + goto yy17; + } + yy27: + yych = *++cursor; + switch (yych) + { + case 'u': + goto yy44; + default: + goto yy17; + } + yy28: + ++cursor; + goto yy13; + yy29: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + goto yy45; + default: + goto yy30; + } + yy30: + cursor = marker; + goto yy13; + yy31: + yych = *++cursor; + switch (yych) + { + case 'd': + goto yy48; + default: + goto yy17; + } + yy32: + yych = *++cursor; + switch (yych) + { + case 'l': + goto yy50; + default: + goto yy17; + } + yy33: + yych = *++cursor; + switch (yych) + { + case 'v': + goto yy51; + default: + goto yy17; + } + yy34: + yych = *++cursor; + switch (yych) + { + case 'p': + goto yy53; + default: + goto yy17; + } + yy35: + yych = *++cursor; + switch (yych) + { + case 'p': + goto yy55; + default: + goto yy17; + } + yy36: + yych = *++cursor; + switch (yych) + { + case 'b': + goto yy57; + default: + goto yy17; + } + yy37: + yych = *++cursor; + switch (yych) + { + case 'q': + goto yy58; + case 's': + goto yy60; + default: + goto yy17; + } + yy38: + yych = *++cursor; + switch (yych) + { + case 'd': + goto yy61; + default: + goto yy17; + } + yy39: + yych = *++cursor; + switch (yych) + { + case 'l': + goto yy63; + default: + goto yy17; + } + yy40: + yych = *++cursor; + switch (yych) + { + case 'p': + goto yy65; + default: + goto yy17; + } + yy41: + yych = *++cursor; + switch (yych) + { + case 'i': + goto yy67; + default: + goto yy17; + } + yy42: + yych = *++cursor; + switch (yych) + { + case 's': + goto yy68; + default: + goto yy17; + } + yy43: + yych = *++cursor; + switch (yych) + { + case 'a': + goto yy69; + case 't': + goto yy70; + default: + goto yy17; + } + yy44: + yych = *++cursor; + switch (yych) + { + case 'b': + goto yy72; + default: + goto yy17; + } + yy45: + ++cursor; + if (limit <= cursor) + return true; + yych = *cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + goto yy45; + default: + goto yy47; + } + yy47: +#line 66 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::xinteger, lineno, token_start, cursor)); + token_start = cursor; + + continue; + } +#line 498 "spasm/src/asm/lexer.cpp" + yy48: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy49; + } + yy49: +#line 109 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::plus, lineno)); + token_start = cursor; + + continue; + } +#line 575 "spasm/src/asm/lexer.cpp" + yy50: + yych = *++cursor; + switch (yych) + { + case 'l': + goto yy74; + default: + goto yy17; + } + yy51: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy52; + } + yy52: +#line 130 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::divide, lineno)); + token_start = cursor; + + continue; + } +#line 658 "spasm/src/asm/lexer.cpp" + yy53: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy54; + } + yy54: +#line 88 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::dup, lineno)); + token_start = cursor; + + continue; + } +#line 735 "spasm/src/asm/lexer.cpp" + yy55: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + case 'f': + goto yy76; + case 't': + goto yy78; + default: + goto yy56; + } + yy56: +#line 158 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::jmp, lineno)); + token_start = cursor; + + continue; + } +#line 812 "spasm/src/asm/lexer.cpp" + yy57: + yych = *++cursor; + switch (yych) + { + case 'e': + goto yy80; + default: + goto yy17; + } + yy58: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy59; + } + yy59: +#line 179 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::lesseq, lineno)); + token_start = cursor; + + continue; + } +#line 895 "spasm/src/asm/lexer.cpp" + yy60: + yych = *++cursor; + switch (yych) + { + case 's': + goto yy81; + default: + goto yy17; + } + yy61: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy62; + } + yy62: +#line 137 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::modulus, lineno)); + token_start = cursor; + + continue; + } +#line 978 "spasm/src/asm/lexer.cpp" + yy63: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy64; + } + yy64: +#line 123 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::multiply, lineno)); + token_start = cursor; + + continue; + } +#line 1055 "spasm/src/asm/lexer.cpp" + yy65: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy66; + } + yy66: +#line 81 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::pop, lineno)); + token_start = cursor; + + continue; + } +#line 1132 "spasm/src/asm/lexer.cpp" + yy67: + yych = *++cursor; + switch (yych) + { + case 'n': + goto yy83; + default: + goto yy17; + } + yy68: + yych = *++cursor; + switch (yych) + { + case 'h': + goto yy84; + default: + goto yy17; + } + yy69: + yych = *++cursor; + switch (yych) + { + case 'd': + goto yy86; + default: + goto yy17; + } + yy70: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy71; + } + yy71: +#line 172 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::ret, lineno)); + token_start = cursor; + + continue; + } +#line 1227 "spasm/src/asm/lexer.cpp" + yy72: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy73; + } + yy73: +#line 116 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::minus, lineno)); + token_start = cursor; + + continue; + } +#line 1304 "spasm/src/asm/lexer.cpp" + yy74: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy75; + } + yy75: +#line 165 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::call, lineno)); + token_start = cursor; + + continue; + } +#line 1381 "spasm/src/asm/lexer.cpp" + yy76: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy77; + } + yy77: +#line 151 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::jmpf, lineno)); + token_start = cursor; + + continue; + } +#line 1458 "spasm/src/asm/lexer.cpp" + yy78: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy79; + } + yy79: +#line 144 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::jmpt, lineno)); + token_start = cursor; + + continue; + } +#line 1535 "spasm/src/asm/lexer.cpp" + yy80: + yych = *++cursor; + switch (yych) + { + case 'l': + goto yy88; + default: + goto yy17; + } + yy81: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy82; + } + yy82: +#line 185 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::less, lineno)); + token_start = cursor; + + continue; + } +#line 1618 "spasm/src/asm/lexer.cpp" + yy83: + yych = *++cursor; + switch (yych) + { + case 't': + goto yy90; + default: + goto yy17; + } + yy84: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy85; + } + yy85: +#line 74 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::push, lineno)); + token_start = cursor; + + continue; + } +#line 1701 "spasm/src/asm/lexer.cpp" + yy86: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy87; + } + yy87: +#line 95 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::read, lineno)); + token_start = cursor; + + continue; + } +#line 1778 "spasm/src/asm/lexer.cpp" + yy88: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy89; + } + yy89: +#line 192 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::label, lineno)); + token_start = cursor; + + continue; + } +#line 1855 "spasm/src/asm/lexer.cpp" + yy90: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy16; + default: + goto yy91; + } + yy91: +#line 102 "spasm/src/asm/lexer.re" + { + ts.push_token(Token(Token::print, lineno)); + token_start = cursor; + + continue; + } +#line 1932 "spasm/src/asm/lexer.cpp" + } +#line 230 "spasm/src/asm/lexer.re" + } + return true; +} + +/*! +** Fills up the buffer when neccessary. +** Note the buffer is always filled to the maximum, not just the +** number of bytes neccessary for the lexer to continue. +** +** \param nbytes - the number of bytes +*/ + +void Lexer::buffer_grow(size_t new_size) +{ + char* new_buffer = new char[new_size]; + + std::copy(buffer, limit, new_buffer); + + token_start = new_buffer + (token_start - buffer); + cursor = new_buffer + (cursor - buffer); + limit = new_buffer + new_size; + + buffer_size = new_size; + + delete[] buffer; + buffer = new_buffer; +} + +void Lexer::read(size_t nbytes) +{ + if (token_start + nbytes > limit) + { // we need larger buffer + buffer_grow(token_start - buffer + nbytes); + } + + std::copy(token_start, limit, buffer); + cursor -= token_start - buffer; + char* old_limit = limit - (token_start - buffer); + token_start = buffer; + + file->read(old_limit, limit - old_limit); + if (file->eof()) + { + size_t bytes = file->gcount(); + std::fill(old_limit + bytes, limit, '\0'); + } +} + +void Lexer::buffer_init() +{ + file->read(buffer, buffer_size); + if (file->eof()) + { + size_t bytes = file->gcount(); + std::fill(buffer + bytes, buffer + buffer_size, '\0'); + } + + cursor = marker = token_start = buffer; + limit = buffer + buffer_size; +} + +} // namespace Lexer + +} // namespace ASM +} // namespace SpasmImpl diff --git a/spasm/src/asm/lexer.re b/spasm/src/asm/lexer.re index c6f87ea..c54d54f 100644 --- a/spasm/src/asm/lexer.re +++ b/spasm/src/asm/lexer.re @@ -106,35 +106,35 @@ XINTEGER { continue; } -"+" { +"add" { ts.push_token (Token (Token::plus, lineno)); token_start = cursor; continue; } -"-" { +"sub" { ts.push_token (Token (Token::minus, lineno)); token_start = cursor; continue; } -"*" { +"mul" { ts.push_token (Token (Token::multiply, lineno)); token_start = cursor; continue; } -"/" { +"div" { ts.push_token (Token (Token::divide, lineno)); token_start = cursor; continue; } -"%" { +"mod" { ts.push_token (Token (Token::modulus, lineno)); token_start = cursor; @@ -142,21 +142,21 @@ XINTEGER { } "jmpt" { - ts.push_token (Token (Token::gotrue, lineno)); + ts.push_token (Token (Token::jmpt, lineno)); token_start = cursor; continue; } "jmpf" { - ts.push_token (Token (Token::gofalse, lineno)); + ts.push_token (Token (Token::jmpf, lineno)); token_start = cursor; continue; } "jmp" { - ts.push_token (Token (Token::go, lineno)); + ts.push_token (Token (Token::jmp, lineno)); token_start = cursor; continue; @@ -176,26 +176,13 @@ XINTEGER { continue; } -"load" { - ts.push_token (Token (Token::load, lineno)); - token_start = cursor; - - continue; - } - -"store" { - ts.push_token (Token (Token::store, lineno)); - token_start = cursor; - - continue; - } -"<=" { +"leq" { ts.push_token (Token (Token::lesseq, lineno)); token_start = cursor; continue; } -"<" { +"less" { ts.push_token (Token (Token::less, lineno)); token_start = cursor; diff --git a/spasm/src/asm/token.hpp b/spasm/src/asm/token.hpp index 4ef7ce0..5f3b6b9 100644 --- a/spasm/src/asm/token.hpp +++ b/spasm/src/asm/token.hpp @@ -4,9 +4,9 @@ #include <string> #define TOKENS \ + TOK(dup) \ TOK(push) \ TOK(pop) \ - TOK(dup) \ TOK(print) \ TOK(read) \ TOK(plus) \ @@ -14,9 +14,9 @@ TOK(multiply) \ TOK(divide) \ TOK(modulus) \ - TOK(gotrue) \ - TOK(gofalse) \ - TOK(go) \ + TOK(jmpt) \ + TOK(jmpf) \ + TOK(jmp) \ TOK(call) \ TOK(ret) \ TOK(load) \ diff --git a/spasm/src/dstack.cpp b/spasm/src/dstack.cpp deleted file mode 100644 index 93592ed..0000000 --- a/spasm/src/dstack.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include "dstack.hpp" - -#include <algorithm> - -namespace SpasmImpl -{ -Dstack::Dstack() : bottom(NULL), tos(NULL), s_size(0) {} - -Dstack::Dstack(const Dstack& ds) : s_size(ds.s_size) -{ - copy_dstack(ds); -} - -Dstack& Dstack::operator=(const Dstack& ds) -{ - if (this != &ds) - { - if (bottom) - delete[] bottom; - s_size = ds.s_size; - copy_dstack(ds); - } - return *this; -} - -Dstack::~Dstack() -{ - if (bottom) - delete[] bottom; -} - -/** - * Makes the stack occupy new_size bytes - * \param new_size new size for the stack - */ -void Dstack::reserve(size_t new_size) -{ - size_t offset = tos - bottom; - byte* new_bottom = new byte[new_size]; - if (bottom) - { - std::copy(bottom, bottom + std::min(s_size, new_size), new_bottom); - delete[] bottom; - } - bottom = new_bottom; - tos = new_bottom + offset; - s_size = new_size; -} - -/*! -** Pushes x in the stack. -** If the stack is full its size is doubled. -** \param x data_t object to be pushed on the stack -*/ -void Dstack::push(data_t x) -{ - if (bottom + s_size < tos + sizeof(data_t)) - reserve((s_size ? s_size : sizeof(data_t)) * 2); - *((data_t*)tos) = x; - tos += sizeof(data_t); -} - -/*! -** Pushes the object of size x_size bytes pointed by x in the stack. -** If the stack is full its size is doubled (or more is x_size is greater -** than the size of the stack). -** \param x pointer to the element to be pushed on the stack -** \param x_size size of the element -*/ -void Dstack::push(byte* x, size_t x_size) -{ - if (bottom + s_size < tos + x_size) - reserve(s_size + ((s_size > x_size) ? s_size : x_size)); - std::copy(x, x + x_size, tos); - tos += x_size; -} - -/*! -** Pops an object of size x_size from the stack. -** The object is written to the place pointed by x. -** -** \param x pointer to the place for popping -** \param x_size size of the object to be popped -*/ -void Dstack::pop(void* x, size_t x_size) -{ - if (tos - x_size >= bottom) - { - std::copy(tos - x_size, tos, (byte*)x); - tos -= x_size; - } -} - -/*! -** \return a single data_t object, popping it from the stack. -*/ -data_t Dstack::pop() -{ - data_t x{}; - if (tos - sizeof(data_t) >= bottom) - { - tos -= sizeof(data_t); - x = *((data_t*)tos); - } - return x; -} - -/*! -** \return copy of the data_t object that is on top of the stack -*/ -data_t Dstack::top() const -{ - data_t x{}; - if (tos - sizeof(data_t) >= bottom) - { - x = *((data_t*)(tos - sizeof(data_t))); - } - return x; -} - -/*! -** \return the size of the stack in bytes -*/ -size_t Dstack::size() const -{ - return tos - bottom; -} - -/*! -** \return the space reserved for the stack in bytes -*/ -size_t Dstack::reserved() const -{ - return s_size; -} - -/*! -** Frees unused memory. Note that it is not always possible because memory -** management is done with new / delete -*/ - -void Dstack::strip_memory() -{ - reserve(size()); -} - -/*! -** \return true if the stack is empty -*/ -bool Dstack::empty() const -{ - return tos - bottom == 0; -} - -/*! -** Creates a copy of ds -** -** \param ds data stack to be copied -*/ -void Dstack::copy_dstack(const Dstack& ds) -{ - if (ds.bottom) - { - bottom = new byte[ds.s_size]; - tos = bottom + (ds.tos - ds.bottom); - std::copy(ds.bottom, ds.tos, bottom); - } - else - bottom = tos = NULL; -} - -} // namespace SpasmImpl diff --git a/spasm/src/dstack.hpp b/spasm/src/dstack.hpp deleted file mode 100644 index 850b66b..0000000 --- a/spasm/src/dstack.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef DSTACK_HPP -#define DSTACK_HPP - -#include "types.hpp" - -namespace SpasmImpl -{ -//! class representing the data stack - -/*! The class is quite simple stack. It is byte-orientatied - every push -** and pop is done in bytes with no taking care of any byte order! -*/ -class Dstack -{ - public: - Dstack(); - Dstack(const Dstack&); - Dstack& operator=(const Dstack&); - ~Dstack(); - void push(data_t); - void push(byte*, size_t); - void pop(void*, size_t); - data_t pop(); - data_t top() const; - - void reserve(size_t); - void strip_memory(); - size_t size() const; - size_t reserved() const; - bool empty() const; - - private: - void copy_dstack(const Dstack&); - - //! pointer to the bottom of the stack - byte* bottom; - - //! pointer to the top of the stack - byte* tos; - - //! size of the stack in bytes - size_t s_size; -}; -} // namespace SpasmImpl - -#endif // #ifndef DSTACK_HPP diff --git a/spasm/src/frames.cpp b/spasm/src/frames.cpp deleted file mode 100644 index 8b7c891..0000000 --- a/spasm/src/frames.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include <algorithm> - -#include "types.hpp" - -#include "frames.hpp" - -namespace SpasmImpl -{ -FrameStack::FrameStack() : base_ptr(NULL), frame_ptr(NULL), g_size(0), c_size(0) -{ -} - -FrameStack::FrameStack(const FrameStack& fs) - : g_size(fs.g_size), c_size(fs.c_size), fstack(fs.fstack) -{ - copy_fstack(fs); -} - -FrameStack::~FrameStack() -{ - delete_fstack(); -} - -FrameStack& FrameStack::operator=(const FrameStack& fs) -{ - if (this != &fs) - { - delete_fstack(); - copy_fstack(fs); - g_size = fs.g_size; - c_size = fs.c_size; - fstack = fs.fstack; - } - return *this; -} - -/*! -** Deletes the frame stack -*/ -void FrameStack::delete_fstack() -{ - if (base_ptr) - delete[] base_ptr; -} - -/*! -** Copies the frame stack fs -** -** \param fs - the frame stack to be copied -*/ -void FrameStack::copy_fstack(const FrameStack& fs) -{ - base_ptr = new data_t[fs.g_size]; - std::copy(fs.base_ptr, fs.frame_ptr + fs.c_size, base_ptr); - frame_ptr = base_ptr + (fs.frame_ptr - fs.base_ptr); -} - -/*! -** Returns a data_t object from the current frame -** -** \param index - index of the data_t object -** \return const reference to the object -*/ -const data_t& FrameStack::operator[](size_t index) const -{ - return frame_ptr[index]; -} - -/*! -** Returns a data_t object from the current frame -** -** \param index - index of the data_t object -** \return reference to the object -*/ -data_t& FrameStack::operator[](size_t index) -{ - return frame_ptr[index]; -} - -/*! -** Removes the current frame from the stack. -** It is called when a function does return. -*/ -void FrameStack::pop_frame() -{ - if (fstack.empty()) - { - frame_ptr = base_ptr; - c_size = 0; - } - else - { - data_t* new_frame_ptr = base_ptr + fstack.top(); - fstack.pop(); - c_size = frame_ptr - new_frame_ptr; - frame_ptr = new_frame_ptr; - } -} - -/*! -** Creates (pushes on the stack) new frame of fsize data_t objects -** -** \param fsize - size in data_t objects of the new frame -*/ -void FrameStack::new_frame(size_t fsize) -{ - if (frame_ptr + c_size + fsize > base_ptr + g_size) - { - size_t new_size = g_size + std::max(g_size, c_size + fsize); - data_t* new_base = new data_t[new_size]; - if (base_ptr) - { - std::copy(base_ptr, frame_ptr + c_size, new_base); - delete[] base_ptr; - } - frame_ptr = new_base + (frame_ptr - base_ptr); - base_ptr = new_base; - } - fstack.push(frame_ptr - base_ptr); - c_size = fsize; -} - -/*! -** \return true if the stack is empty -*/ -bool FrameStack::empty() const -{ - return frame_ptr == base_ptr && c_size == 0; -} -} // namespace SpasmImpl diff --git a/spasm/src/frames.hpp b/spasm/src/frames.hpp deleted file mode 100644 index 14d1d14..0000000 --- a/spasm/src/frames.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef FRAMES_HPP -#define FRAMES_HPP - -#include <stack> - -#include "types.hpp" - -namespace SpasmImpl -{ -//! Class representing the stack frame for a function -/*! -** The class is implemented as a simple stack of frames while each frame -** is built up by a number of data_t objects -*/ -class FrameStack -{ - public: - FrameStack(); - FrameStack(const FrameStack&); - ~FrameStack(); - FrameStack& operator=(const FrameStack&); - - const data_t& operator[](size_t) const; - data_t& operator[](size_t); - void pop_frame(); - void new_frame(size_t); - bool empty() const; - - private: - //! pointer to the base of the stack - data_t* base_ptr; - - //! pointer to the beginning of the current frame - data_t* frame_ptr; - - //! size of the whole stack in data_t objects - size_t g_size; - - //! size of the current frame in data_t objects - size_t c_size; - - //! stack of the offsets between frames in the stack. - std::stack<size_t> fstack; - - void copy_fstack(const FrameStack&); - void delete_fstack(); -}; - -} // namespace SpasmImpl - -#endif // #ifndef FRAMES_HPP diff --git a/spasm/src/main.cpp b/spasm/src/main.cpp index 17bb322..a6465a6 100644 --- a/spasm/src/main.cpp +++ b/spasm/src/main.cpp @@ -23,7 +23,8 @@ int main(int argc, const char* argv[]) std::cout << std::hex << (int)bytecode[i] << ' '; std::cout << std::endl; - Spasm::Spasm vm(len, bytecode.get()); + Spasm::Spasm vm; + vm.Initialize(len, bytecode.get()); vm.run(); diff --git a/spasm/src/program.spa b/spasm/src/program.spa index d92456a..d3149a1 100644 --- a/spasm/src/program.spa +++ b/spasm/src/program.spa @@ -3,10 +3,10 @@ label next dup push 1 < -gotrue bye +jmpt bye push 1 - dup print -go next +jmp next label bye diff --git a/spasm/src/spasm.cpp b/spasm/src/spasm.cpp index e67c975..d06552d 100644 --- a/spasm/src/spasm.cpp +++ b/spasm/src/spasm.cpp @@ -1,37 +1,12 @@ #include <algorithm> +#include <cassert> #include <iostream> #include "spasm.hpp" namespace SpasmImpl { -PC_t Spasm::op_size = 21; -// Be sure the same number is on the previous and next lines -Operation Spasm::operations[] = {NULL, - &Spasm::push, - &Spasm::pop, - &Spasm::dup, - &Spasm::print, - &Spasm::read, - &Spasm::plus, - &Spasm::minus, - &Spasm::multiply, - &Spasm::divide, - &Spasm::modulus, - &Spasm::gotrue, - &Spasm::gofalse, - &Spasm::go, - &Spasm::call, - &Spasm::ret, - &Spasm::load, - &Spasm::store, - &Spasm::less, - &Spasm::lesseq}; - -Spasm::Spasm() - : pc(0), bc_size(0), bytecode(NULL), istr(&std::cin), ostr(&std::cout) -{ -} +Spasm::Spasm() {} /*! ** Constructs new Spasm object @@ -41,106 +16,187 @@ Spasm::Spasm() ** \param _istr - input stream for the machine ** \param _ostr - output stream for the machine */ -Spasm::Spasm(PC_t _bc_size, - const byte* _bytecode, - std::istream& _istr, - std::ostream& _ostr) - : pc(0), bc_size(_bc_size), istr(&_istr), ostr(&_ostr) -{ - bytecode = new byte[bc_size]; - std::copy(_bytecode, _bytecode + bc_size, bytecode); -} - -Spasm::Spasm(const Spasm& m) - : pc(m.pc), - bc_size(m.bc_size), - data_stack(m.data_stack), - return_stack(m.return_stack), - frame(m.frame), - istr(m.istr), - ostr(m.ostr) -{ - copybc(m); -} +void Spasm::Initialize(PC_t _bc_size, + const byte* _bytecode, + std::istream& _istr, + std::ostream& _ostr) -Spasm::~Spasm() { - deleteobj(); + m_PC = 0; + m_ByteCode.assign(_bytecode, _bytecode + _bc_size); + istr = &_istr; + ostr = &_ostr; + data_stack.resize(1024); + m_SP = &data_stack[0]; + m_FP = &data_stack[0]; } -Spasm& Spasm::operator=(const Spasm& m) -{ - if (this != &m) - { - deleteobj(); - data_stack = m.data_stack; - return_stack = m.return_stack; - frame = m.frame; - istr = m.istr; - ostr = m.ostr; - copybc(m); - } - return *this; -} - -/*! -** Copies the bytecode of another machine m -** -** \param m - the machine from the bytecode is copied -*/ - -void Spasm::copybc(const Spasm& m) -{ - bytecode = new byte[bc_size]; - std::copy(m.bytecode, m.bytecode + bc_size, bytecode); -} - -/*! -** Deletes the machine -*/ -void Spasm::deleteobj() -{ - if (bytecode) - delete[] bytecode; -} - -/*! -** Returns the dstack, so that it can be examined after execution -** -** \return const reference to the data stack -*/ -const Dstack& Spasm::get_dstack() const -{ - return data_stack; -} +Spasm::~Spasm() {} /*! -** Starts the machine. The machine stops if it reaches an invalid opcode +** Runs the machine. The machine stops if it reaches an invalid opcode ** or opcode 0 or the pc reaches beyond the end of the bytecode. +** @return error code for success or failure */ -void Spasm::run() +Spasm::RunResult Spasm::run() { - while (pc < bc_size) + const auto codeSize = m_ByteCode.size(); + while (m_PC < codeSize) { - if (bytecode[pc] > 0 && bytecode[pc] < op_size) - (this->*operations[bytecode[pc]])(); - else + const auto instruction = m_ByteCode[m_PC++]; + const auto opcode = OpCodes(instruction & 0x3f); + const auto size = instruction >> 6; + assert(size == 0 && "no long args yet"); + switch (opcode) { - std::cerr << "opcode got to " << int(bytecode[pc]) << std::endl; - break; + case OpCodes::Halt: + return RunResult::Success; + case OpCodes::Dup: + dup(); + break; + case OpCodes::Pop: + pop(); + break; + case OpCodes::PopTo: + break; + case OpCodes::Push: + { + const auto arg0 = read_reg(size); + push(arg0); + break; + } + case OpCodes::Alloc: + { + const auto count = PC_t(read_reg(size)); + for (PC_t i = 0; i < count; ++i) + { + push_data(0); + } + break; + } + case OpCodes::Print: + { + const auto arg0 = read_reg(size); + print(arg0); + break; + } + case OpCodes::Read: + { + const auto arg0 = read_reg(size); + read(arg0); + break; + } + case OpCodes::Call: + { + const auto arg0 = read_reg(size); + call(arg0); + break; + } + case OpCodes::Ret: + { + const auto arg0 = read_reg(size); + ret(arg0); + break; + } + case OpCodes::Jump: + { + const auto arg0 = read_reg(size); + go(arg0); + break; + } + case OpCodes::JumpT: + { + const auto arg0 = read_reg(size); + const auto arg1 = read_reg(size); + gotrue(arg0, arg1); + break; + } + case OpCodes::JumpF: + { + const auto arg0 = read_reg(size); + const auto arg1 = read_reg(size); + gofalse(arg0, arg1); + break; + } + case OpCodes::Const: + { + const auto reg = read_reg(size); + const auto value = read_number(size); + set_local(reg, value); + break; + } + case OpCodes::Add: + { + const auto arg0 = read_reg(size); + const auto arg1 = read_reg(size); + const auto arg2 = read_reg(size); + plus(arg0, arg1, arg2); + break; + } + case OpCodes::Sub: + { + const auto arg0 = read_reg(size); + const auto arg1 = read_reg(size); + const auto arg2 = read_reg(size); + minus(arg0, arg1, arg2); + break; + } + case OpCodes::Mul: + { + const auto arg0 = read_reg(size); + const auto arg1 = read_reg(size); + const auto arg2 = read_reg(size); + multiply(arg0, arg1, arg2); + break; + } + case OpCodes::Div: + { + const auto arg0 = read_reg(size); + const auto arg1 = read_reg(size); + const auto arg2 = read_reg(size); + divide(arg0, arg1, arg2); + break; + } + case OpCodes::Mod: + { + const auto arg0 = read_reg(size); + const auto arg1 = read_reg(size); + const auto arg2 = read_reg(size); + modulus(arg0, arg1, arg2); + break; + } + case OpCodes::Less: + { + const auto arg0 = read_reg(size); + const auto arg1 = read_reg(size); + const auto arg2 = read_reg(size); + less(arg0, arg1, arg2); + break; + } + case OpCodes::LessEq: + { + const auto arg0 = read_reg(size); + const auto arg1 = read_reg(size); + const auto arg2 = read_reg(size); + lesseq(arg0, arg1, arg2); + break; + } + default: + { + std::cerr << opcode << ": not implemented" << std::endl; + return RunResult::NotImplemented; + } } - ++pc; } + return RunResult::Success; } /*! ** Pushes the next data_t object on the data stack */ -void Spasm::push() +void Spasm::push(reg_t reg) { - ++pc; - data_stack.push(*reinterpret_cast<data_t*>(bytecode + pc)); - pc += sizeof(data_t) - 1; + push_data(get_local(reg)); } /*! @@ -148,7 +204,7 @@ void Spasm::push() */ void Spasm::pop() { - data_stack.pop(); + --m_SP; } /*! @@ -156,82 +212,72 @@ void Spasm::pop() */ void Spasm::dup() { - data_stack.push(data_stack.top()); + push_data(*(m_SP - 1)); } /*! ** Reads a data_t object from the input stream and pushes it on the data ** stack. */ -void Spasm::read() +void Spasm::read(reg_t reg) { data_t x; *istr >> x; - data_stack.push(x); + set_local(reg, x); } /*! ** Pops a data_t object from the data stack and prints it on the output ** stream. */ -void Spasm::print() +void Spasm::print(reg_t reg) { - *ostr << data_stack.pop(); + *ostr << get_local(reg); } /*! ** Pops two data objects from the data stack and pushes their sum on the ** data stack. */ -void Spasm::plus() +void Spasm::plus(reg_t a0, reg_t a1, reg_t a2) { - data_t x, y = data_stack.pop(); - x = data_stack.pop(); - data_stack.push(x + y); + set_local(a0, get_local(a1) + get_local(a2)); } /*! ** Pops two data objects from the data stack and pushes their difference ** on the data stack. */ -void Spasm::minus() +void Spasm::minus(reg_t a0, reg_t a1, reg_t a2) { - data_t x, y = data_stack.pop(); - x = data_stack.pop(); - data_stack.push(x - y); + set_local(a0, get_local(a1) - get_local(a2)); } /*! ** Pops two data objects from the data stack and pushes their product ** on the data stack. */ -void Spasm::multiply() +void Spasm::multiply(reg_t a0, reg_t a1, reg_t a2) { - data_t x, y = data_stack.pop(); - x = data_stack.pop(); - data_stack.push(x * y); + set_local(a0, get_local(a1) * get_local(a2)); } /*! ** Pops two data objects from the data stack and pushes their division ** on the data stack. */ -void Spasm::divide() +void Spasm::divide(reg_t a0, reg_t a1, reg_t a2) { - data_t x, y = data_stack.pop(); - x = data_stack.pop(); - data_stack.push(x / y); + set_local(a0, get_local(a1) / get_local(a2)); } /*! ** Pops two data objects from the data stack and pushes their modulus ** on the data stack. */ -void Spasm::modulus() +void Spasm::modulus(reg_t a0, reg_t a1, reg_t a2) { - data_t x, y = data_stack.pop(); - x = data_stack.pop(); - data_stack.push(x % y); + set_local(a0, get_local(a1) % get_local(a2)); } /*! @@ -239,13 +285,12 @@ void Spasm::modulus() ** If the data_t object on top of the data stack evaluates to true ** execution continues from the place pointed by number in the next bytes */ -void Spasm::gotrue() +void Spasm::gotrue(reg_t a0, reg_t a1) { - ++pc; - if (data_stack.pop()) - pc = *(reinterpret_cast<PC_t*>(bytecode + pc)) - 1; - else - pc += sizeof(size_t) - 1; + if (get_local(a0)) + { + m_PC = a1; + } } /*! @@ -253,48 +298,48 @@ void Spasm::gotrue() ** If the data_t object on top of the data stack evaluates to false ** execution continues from the place pointed by number in the next bytes */ -void Spasm::gofalse() +void Spasm::gofalse(reg_t a0, reg_t a1) { - ++pc; - if (!data_stack.pop()) - pc = *(reinterpret_cast<PC_t*>(bytecode + pc)) - 1; - else - pc += sizeof(size_t) - 1; + if (!get_local(a0)) + { + m_PC = a1; + } } /*! ** Unconditional execution. ** Execution continues from the opcode pointed by the next bytes */ -void Spasm::go() +void Spasm::go(reg_t a0) { - ++pc; - pc = *(reinterpret_cast<PC_t*>(bytecode + pc)) - 1; + m_PC = a0; } /*! ** Function call. A new frame with the specified size is created, the ** return address is saved in the return stack and the new pc is loaded. */ -void Spasm::call() +void Spasm::call(reg_t a0) { - size_t fs; // new frame size - return_stack.push(pc); // using the ++pc in run() - data_stack.pop(&fs, sizeof(fs)); - data_stack.pop(&pc, sizeof(pc)); - frame.new_frame(fs); - --pc; // the ++pc in run() + Frame call{m_PC, PC_t(m_FP - &data_stack[0]), + m_SP - &data_stack[0] - PC_t(*(m_SP - 1)) - 1}; + m_Frames.push(std::move(call)); + m_FP = m_SP - 1; + go(a0); } /*! ** Function return. The frame of the current function is destroyed and the ** saved return address is loaded in the pc */ -void Spasm::ret() +void Spasm::ret(reg_t reg) { - pc = return_stack.top(); - return_stack.pop(); - frame.pop_frame(); + Frame parent = m_Frames.top(); + m_Frames.pop(); + m_SP = &data_stack[parent.StackPointer]; + *(m_SP - 1) = m_FP[reg]; + m_FP = &data_stack[parent.FramePointer]; + m_PC = parent.ReturnAddress; } /*! @@ -303,10 +348,7 @@ void Spasm::ret() */ void Spasm::load() { - size_t offset; - - data_stack.pop(&offset, sizeof(offset)); - data_stack.push(frame[offset]); + assert(false && "not-implemented"); } /*! @@ -314,35 +356,64 @@ void Spasm::load() */ void Spasm::store() { - data_t value = data_stack.pop(); - size_t offset; - - data_stack.pop(&offset, sizeof(offset)); - frame[offset] = value; + assert(false && "not-implemented"); } /*! ** Compares the values on top of the stack. Pushes 1 if the value before ** the top of the stack is less than that on top of the stack. */ -void Spasm::less() +void Spasm::less(reg_t a0, reg_t a1, reg_t a2) { - data_t y = data_stack.pop(); - data_t x = data_stack.pop(); - - data_stack.push(x < y); + set_local(a0, get_local(a1) < get_local(a2)); } /*! ** Compares the values on top of the stack. Pushes 1 if the value before ** the top of the stack is less than or equal to that on top of the stack. */ -void Spasm::lesseq() +void Spasm::lesseq(reg_t a0, reg_t a1, reg_t a2) { - data_t y = data_stack.pop(); - data_t x = data_stack.pop(); + set_local(a0, get_local(a1) <= get_local(a2)); +} + +data_t Spasm::get_local(reg_t reg) +{ + assert(&data_stack[0] <= (m_FP + reg)); + assert((m_FP + reg) < &data_stack[data_stack.size() - 1]); + return m_FP[reg]; +} - data_stack.push(x <= y); +void Spasm::set_local(reg_t reg, data_t data) +{ + assert(&data_stack[0] <= (m_FP + reg)); + assert((m_FP + reg) < &data_stack[data_stack.size() - 1]); + m_FP[reg] = data; +} + +data_t Spasm::pop_data() +{ + auto result = data_stack.back(); + data_stack.pop_back(); + return result; +} + +void Spasm::push_data(data_t data) +{ + assert(m_SP < &data_stack[data_stack.size() - 1]); + *(m_SP++) = data; +} + +reg_t Spasm::read_reg(size_t size) +{ + assert(size == 0); + return m_ByteCode[m_PC++]; +} + +data_t Spasm::read_number(size_t size) +{ + assert(size == 0); + return m_ByteCode[m_PC++]; } } // namespace SpasmImpl diff --git a/spasm/src/spasm.hpp b/spasm/src/spasm.hpp index 7468bd8..85b2e8d 100644 --- a/spasm/src/spasm.hpp +++ b/spasm/src/spasm.hpp @@ -8,6 +8,7 @@ namespace Spasm using SpasmImpl::byte; using SpasmImpl::PC_t; using SpasmImpl::Spasm; +using SpasmImpl::OpCodes; } // namespace Spasm #endif // #ifndef SPASM_HPP diff --git a/spasm/src/spasm_impl.hpp b/spasm/src/spasm_impl.hpp index 78c5d08..75fb4c4 100644 --- a/spasm/src/spasm_impl.hpp +++ b/spasm/src/spasm_impl.hpp @@ -3,12 +3,37 @@ #include <iostream> -#include "dstack.hpp" -#include "frames.hpp" #include "types.hpp" namespace SpasmImpl { +enum OpCodes : char +{ + Halt, + Dup, + Pop, + PopTo, + Push, + Alloc, + Print, + Read, + Call, + Ret, + Jump, + JumpT, + JumpF, + Const, + Add, + Sub, + Mul, + Div, + Mod, + Less, + LessEq, + LastIndex = LessEq, +}; +static_assert(LastIndex < 0x3f, "Too many opcodes"); + //! The Abstract Stack Machine /*! ** The machine contains a data stack for operations and control flow and @@ -19,42 +44,48 @@ class Spasm { public: Spasm(); - Spasm(PC_t, + void Initialize(PC_t, const byte*, std::istream& = std::cin, std::ostream& = std::cout); - Spasm(const Spasm&); ~Spasm(); - Spasm& operator=(const Spasm&); + Spasm(const Spasm&) = delete; + Spasm& operator=(const Spasm&) = delete; - void run(); - - const Dstack& get_dstack() const; + enum RunResult { + Success, + Exception, + NotImplemented, + }; + RunResult run(); private: - //! Operations (opcodes) of the machine - static Operation operations[]; - - //! number of operations - static PC_t op_size; - //! Program counter - points the current opcode - PC_t pc; - - //! size of the program bytecode - PC_t bc_size; + PC_t m_PC = 0; + typedef SPVector<byte> ByteCode; //! bytecode of the program - byte* bytecode; + ByteCode m_ByteCode; + + typedef SPVector<data_t> DataStack; + //! stack for storing arguments and local variables + DataStack data_stack; + + //! Stack pointer - always the top of the stack + data_t* m_SP = nullptr; - //! Data stack for arithmetic operations and control flow - Dstack data_stack; + //! Frame pointer - the start of the stack for the current function + data_t* m_FP = nullptr; - //! Return stack for the addresses of the returns - Rstack_t return_stack; + struct Frame { + PC_t ReturnAddress; + PC_t FramePointer; + PC_t StackPointer; + }; - //! Stack for the frame of the functions - FrameStack frame; + typedef std::stack<Frame> FrameStack; + //! Stack for function frames + FrameStack m_Frames; //! Input stream for read () operation std::istream* istr; @@ -62,35 +93,39 @@ class Spasm //! Output stream for print () opertion std::ostream* ostr; - void push(); + void push(reg_t reg); + void pop(reg_t reg); void pop(); void dup(); - void print(); - void read(); + void print(reg_t reg); + void read(reg_t reg); - void plus(); - void minus(); - void multiply(); - void divide(); - void modulus(); + void plus(reg_t a0, reg_t a1, reg_t a2); + void minus(reg_t a0, reg_t a1, reg_t a2); + void multiply(reg_t a0, reg_t a1, reg_t a2); + void divide(reg_t a0, reg_t a1, reg_t a2); + void modulus(reg_t a0, reg_t a1, reg_t a2); - void gotrue(); - void gofalse(); - void go(); + void gotrue(reg_t a0, reg_t a1); + void gofalse(reg_t a0, reg_t a1); + void go(reg_t a0); - void call(); - void ret(); + void call(reg_t a0); + void ret(reg_t a0); void load(); void store(); - void less(); - void lesseq(); + void less(reg_t a0, reg_t a1, reg_t a2); + void lesseq(reg_t a0, reg_t a1, reg_t a2); - // private method for copying and deleting an object - void copybc(const Spasm&); - void deleteobj(); + data_t get_local(reg_t reg); + void set_local(reg_t reg, data_t data); + data_t pop_data(); + void push_data(data_t); + reg_t read_reg(size_t size); + data_t read_number(size_t size); }; } // namespace SpasmImpl diff --git a/spasm/src/types.hpp b/spasm/src/types.hpp index 0d86cab..26450db 100644 --- a/spasm/src/types.hpp +++ b/spasm/src/types.hpp @@ -3,15 +3,20 @@ #include <cstdlib> #include <stack> +#include <vector> namespace SpasmImpl { -typedef unsigned char byte; +typedef int8_t byte; typedef size_t PC_t; typedef int data_t; -typedef std::stack<PC_t> Rstack_t; class Spasm; typedef void (Spasm::*Operation)(); + +template <typename T> +using SPVector = std::vector<T>; + +typedef long long int reg_t; } // namespace SpasmImpl #endif // ----- #ifndef TYPES_HPP |
