Website Summary Files Commits Branches @commit @diff @stats
diff options
context:
space:
mode:
Commit9a7a8a31e75d1b85274ef46ca29714270062809e (patch)
Author
 dtrendafilov <trendafilov.dn@gmail.com>
2018-11-14 19:47:37 +0200
Committer
 GitHub <noreply@github.com>
2018-11-14 19:47:37 +0200
Files587a120e78e7c0d50c381d8f38bf0665ed8733a7
IPL-9a7a8a31e75d1b85274ef46ca29714270062809e.tar
IPL-9a7a8a31e75d1b85274ef46ca29714270062809e.tar.gz
IPL-9a7a8a31e75d1b85274ef46ca29714270062809e.zip
Parent990a8f5e2c2d6e246acfd8b7a99ac1cbf4fb1675 (diff)
Parente7c2a14f3e424f1ef1109d7634ece820a058e862 (diff)
Merge pull request #45 from SofiaCPP/feature/spasm_improvements
Feature/spasm improvements
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