Make gen_commands.py generate a schema file

This commit is contained in:
dP
2023-03-24 21:24:11 +04:00
parent 6b11a1df38
commit ef7d1c5f04
4 changed files with 320 additions and 222 deletions

View File

@@ -1,14 +1,16 @@
import glob
import json
import re
from pathlib import Path
from pprint import pprint
RX_COMMAND = re.compile(r'(?P<returns>CommandCost|std::tuple<CommandCost, [^>]*>) (?P<name>Cmd\w*)\((?P<args>[^)]*)\);')
RX_DEF_TRAIT = re.compile(r'DEF_CMD_TRAIT\((?P<constant>\w+),\s+(?P<function>\w+),\s+[^,]*,\s+(?P<category>\w+)\)')
RX_DEF_TRAIT = re.compile(r'DEF_CMD_TRAIT\((?P<constant>\w+),\s+(?P<function>\w+),\s+(?P<flags>[^,]*),\s+(?P<category>\w+)\)')
RX_ARG = re.compile(r'(?P<type>(:?const |)[\w:]* &?)(?P<name>\w*)')
RX_CALLBACK = re.compile(r'void\s+(?P<name>Cc\w+)\(Commands')
RX_CALLBACK_REF = re.compile(r'CommandCallback\s+(?P<name>Cc\w+);')
RX_CAMEL_TO_SNAKE = re.compile(r'(?<!^)(?=[A-Z])')
RX_CMD_CONSTANT = re.compile(r'CMD_[\w_]+')
FILES = [
'src/misc_cmd.h',
@@ -23,18 +25,84 @@ FILES = [
BASE_DIR = Path(__file__).parent
OUTPUT = BASE_DIR / 'src/citymania/generated/cm_gen_commands'
GLOBAL_TYPES = set(('GoalType', 'GoalTypeID', 'GoalID'))
TYPE_CONVERT = {
'const std::string &': 'std::string',
}
AREA_CODE = {
('CMD_BUILD_RAIL_STATION',): (
'if (this->axis == AXIS_X) return CommandArea(this->tile, this->plat_len, this->numtracks);\n'
'return CommandArea(this->tile, this->numtracks, this->plat_len);\n'
),
('CMD_BUILD_AIRPORT',): (
'const AirportSpec *as = AirportSpec::Get(this->airport_type);\n'
'if (!as->IsAvailable()) return CommandArea(this->tile);\n'
'return CommandArea(this->tile, as->size_x, as->size_y);\n'
),
('CMD_BUILD_ROAD_STOP',):
'return CommandArea(this->tile, this->width, this->length);\n',
#TODO diagonal areas
(
'CMD_PLANT_TREE',
'CMD_BUILD_RAILROAD_TRACK',
'CMD_REMOVE_RAILROAD_TRACK',
'CMD_BUILD_LONG_ROAD',
'CMD_REMOVE_LONG_ROAD',
'CMD_CLEAR_AREA',
'CMD_BUILD_CANAL',
'CMD_LEVEL_LAND',
'CMD_BUILD_BRIDGE',
): 'return CommandArea(this->start_tile, this->tile);\n',
(
'CMD_BUILD_BRIDGE',
): 'return CommandArea(this->tile_start, this->tile);\n',
(
'CMD_BUILD_SINGLE_RAIL',
'CMD_BUILD_TRAIN_DEPOT',
'CMD_BUILD_BUOY',
'CMD_BUILD_ROAD',
'CMD_BUILD_ROAD_DEPOT',
'CMD_PLACE_SIGN',
'CMD_LANDSCAPE_CLEAR',
'CMD_TERRAFORM_LAND',
'CMD_FOUND_TOWN', # TODO
'CMD_BUILD_DOCK', # TODO
'CMD_BUILD_SHIP_DEPOT', # TODO
'CMD_BUILD_LOCK', # TODO
'CMD_BUILD_OBJECT', # TODO
'CMD_BUILD_INDUSTRY', # TODO
'CMD_BUILD_TUNNEL', # TODO find other end
): 'return CommandArea(this->tile);\n'
}
DEFAULT_AREA_CODE = 'return CommandArea();\n'
def parse_commands():
res = []
includes = []
callbacks = []
command_ids = {}
cid = 0
for l in open(BASE_DIR / 'src' / 'command_type.h'):
cl = RX_CMD_CONSTANT.findall(l)
if not cl:
continue
cmd = cl[0]
if cmd == 'CMD_END':
break
command_ids[cmd] = cid
cid += 1
for f in glob.glob(str(BASE_DIR / 'src' / '*_cmd.h')):
# for f in glob.glob(str(BASE_DIR / 'src' / 'group_cmd.h')):
includes.append(Path(f).name)
data = open(f).read()
traits = {}
for constant, name, category in RX_DEF_TRAIT.findall(data):
traits[name] = constant, category
for constant, name, flags, category in RX_DEF_TRAIT.findall(data):
traits[name] = constant, flags, category
callbacks.extend(RX_CALLBACK.findall(data))
callbacks.extend(RX_CALLBACK_REF.findall(data))
for returns, name, args_str in RX_COMMAND.findall(data):
@@ -43,24 +111,51 @@ def parse_commands():
print(f'Not a command: {name}')
continue
print(f, name, end=' ', flush=True)
constant, category = trait
constant, flags, category = trait
cid = command_ids[constant]
if returns.startswith('std::tuple'):
ret_type = returns[24: -1]
result_type = returns[24: -1]
if result_type in GLOBAL_TYPES:
result_type = '::' + result_type
else:
ret_type = None
result_type = None
args = [RX_ARG.fullmatch(x).group('type', 'name') for x in args_str.split(', ')]
args = args[1:] # flags
first_tile_arg = (args[0][0].strip() == 'TileIndex')
if first_tile_arg:
args = args[1:]
print(constant, category, args)
for i, (at, an) in enumerate(args):
at = at.strip()
if at in GLOBAL_TYPES:
at = '::' + at
args[i] = (at, an)
print(cid, constant, category, args)
callback_args = 'CommandCost' if result_type is None else f'CommandCost, {result_type}'
callback_type = f'std::function<void ({callback_args})>'
area_code = DEFAULT_AREA_CODE
for cl, cc in AREA_CODE.items():
if constant in cl:
area_code = cc
default_run_as = 'INVALID_COMPANY'
if 'CMD_DEITY' in flags:
default_run_as = 'OWNER_DEITY'
if 'CMD_SERVER' in flags or 'CMD_SPECTATOR' in flags:
default_run_as = 'COMPANY_SPECTATOR' # same as INVALID though
res.append({
'name': name[3:],
'id': cid,
'constant': constant,
'category': category,
'flags': flags,
'default_run_as': default_run_as,
'args': args,
'first_tile_arg': first_tile_arg,
'returns': ret_type,
'returns': returns,
'result_type': result_type,
'callback_type': callback_type,
'area_code': area_code,
})
return res, includes, callbacks
@@ -128,6 +223,11 @@ inline constexpr auto MakeDispatchTable() noexcept
def run():
commands, includes, callbacks = parse_commands()
json.dump({
'commands': commands,
'includes': includes,
'callbacks': callbacks,
}, open('commands.json', 'w'))
with open(OUTPUT.with_suffix('.hpp'), 'w') as f:
f.write(
'// This file is generated by gen_commands.py, do not edit\n\n'
@@ -144,14 +244,14 @@ def run():
)
for cmd in commands:
name = cmd['name']
args_list = ', '.join(f'{at}{an}' for at, an in cmd['args'])
args_list = ', '.join(f'{at} {an}' for at, an in cmd['args'])
args_init = ', '.join(f'{an}{{{an}}}' for _, an in cmd['args'])
f.write(
f'class {name}: public Command {{\n'
f'public:\n'
)
for at, an in cmd['args']:
f.write(f' {at}{an};\n')
f.write(f' {at} {an};\n')
f.write(f'\n')
if args_init:
f.write(
@@ -220,7 +320,7 @@ def run():
else:
test_args_list = f'this->tile'
cost_getter = '' if cmd['returns'] is None else 'std::get<0>'
cost_getter = '' if cmd['result_type'] is None else 'std::get<0>'
sep_args_list = sep_args_type_list = sep_this_args_list = ''
if args_list:
sep_args_list = ', ' + args_list

View File

@@ -133,7 +133,6 @@ void load_replay_commands(const std::string &filename, std::function<void(const
lzma.next_out = &data[0];
lzma.avail_out = data.size();
do {
fprintf(stderr, "LZMA in %d\n", (int)lzma.avail_in);
if (lzma.avail_in == 0 && !std::feof(f)) {
lzma.next_in = inbuf;
lzma.avail_in = std::fread((char *)inbuf, 1, sizeof(inbuf), f);
@@ -172,8 +171,7 @@ void load_replay_commands(const std::string &filename, std::function<void(const
return;
}
// auto openttd_version = bs.ReadBytes(4);
auto openttd_version = _openttd_newgrf_version;
auto openttd_version = bs.ReadBytes(4);
if (_openttd_newgrf_version != openttd_version) {
error_func(fmt::format("OpenTTD version doesn't match: current {}, log file {}",

File diff suppressed because it is too large Load Diff

View File

@@ -47,9 +47,9 @@ namespace cmd {
class CreateStoryPage: public Command {
public:
CompanyID company;
const std::string &text;
const std::string & text;
CreateStoryPage(CompanyID company, const std::string &text)
CreateStoryPage(CompanyID company, const std::string & text)
:company{company}, text{text} {}
~CreateStoryPage() override {}
@@ -63,11 +63,11 @@ public:
StoryPageID page_id;
StoryPageElementType type;
uint32 reference;
const std::string &text;
const std::string & text;
CreateStoryPageElement(StoryPageID page_id, StoryPageElementType type, uint32 reference, const std::string &text)
CreateStoryPageElement(StoryPageID page_id, StoryPageElementType type, uint32 reference, const std::string & text)
:page_id{page_id}, type{type}, reference{reference}, text{text} {}
CreateStoryPageElement(TileIndex tile, StoryPageID page_id, StoryPageElementType type, uint32 reference, const std::string &text)
CreateStoryPageElement(TileIndex tile, StoryPageID page_id, StoryPageElementType type, uint32 reference, const std::string & text)
:Command{tile}, page_id{page_id}, type{type}, reference{reference}, text{text} {}
~CreateStoryPageElement() override {}
@@ -80,11 +80,11 @@ class UpdateStoryPageElement: public Command {
public:
StoryPageElementID page_element_id;
uint32 reference;
const std::string &text;
const std::string & text;
UpdateStoryPageElement(StoryPageElementID page_element_id, uint32 reference, const std::string &text)
UpdateStoryPageElement(StoryPageElementID page_element_id, uint32 reference, const std::string & text)
:page_element_id{page_element_id}, reference{reference}, text{text} {}
UpdateStoryPageElement(TileIndex tile, StoryPageElementID page_element_id, uint32 reference, const std::string &text)
UpdateStoryPageElement(TileIndex tile, StoryPageElementID page_element_id, uint32 reference, const std::string & text)
:Command{tile}, page_element_id{page_element_id}, reference{reference}, text{text} {}
~UpdateStoryPageElement() override {}
@@ -96,9 +96,9 @@ public:
class SetStoryPageTitle: public Command {
public:
StoryPageID page_id;
const std::string &text;
const std::string & text;
SetStoryPageTitle(StoryPageID page_id, const std::string &text)
SetStoryPageTitle(StoryPageID page_id, const std::string & text)
:page_id{page_id}, text{text} {}
~SetStoryPageTitle() override {}
@@ -229,9 +229,9 @@ public:
class RenameWaypoint: public Command {
public:
StationID waypoint_id;
const std::string &text;
const std::string & text;
RenameWaypoint(StationID waypoint_id, const std::string &text)
RenameWaypoint(StationID waypoint_id, const std::string & text)
:waypoint_id{waypoint_id}, text{text} {}
~RenameWaypoint() override {}
@@ -355,9 +355,9 @@ public:
class RenameStation: public Command {
public:
StationID station_id;
const std::string &text;
const std::string & text;
RenameStation(StationID station_id, const std::string &text)
RenameStation(StationID station_id, const std::string & text)
:station_id{station_id}, text{text} {}
~RenameStation() override {}
@@ -382,11 +382,11 @@ public:
class CreateGoal: public Command {
public:
CompanyID company;
GoalType type;
GoalTypeID dest;
const std::string &text;
::GoalType type;
::GoalTypeID dest;
const std::string & text;
CreateGoal(CompanyID company, GoalType type, GoalTypeID dest, const std::string &text)
CreateGoal(CompanyID company, ::GoalType type, ::GoalTypeID dest, const std::string & text)
:company{company}, type{type}, dest{dest}, text{text} {}
~CreateGoal() override {}
@@ -397,9 +397,9 @@ public:
class RemoveGoal: public Command {
public:
GoalID goal;
::GoalID goal;
RemoveGoal(GoalID goal)
RemoveGoal(::GoalID goal)
:goal{goal} {}
~RemoveGoal() override {}
@@ -410,10 +410,10 @@ public:
class SetGoalText: public Command {
public:
GoalID goal;
const std::string &text;
::GoalID goal;
const std::string & text;
SetGoalText(GoalID goal, const std::string &text)
SetGoalText(::GoalID goal, const std::string & text)
:goal{goal}, text{text} {}
~SetGoalText() override {}
@@ -424,10 +424,10 @@ public:
class SetGoalProgress: public Command {
public:
GoalID goal;
const std::string &text;
::GoalID goal;
const std::string & text;
SetGoalProgress(GoalID goal, const std::string &text)
SetGoalProgress(::GoalID goal, const std::string & text)
:goal{goal}, text{text} {}
~SetGoalProgress() override {}
@@ -438,10 +438,10 @@ public:
class SetGoalCompleted: public Command {
public:
GoalID goal;
::GoalID goal;
bool completed;
SetGoalCompleted(GoalID goal, bool completed)
SetGoalCompleted(::GoalID goal, bool completed)
:goal{goal}, completed{completed} {}
~SetGoalCompleted() override {}
@@ -457,9 +457,9 @@ public:
bool is_client;
uint32 button_mask;
GoalQuestionType type;
const std::string &text;
const std::string & text;
GoalQuestion(uint16 uniqueid, uint16 target, bool is_client, uint32 button_mask, GoalQuestionType type, const std::string &text)
GoalQuestion(uint16 uniqueid, uint16 target, bool is_client, uint32 button_mask, GoalQuestionType type, const std::string & text)
:uniqueid{uniqueid}, target{target}, is_client{is_client}, button_mask{button_mask}, type{type}, text{text} {}
~GoalQuestion() override {}
@@ -484,10 +484,10 @@ public:
class ChangeSetting: public Command {
public:
const std::string &name;
const std::string & name;
int32 value;
ChangeSetting(const std::string &name, int32 value)
ChangeSetting(const std::string & name, int32 value)
:name{name}, value{value} {}
~ChangeSetting() override {}
@@ -498,10 +498,10 @@ public:
class ChangeCompanySetting: public Command {
public:
const std::string &name;
const std::string & name;
int32 value;
ChangeCompanySetting(const std::string &name, int32 value)
ChangeCompanySetting(const std::string & name, int32 value)
:name{name}, value{value} {}
~ChangeCompanySetting() override {}
@@ -516,9 +516,9 @@ public:
NewsReferenceType reftype1;
CompanyID company;
uint32 reference;
const std::string &text;
const std::string & text;
CustomNewsItem(NewsType type, NewsReferenceType reftype1, CompanyID company, uint32 reference, const std::string &text)
CustomNewsItem(NewsType type, NewsReferenceType reftype1, CompanyID company, uint32 reference, const std::string & text)
:type{type}, reftype1{reftype1}, company{company}, reference{reference}, text{text} {}
~CustomNewsItem() override {}
@@ -932,11 +932,11 @@ public:
class CreateLeagueTable: public Command {
public:
const std::string &title;
const std::string &header;
const std::string &footer;
const std::string & title;
const std::string & header;
const std::string & footer;
CreateLeagueTable(const std::string &title, const std::string &header, const std::string &footer)
CreateLeagueTable(const std::string & title, const std::string & header, const std::string & footer)
:title{title}, header{header}, footer{footer} {}
~CreateLeagueTable() override {}
@@ -950,12 +950,12 @@ public:
LeagueTableID table;
int64 rating;
CompanyID company;
const std::string &text;
const std::string &score;
const std::string & text;
const std::string & score;
LinkType link_type;
LinkTargetID link_target;
CreateLeagueTableElement(LeagueTableID table, int64 rating, CompanyID company, const std::string &text, const std::string &score, LinkType link_type, LinkTargetID link_target)
CreateLeagueTableElement(LeagueTableID table, int64 rating, CompanyID company, const std::string & text, const std::string & score, LinkType link_type, LinkTargetID link_target)
:table{table}, rating{rating}, company{company}, text{text}, score{score}, link_type{link_type}, link_target{link_target} {}
~CreateLeagueTableElement() override {}
@@ -968,11 +968,11 @@ class UpdateLeagueTableElementData: public Command {
public:
LeagueTableElementID element;
CompanyID company;
const std::string &text;
const std::string & text;
LinkType link_type;
LinkTargetID link_target;
UpdateLeagueTableElementData(LeagueTableElementID element, CompanyID company, const std::string &text, LinkType link_type, LinkTargetID link_target)
UpdateLeagueTableElementData(LeagueTableElementID element, CompanyID company, const std::string & text, LinkType link_type, LinkTargetID link_target)
:element{element}, company{company}, text{text}, link_type{link_type}, link_target{link_target} {}
~UpdateLeagueTableElementData() override {}
@@ -985,9 +985,9 @@ class UpdateLeagueTableElementScore: public Command {
public:
LeagueTableElementID element;
int64 rating;
const std::string &score;
const std::string & score;
UpdateLeagueTableElementScore(LeagueTableElementID element, int64 rating, const std::string &score)
UpdateLeagueTableElementScore(LeagueTableElementID element, int64 rating, const std::string & score)
:element{element}, rating{rating}, score{score} {}
~UpdateLeagueTableElementScore() override {}
@@ -1011,11 +1011,11 @@ public:
class PlaceSign: public Command {
public:
const std::string &text;
const std::string & text;
PlaceSign(const std::string &text)
PlaceSign(const std::string & text)
:text{text} {}
PlaceSign(TileIndex tile, const std::string &text)
PlaceSign(TileIndex tile, const std::string & text)
:Command{tile}, text{text} {}
~PlaceSign() override {}
@@ -1027,9 +1027,9 @@ public:
class RenameSign: public Command {
public:
SignID sign_id;
const std::string &text;
const std::string & text;
RenameSign(SignID sign_id, const std::string &text)
RenameSign(SignID sign_id, const std::string & text)
:sign_id{sign_id}, text{text} {}
~RenameSign() override {}
@@ -1094,9 +1094,9 @@ class SendVehicleToDepot: public Command {
public:
VehicleID veh_id;
DepotCommand depot_cmd;
const VehicleListIdentifier &vli;
const VehicleListIdentifier & vli;
SendVehicleToDepot(VehicleID veh_id, DepotCommand depot_cmd, const VehicleListIdentifier &vli)
SendVehicleToDepot(VehicleID veh_id, DepotCommand depot_cmd, const VehicleListIdentifier & vli)
:veh_id{veh_id}, depot_cmd{depot_cmd}, vli{vli} {}
~SendVehicleToDepot() override {}
@@ -1124,9 +1124,9 @@ public:
class RenameVehicle: public Command {
public:
VehicleID veh_id;
const std::string &text;
const std::string & text;
RenameVehicle(VehicleID veh_id, const std::string &text)
RenameVehicle(VehicleID veh_id, const std::string & text)
:veh_id{veh_id}, text{text} {}
~RenameVehicle() override {}
@@ -1169,11 +1169,11 @@ class MassStartStopVehicle: public Command {
public:
bool do_start;
bool vehicle_list_window;
const VehicleListIdentifier &vli;
const VehicleListIdentifier & vli;
MassStartStopVehicle(bool do_start, bool vehicle_list_window, const VehicleListIdentifier &vli)
MassStartStopVehicle(bool do_start, bool vehicle_list_window, const VehicleListIdentifier & vli)
:do_start{do_start}, vehicle_list_window{vehicle_list_window}, vli{vli} {}
MassStartStopVehicle(TileIndex tile, bool do_start, bool vehicle_list_window, const VehicleListIdentifier &vli)
MassStartStopVehicle(TileIndex tile, bool do_start, bool vehicle_list_window, const VehicleListIdentifier & vli)
:Command{tile}, do_start{do_start}, vehicle_list_window{vehicle_list_window}, vli{vli} {}
~MassStartStopVehicle() override {}
@@ -1248,9 +1248,9 @@ public:
class RenameDepot: public Command {
public:
DepotID depot_id;
const std::string &text;
const std::string & text;
RenameDepot(DepotID depot_id, const std::string &text)
RenameDepot(DepotID depot_id, const std::string & text)
:depot_id{depot_id}, text{text} {}
~RenameDepot() override {}
@@ -1469,9 +1469,9 @@ public:
class RenameCompany: public Command {
public:
const std::string &text;
const std::string & text;
RenameCompany(const std::string &text)
RenameCompany(const std::string & text)
:text{text} {}
~RenameCompany() override {}
@@ -1482,9 +1482,9 @@ public:
class RenamePresident: public Command {
public:
const std::string &text;
const std::string & text;
RenamePresident(const std::string &text)
RenamePresident(const std::string & text)
:text{text} {}
~RenamePresident() override {}
@@ -1557,11 +1557,11 @@ public:
TownLayout layout;
bool random_location;
uint32 townnameparts;
const std::string &text;
const std::string & text;
FoundTown(TownSize size, bool city, TownLayout layout, bool random_location, uint32 townnameparts, const std::string &text)
FoundTown(TownSize size, bool city, TownLayout layout, bool random_location, uint32 townnameparts, const std::string & text)
:size{size}, city{city}, layout{layout}, random_location{random_location}, townnameparts{townnameparts}, text{text} {}
FoundTown(TileIndex tile, TownSize size, bool city, TownLayout layout, bool random_location, uint32 townnameparts, const std::string &text)
FoundTown(TileIndex tile, TownSize size, bool city, TownLayout layout, bool random_location, uint32 townnameparts, const std::string & text)
:Command{tile}, size{size}, city{city}, layout{layout}, random_location{random_location}, townnameparts{townnameparts}, text{text} {}
~FoundTown() override {}
@@ -1573,9 +1573,9 @@ public:
class RenameTown: public Command {
public:
TownID town_id;
const std::string &text;
const std::string & text;
RenameTown(TownID town_id, const std::string &text)
RenameTown(TownID town_id, const std::string & text)
:town_id{town_id}, text{text} {}
~RenameTown() override {}
@@ -1645,9 +1645,9 @@ public:
class TownSetText: public Command {
public:
TownID town_id;
const std::string &text;
const std::string & text;
TownSetText(TownID town_id, const std::string &text)
TownSetText(TownID town_id, const std::string & text)
:town_id{town_id}, text{text} {}
~TownSetText() override {}
@@ -1720,9 +1720,9 @@ public:
IndustryAction action;
IndustryControlFlags ctlflags;
Owner company_id;
const std::string &text;
const std::string & text;
IndustryCtrl(IndustryID ind_id, IndustryAction action, IndustryControlFlags ctlflags, Owner company_id, const std::string &text)
IndustryCtrl(IndustryID ind_id, IndustryAction action, IndustryControlFlags ctlflags, Owner company_id, const std::string & text)
:ind_id{ind_id}, action{action}, ctlflags{ctlflags}, company_id{company_id}, text{text} {}
~IndustryCtrl() override {}
@@ -1779,9 +1779,9 @@ class InsertOrder: public Command {
public:
VehicleID veh;
VehicleOrderID sel_ord;
const Order &new_order;
const Order & new_order;
InsertOrder(VehicleID veh, VehicleOrderID sel_ord, const Order &new_order)
InsertOrder(VehicleID veh, VehicleOrderID sel_ord, const Order & new_order)
:veh{veh}, sel_ord{sel_ord}, new_order{new_order} {}
~InsertOrder() override {}
@@ -1953,9 +1953,9 @@ public:
class RenameEngine: public Command {
public:
EngineID engine_id;
const std::string &text;
const std::string & text;
RenameEngine(EngineID engine_id, const std::string &text)
RenameEngine(EngineID engine_id, const std::string & text)
:engine_id{engine_id}, text{text} {}
~RenameEngine() override {}
@@ -2031,9 +2031,9 @@ public:
AlterGroupMode mode;
GroupID group_id;
GroupID parent_id;
const std::string &text;
const std::string & text;
AlterGroup(AlterGroupMode mode, GroupID group_id, GroupID parent_id, const std::string &text)
AlterGroup(AlterGroupMode mode, GroupID group_id, GroupID parent_id, const std::string & text)
:mode{mode}, group_id{group_id}, parent_id{parent_id}, text{text} {}
~AlterGroup() override {}