Skip to content

Commit

Permalink
Plug the new event reader into the compiler. This kills the crab.
Browse files Browse the repository at this point in the history
To-do:

- Test harness needs to be hooked in instead of being run ad-hoc with a gross makefile.
- There's an infinite loop somewhere; testing isn't finding it.
- Super check assumptions are wrong; super checks *can* use parameters. Compiler needs to be refactored further around how it treats super checks.
- Case insensitivity in param lookup maps. Currently retrieval of "key" will fail because it's called "Key" in the parameter value map.
- Need a method like ParamSubst that swaps in parameter names instead of argument spellings.
- Tons of migration work to get the whole compiler on the new system. Until then, resource names can't be used in filenames.
  • Loading branch information
JoshDreamland committed Jan 20, 2020
1 parent 7c03d46 commit 2444968
Show file tree
Hide file tree
Showing 21 changed files with 827 additions and 182 deletions.
3 changes: 2 additions & 1 deletion CommandLine/emake/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ SHARED_SRC_DIR := ../../shared
include $(SHARED_SRC_DIR)/Makefile
include $(SHARED_SRC_DIR)/eyaml/Makefile
include $(SHARED_SRC_DIR)/event_reader/Makefile
include $(SHARED_SRC_DIR)/ProtoYaml/Makefile

OS := $(shell uname -s)
ifeq ($(OS), Linux)
Expand All @@ -18,7 +19,7 @@ endif

PROTO_DIR := $(SHARED_SRC_DIR)/protos
CXXFLAGS := -I$(SRC_DIR) -I../../CompilerSource -I$(SHARED_SRC_DIR) -I$(PROTO_DIR)/.eobjs -std=c++11 -Wall -Wextra -Wpedantic -g
LDFLAGS := $(OS_LIBS) -L../../ -lProtocols -lprotobuf
LDFLAGS := $(OS_LIBS) -L../../ -lProtocols -lprotobuf -lyaml-cpp

rwildcard=$(wildcard $1/$2) $(foreach d,$(wildcard $1/*),$(call rwildcard,$d,$2))
SOURCES := $(call rwildcard,$(SRC_DIR),*.cpp)
Expand Down
61 changes: 23 additions & 38 deletions CommandLine/emake/SOG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,54 +7,39 @@
#include <fstream>
#include <iostream>

bool ReadSOG(const std::string &input_file, Game *game) {
event_parse_resourcefile();
map<string, evpair> event_filenames;
for (evpair e : event_sequence) {
event_filenames[event_get_function_name(e.first, e.second) + ".edl"] = e;
if (!e.second && event_is_instance(e.first, e.second)) {
// For stacked events, allow more than just the 0th instance.
// Needs to be big enough to accommodate the largest vk_ constant and also
// provide a reasonable number of alarm events, user events, etc.
// Using BYTE_MAX gives us both, and plenty of wiggle room.
for (int i = 1; i < 255; ++i) {
event_filenames[event_get_function_name(e.first, i) + ".edl"] = e;
}
}
}
using std::map;
using evpair = std::pair<int, int>;

bool ReadSOG(const std::string &input_file, Game *game) {
EventData event_data(ParseEventFile("events.res"));
map<evpair, string> events;
boost::filesystem::path targetDir(input_file);
boost::filesystem::recursive_directory_iterator iter(targetDir), eod;
BOOST_FOREACH(boost::filesystem::path const& i, std::make_pair(iter, eod)) {
if (is_regular_file(i)) {
auto find = event_filenames.find(i.filename().string());
if (find == event_filenames.end()) {
errorStream << "Error: unrecognized event file " << i << '.' << std::endl;
errorStream << "Supported events:" << std::endl;
for (auto st : event_sequence) {
errorStream << " - " << event_get_function_name(st.first, st.second);
if (!st.second && event_is_instance(st.first, st.second)) {
errorStream << ", " << event_get_function_name(st.first, 1);
errorStream << ", " << event_get_function_name(st.first, 2);
errorStream << ", " << "...";
if (Event ev = event_data.DecodeEventString(i.filename().string())) {
if (std::ifstream f{i.string()}) {
evpair eid = reverse_lookup_legacy_event(ev);
std::string code {
std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>()
};
if (!events.insert(std::make_pair(eid, code)).second) {
errorStream << "Logic error: Duplicate event " << i << " ("
<< eid.first << ", " << eid.second
<< "): your event configuration is broken." << std::endl;
return false;
}
errorStream << std::endl;
}
return false;
} else if (std::ifstream f{i.string()}) {
evpair eid = find->second;
std::string code {
std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>()
};
if (!events.insert(std::make_pair(eid, code)).second) {
errorStream << "Logic error: Duplicate event " << i << " ("
<< eid.first << ", " << eid.second
<< "): your event configuration is broken." << std::endl;
} else {
errorStream << "Error: Failed to read " << i << "..." << std::endl;
return false;
}
} else {
errorStream << "Error: Failed to read " << i << "..." << std::endl;
errorStream << "Error: unrecognized event file " << i << '.' << std::endl;
errorStream << "Supported events:" << std::endl;
for (auto st : event_data.events()) {
errorStream << " - " << st.ExampleIDStrings();
errorStream << std::endl;
}
return false;
}
} else {
Expand Down
8 changes: 8 additions & 0 deletions CommandLine/libEGM-test/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CXXFLAGS := -std=c++17
DEPS := ../../shared/event_reader/event_parser.cpp ../../shared/ProtoYaml/proto-yaml.cpp
INCLUDES := -I../../shared/ -I../../shared/protos/.eobjs/
LDFLAGS := -Wl,-rpath,../.. -L../..
LDLIBS := -lEGM -lProtocols -lgtest -lgtest_main -lprotobuf -lyaml-cpp -lpthread

event-reader-tests: event-reader-tests.cpp $(DEPS)
g++ $(CXXFLAGS) $^ $(INCLUDES) $(LDFLAGS) $(LDLIBS) -o $@
Binary file added CommandLine/libEGM-test/event-reader-tests
Binary file not shown.
113 changes: 113 additions & 0 deletions CommandLine/libEGM-test/event-reader-tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#include "event_reader/event_parser.h"
#include <gtest/gtest.h>

#include <sstream>

constexpr char kTestEvents[] = R"(
Events:
Alarm:
Name: "Alarm %1"
Type: Parameterized
Parameters:
- integer
Group: Alarm
SubCheck: |
{
alarm[%1] = (int) alarm[%1];
return alarm[%1] < 0 ? false : !((int)--alarm[%1]);
}
Collision:
Name: "Colision %1"
Description: "Instance is colliding (overlapping) with another object."
Group: "Collisions"
Type: Parameterized
Parameters:
- Object
SuperCheck: |
instance_number(%1)
SubCheck: |
enigma::place_meeting_inst(x,y,%1)
Prefix: "{"
Suffix: "}"
Keyboard:
Name: "Keyboard %1"
Description: "A key was pressed or is being held."
Group: "Input"
Type: Parameterized
Parameters:
- Key
SuperCheck: |
keyboard_check(%1)
Joystick.Button:
Name: "Joystick %1 Button %2"
Description: "A joystick button is pressed or held"
Group: "Input"
Type: Parameterized
Parameters:
- Integer
- JoystickButton
Aliases:
Key:
Left: {value: 37, spelling: "vk_left"}
Right: {value: 39, spelling: "vk_right"}
Up: {value: 38, spelling: "vk_up"}
Down: {value: 40, spelling: "vk_down"}
A: {value: 65, spelling: "'A'"}
B: {value: 66, spelling: "'B'"}
JoystickButton:
Left: {value: 0, spelling: "js_left"}
Right: {value: 1, spelling: "js_right"}
Up: {value: 2, spelling: "js_up"}
Down: {value: 3, spelling: "js_down"}
GameMakerEventMappings:
0: # Instance construct event.
Single: Create
2: # Alarms. GM only supports ten.
Parameterized: Alarm[%1] # Number <1-10>
4: # Collision events.
Parameterized: Collision[%1] # <Object>
5: # Keyboard events.
Parameterized: Keyboard[%1] # <Key>
6: # The "Mouse" group, which somehow inherited joysticks.
Specialized:
Cases:
21: Joystick[1]Button[1]
22: Joystick[1]Button[2]
23: Joystick[1]Button[3]
24: Joystick[1]Button[4]
25: Joystick[1]Button[5]
26: Joystick[1]Button[6]
27: Joystick[1]Button[7]
28: Joystick[1]Button[8]
36: Joystick[2]Button[1]
37: Joystick[2]Button[2]
38: Joystick[2]Button[3]
39: Joystick[2]Button[4]
40: Joystick[2]Button[5]
41: Joystick[2]Button[6]
42: Joystick[2]Button[7]
43: Joystick[2]Button[8]
)";

TEST(EventReaderTest, ReadsEventFile) {
std::istringstream str(kTestEvents);
EventData events(ParseEventFile(str));
Event ev = events.DecodeEventString("Keyboard[Up]");
EXPECT_EQ(ev.HumanName(), "Keyboard vk_up");
EXPECT_EQ(ev.IdString(), "Keyboard[Up]");
EXPECT_EQ(events.reverse_get_event(ev).mid, 5);
EXPECT_EQ(events.reverse_get_event(ev).id, 38);
EXPECT_FALSE(ev.HasSubCheck());
EXPECT_FALSE(ev.HasSubCheckExpression());
EXPECT_FALSE(ev.HasSubCheckFunction());
// EXPECT_TRUE(ev.HasSuperCheck());
// EXPECT_TRUE(ev.HasSuperCheckExpression());
// EXPECT_EQ(ev.event->super_check(), "keyboard_check(%1)");
// EXPECT_EQ(ev.SuperCheckExpression(), "keyboard_check(vk_up)");
}
2 changes: 1 addition & 1 deletion CommandLine/libEGM/egm-rooms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ void BuildLayers(const RepeatedPtrField<Entity> &entities, Layers *out) {

// Sort out snowflakes (Instances which cannot be lumped).
for (const Entity &entity : entities) {
if (!StripForLump(entity).ByteSize()) {
if (!StripForLump(entity).ByteSizeLong()) {
lumpable[entity].insert(Coords{entity});
} else {
std::cout << "INFO: Cannot lump instance because it has special fields.\n"
Expand Down
38 changes: 38 additions & 0 deletions CompilerSource/CompileEGMf.cbp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
<Option compiler="gcc" />
<Compiler>
<Add option="-Wall" />
<Add option="-std=c++1z" />
<Add option="-g" />
<Add option="-DENIGMA_PARSERS_DEBUG" />
<Add option="-DNOT_A_DLL" />
Expand Down Expand Up @@ -122,7 +123,44 @@
<Add option="-Wall" />
<Add directory="." />
<Add directory="./JDI/src" />
<Add directory="../shared/" />
<Add directory="../shared/protos/.eobjs" />
</Compiler>
<Unit filename="../shared/ProtoYaml/proto-yaml.cpp" />
<Unit filename="../shared/ProtoYaml/proto-yaml.h" />
<Unit filename="../shared/event_reader/event_parser.cpp" />
<Unit filename="../shared/event_reader/event_parser.h" />
<Unit filename="../shared/event_reader/events.res" />
<Unit filename="../shared/eyaml/Makefile" />
<Unit filename="../shared/eyaml/eyaml.cpp" />
<Unit filename="../shared/eyaml/eyaml.h" />
<Unit filename="../shared/libpng-util/libpng-util.cpp" />
<Unit filename="../shared/libpng-util/libpng-util.h" />
<Unit filename="../shared/proto_util.h" />
<Unit filename="../shared/protos/Action.proto" />
<Unit filename="../shared/protos/Background.proto" />
<Unit filename="../shared/protos/Configuration/EventDescriptor.proto" />
<Unit filename="../shared/protos/Font.proto" />
<Unit filename="../shared/protos/GameInformation.proto" />
<Unit filename="../shared/protos/Include.proto" />
<Unit filename="../shared/protos/Object.proto" />
<Unit filename="../shared/protos/Path.proto" />
<Unit filename="../shared/protos/Room.proto" />
<Unit filename="../shared/protos/Script.proto" />
<Unit filename="../shared/protos/Settings.proto" />
<Unit filename="../shared/protos/Shader.proto" />
<Unit filename="../shared/protos/Sound.proto" />
<Unit filename="../shared/protos/Sprite.proto" />
<Unit filename="../shared/protos/Timeline.proto" />
<Unit filename="../shared/protos/compiler.proto" />
<Unit filename="../shared/protos/game.proto" />
<Unit filename="../shared/protos/options.proto" />
<Unit filename="../shared/protos/project.proto" />
<Unit filename="../shared/protos/server.proto" />
<Unit filename="../shared/protos/treenode.proto" />
<Unit filename="../shared/rectpacker/rectpack.cpp" />
<Unit filename="../shared/rectpacker/rectpack.h" />
<Unit filename="../shared/strings_util.h" />
<Unit filename="JDI/src/API/AST.cpp" />
<Unit filename="JDI/src/API/AST.h" />
<Unit filename="JDI/src/API/AST_Export.cpp" />
Expand Down
6 changes: 5 additions & 1 deletion CompilerSource/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ include $(SHARED_SRC_DIR)/Makefile
include $(SHARED_SRC_DIR)/eyaml/Makefile
include $(SHARED_SRC_DIR)/event_reader/Makefile
include $(SHARED_SRC_DIR)/rectpacker/Makefile
include $(SHARED_SRC_DIR)/ProtoYaml/Makefile

#################
# configuration #
Expand Down Expand Up @@ -33,7 +34,7 @@ endif
CXX := g++
CXXFLAGS += -std=c++11 -Wall -O3 -g -I./JDI/src
LDFLAGS += -shared -O3 -g -L../ -Wl,-rpath,./
LDLIBS += -lProtocols -lprotobuf -lz -L$(SHARED_SRC_DIR)/libpng-util -lpng-util -lpng
LDLIBS += -lProtocols -lprotobuf -lz -L$(SHARED_SRC_DIR)/libpng-util -lpng-util -lpng -lyaml-cpp

# This implements a recursive wildcard allowing us to iterate in subdirs
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
Expand Down Expand Up @@ -66,6 +67,9 @@ clean:
$(TARGET): $(OBJECTS)
$(CXX) $(LDFLAGS) -o $@ $(OBJECTS) $(LDLIBS)

emake:
$(MAKE) -C .. emake

# GCC will figure out dependencies and write out makefile rules in %.d when they change
# -MMD outputs dependencies to %.d as a side effect of compilation, ignoring system headers
# -MP gives phony rules for non-target files, avoiding problems with missing files
Expand Down
Loading

0 comments on commit 2444968

Please sign in to comment.