ruby: use symbols for enums everywhere

develop
jj 2012-04-26 20:55:52 +02:00
parent ba7d4f8edd
commit 51ecd15fa8
5 changed files with 63 additions and 36 deletions

@ -47,7 +47,7 @@ my %item_renderer = (
my %global_types; my %global_types;
my %seen_enum_name; our %seen_enum_name;
sub render_global_enum { sub render_global_enum {
my ($name, $type) = @_; my ($name, $type) = @_;
@ -72,6 +72,7 @@ sub render_enum_fields {
for my $attr ($type->findnodes('child::enum-attr')) { for my $attr ($type->findnodes('child::enum-attr')) {
my $rbattr = rb_ucase($attr->getAttribute('name')); my $rbattr = rb_ucase($attr->getAttribute('name'));
my $typeattr = $attr->getAttribute('type-name'); my $typeattr = $attr->getAttribute('type-name');
# find how we need to encode the attribute values: string, symbol (for enums), raw (number, bool)
if ($typeattr) { if ($typeattr) {
if ($global_types{$typeattr}) { if ($global_types{$typeattr}) {
$attr_type{$rbattr} = 'symbol'; $attr_type{$rbattr} = 'symbol';
@ -85,6 +86,7 @@ sub render_enum_fields {
my $def = $attr->getAttribute('default-value'); my $def = $attr->getAttribute('default-value');
if ($def) { if ($def) {
$def = ":$def" if ($attr_type{$rbattr} eq 'symbol'); $def = ":$def" if ($attr_type{$rbattr} eq 'symbol');
$def =~ s/'/\\'/g if ($attr_type{$rbattr} eq 'quote');
$def = "'$def'" if ($attr_type{$rbattr} eq 'quote'); $def = "'$def'" if ($attr_type{$rbattr} eq 'quote');
push @lines_rb, "$rbattr = Hash.new($def)"; push @lines_rb, "$rbattr = Hash.new($def)";
} else { } else {
@ -106,6 +108,7 @@ sub render_enum_fields {
my $iav = $iattr->getAttribute('value'); my $iav = $iattr->getAttribute('value');
my $rbattr = rb_ucase($ian); my $rbattr = rb_ucase($ian);
$iav = ":$iav" if ($attr_type{$rbattr} eq 'symbol'); $iav = ":$iav" if ($attr_type{$rbattr} eq 'symbol');
$iav =~ s/'/\\'/g if ($attr_type{$rbattr} eq 'quote');
$iav = "'$iav'" if ($attr_type{$rbattr} eq 'quote'); $iav = "'$iav'" if ($attr_type{$rbattr} eq 'quote');
$lines_rb[$#lines_rb] .= " ; ${rbattr}[$value] = $iav"; $lines_rb[$#lines_rb] .= " ; ${rbattr}[$value] = $iav";
} }
@ -137,10 +140,14 @@ sub render_bitfield_fields {
for my $field ($type->findnodes('child::ld:field')) { for my $field ($type->findnodes('child::ld:field')) {
my $count = $field->getAttribute('count') || 1; my $count = $field->getAttribute('count') || 1;
my $name = $field->getAttribute('name'); my $name = $field->getAttribute('name');
my $type = $field->getAttribute('type-name');
my $enum = rb_ucase($type) if ($type and $global_types{$type});
$name = $field->getAttribute('ld:anon-name') if (!$name); $name = $field->getAttribute('ld:anon-name') if (!$name);
print "bitfield $name !number\n" if (!($field->getAttribute('ld:meta') eq 'number')); print "bitfield $name !number\n" if (!($field->getAttribute('ld:meta') eq 'number'));
if ($count == 1) { if ($count == 1) {
push @lines_rb, "field(:$name, 0) { bit $shift }" if ($name); push @lines_rb, "field(:$name, 0) { bit $shift }" if ($name);
} elsif ($enum) {
push @lines_rb, "field(:$name, 0) { bits $shift, $count, :$enum }" if ($name);
} else { } else {
push @lines_rb, "field(:$name, 0) { bits $shift, $count }" if ($name); push @lines_rb, "field(:$name, 0) { bits $shift, $count }" if ($name);
} }
@ -189,7 +196,7 @@ sub render_global_class {
indent_rb { indent_rb {
my $sz = query_cpp("sizeof($cppns)"); my $sz = query_cpp("sizeof($cppns)");
push @lines_rb, "sizeof $sz"; push @lines_rb, "sizeof $sz";
push @lines_rb, "rtti_classname '$rtti_name'" if $has_rtti; push @lines_rb, "rtti_classname :$rtti_name" if $has_rtti;
render_struct_fields($type, "$cppns"); render_struct_fields($type, "$cppns");
}; };
push @lines_rb, "end\n"; push @lines_rb, "end\n";
@ -292,10 +299,13 @@ sub render_item_number {
my $subtype = $item->getAttribute('ld:subtype'); my $subtype = $item->getAttribute('ld:subtype');
my $initvalue = $item->getAttribute('init-value'); my $initvalue = $item->getAttribute('init-value');
my $typename = $item->getAttribute('type-name');
$typename = rb_ucase($typename) if $typename;
$typename = $pns if (!$typename and $subtype eq 'enum'); # compound enum
$initvalue = 1 if ($initvalue and $initvalue eq 'true'); $initvalue = 1 if ($initvalue and $initvalue eq 'true');
# XXX needs pre-declaration of the enum... $initvalue = ":$initvalue" if ($initvalue and $typename and $initvalue =~ /[a-zA-Z]/);
$initvalue = rb_ucase($item->getAttribute('type-name')) . '::' . $initvalue if ($initvalue and $subtype and $subtype eq 'enum' and $initvalue =~ /[a-zA-Z]/); $initvalue ||= 'nil' if $typename;
$subtype = $item->getAttribute('base-type') if (!$subtype or $subtype eq 'enum' or $subtype eq 'bitfield'); $subtype = $item->getAttribute('base-type') if (!$subtype or $subtype eq 'enum' or $subtype eq 'bitfield');
$subtype = 'int32_t' if (!$subtype); $subtype = 'int32_t' if (!$subtype);
@ -324,6 +334,7 @@ sub render_item_number {
return; return;
} }
$lines_rb[$#lines_rb] .= ", $initvalue" if ($initvalue); $lines_rb[$#lines_rb] .= ", $initvalue" if ($initvalue);
$lines_rb[$#lines_rb] .= ", :$typename" if ($typename);
} }
sub render_item_compound { sub render_item_compound {
@ -342,10 +353,19 @@ sub render_item_compound {
}; };
push @lines_rb, "}" push @lines_rb, "}"
} elsif ($subtype eq 'enum') { } elsif ($subtype eq 'enum') {
my @namecomponents = split('::', $cppns);
shift @namecomponents;
my $enumclassname = join('_', map { rb_ucase($_) } @namecomponents);
local %seen_enum_name;
push @lines_rb, "class ::DFHack::$enumclassname";
indent_rb {
# declare constants # declare constants
render_enum_fields($item); render_enum_fields($item);
};
push @lines_rb, "end\n";
# actual field # actual field
render_item_number($item, $cppns); render_item_number($item, $enumclassname);
} else { } else {
print "no render compound $subtype\n"; print "no render compound $subtype\n";
} }

@ -3,7 +3,7 @@ def self.each_tree(material=:any)
@raws_tree_name ||= {} @raws_tree_name ||= {}
if @raws_tree_name.empty? if @raws_tree_name.empty?
df.world.raws.plants.all.each_with_index { |p, idx| df.world.raws.plants.all.each_with_index { |p, idx|
@raws_tree_name[idx] = p.id if p.flags[PlantRawFlags::TREE] @raws_tree_name[idx] = p.id if p.flags[:TREE]
} }
end end
@ -25,7 +25,7 @@ def self.each_shrub(material=:any)
@raws_shrub_name ||= {} @raws_shrub_name ||= {}
if @raws_tree_name.empty? if @raws_tree_name.empty?
df.world.raws.plants.all.each_with_index { |p, idx| df.world.raws.plants.all.each_with_index { |p, idx|
@raws_shrub_name[idx] = p.id if not p.flags[PlantRawFlags::GRASS] and not p.flags[PlantRawFlags::TREE] @raws_shrub_name[idx] = p.id if not p.flags[:GRASS] and not p.flags[:TREE]
} }
end end
@ -61,8 +61,8 @@ def self.cuttrees(material=nil, count_max=100)
b = map_block_at(plant) b = map_block_at(plant)
d = b.designation[plant.pos.x%16][plant.pos.y%16] d = b.designation[plant.pos.x%16][plant.pos.y%16]
next if d.hidden next if d.hidden
if d.dig == TileDigDesignation::No if d.dig == :No
d.dig = TileDigDesignation::Default d.dig = :Default
b.flags.designated = true b.flags.designated = true
cnt += 1 cnt += 1
break if cnt == count_max break if cnt == count_max
@ -116,9 +116,9 @@ def self.growcrops(material=nil, count_max=100)
if !material if !material
cnt = Hash.new(0) cnt = Hash.new(0)
suspend { suspend {
world.items.other[ItemsOtherId::SEEDS].each { |seed| world.items.other[:SEEDS].each { |seed|
next if not seed.flags.in_building next if not seed.flags.in_building
next if not seed.itemrefs.find { |ref| ref._rtti_classname == 'general_ref_building_holderst' } next if not seed.itemrefs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index] next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
cnt[seed.mat_index] += 1 cnt[seed.mat_index] += 1
} }
@ -137,10 +137,10 @@ def self.growcrops(material=nil, count_max=100)
cnt = 0 cnt = 0
suspend { suspend {
world.items.other[ItemsOtherId::SEEDS].each { |seed| world.items.other[:SEEDS].each { |seed|
next if wantmat and seed.mat_index != wantmat next if wantmat and seed.mat_index != wantmat
next if not seed.flags.in_building next if not seed.flags.in_building
next if not seed.itemrefs.find { |ref| ref._rtti_classname == 'general_ref_building_holderst' } next if not seed.itemrefs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index] next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
seed.grow_counter = @raws_plant_growdur[seed.mat_index] seed.grow_counter = @raws_plant_growdur[seed.mat_index]
cnt += 1 cnt += 1

@ -7,7 +7,7 @@ def self.unit_citizens
u.race == race and u.civ_id == civ and !u.flags1.dead and !u.flags1.merchant and u.race == race and u.civ_id == civ and !u.flags1.dead and !u.flags1.merchant and
!u.flags1.diplomat and !u.flags2.resident and !u.flags3.ghostly and !u.flags1.diplomat and !u.flags2.resident and !u.flags3.ghostly and
!u.curse.add_tags1.OPPOSED_TO_LIFE and !u.curse.add_tags1.CRAZED and !u.curse.add_tags1.OPPOSED_TO_LIFE and !u.curse.add_tags1.CRAZED and
u.mood != MoodType::Berserk u.mood != :Berserk
# TODO check curse ; currently this should keep vampires, but may include werebeasts # TODO check curse ; currently this should keep vampires, but may include werebeasts
} }
end end
@ -15,9 +15,9 @@ end
# list workers (citizen, not crazy / child / inmood / noble) # list workers (citizen, not crazy / child / inmood / noble)
def self.unit_workers def self.unit_workers
unit_citizens.find_all { |u| unit_citizens.find_all { |u|
u.mood == MoodType::None and u.mood == :None and
Profession::ENUM[u.profession] != :CHILD and u.profession != :CHILD and
Profession::ENUM[u.profession] != :BABY and u.profession != :BABY and
# TODO MENIAL_WORK_EXEMPTION_SPOUSE # TODO MENIAL_WORK_EXEMPTION_SPOUSE
!unit_entitypositions(u).find { |pos| pos.flags[:MENIAL_WORK_EXEMPTION] } !unit_entitypositions(u).find { |pos| pos.flags[:MENIAL_WORK_EXEMPTION] }
} }
@ -33,7 +33,7 @@ def self.unit_idlers
# filter soldiers (TODO check schedule) # filter soldiers (TODO check schedule)
u.military.squad_index == -1 and u.military.squad_index == -1 and
# filter 'on break' # filter 'on break'
!u.status.misc_traits.find { |t| id = UnitMiscTrait::ENUM[t.id] ; id == :OnBreak } !u.status.misc_traits.find { |t| id == :OnBreak }
} }
end end
@ -41,7 +41,7 @@ def self.unit_entitypositions(unit)
list = [] list = []
return list if not hf = world.history.figures.binsearch(unit.hist_figure_id) return list if not hf = world.history.figures.binsearch(unit.hist_figure_id)
hf.entity_links.each { |el| hf.entity_links.each { |el|
next if el._rtti_classname != 'histfig_entity_link_positionst' next if el._rtti_classname != :histfig_entity_link_positionst
next if not ent = world.entities.all.binsearch(el.entity_id) next if not ent = world.entities.all.binsearch(el.entity_id)
next if not pa = ent.positions.assignments.binsearch(el.assignment_id) next if not pa = ent.positions.assignments.binsearch(el.assignment_id)
next if not pos = ent.positions.own.binsearch(pa.position_id) next if not pos = ent.positions.own.binsearch(pa.position_id)

@ -26,8 +26,8 @@ class Compound < MemStruct
end end
end end
def number(bits, signed, initvalue=nil) def number(bits, signed, initvalue=nil, enum=nil)
Number.new(bits, signed, initvalue) Number.new(bits, signed, initvalue, enum)
end end
def float def float
Float.new Float.new
@ -35,8 +35,8 @@ class Compound < MemStruct
def bit(shift) def bit(shift)
BitField.new(shift, 1) BitField.new(shift, 1)
end end
def bits(shift, len) def bits(shift, len, enum=nil)
BitField.new(shift, len) BitField.new(shift, len, enum)
end end
def pointer def pointer
Pointer.new((yield if block_given?)) Pointer.new((yield if block_given?))
@ -144,11 +144,12 @@ class Compound < MemStruct
end end
class Number < MemStruct class Number < MemStruct
attr_accessor :_bits, :_signed, :_initvalue attr_accessor :_bits, :_signed, :_initvalue, :_enum
def initialize(bits, signed, initvalue) def initialize(bits, signed, initvalue, enum)
@_bits = bits @_bits = bits
@_signed = signed @_signed = signed
@_initvalue = initvalue @_initvalue = initvalue
@_enum = enum
end end
def _get def _get
@ -159,10 +160,12 @@ class Number < MemStruct
when 64;(DFHack.memory_read_int32(@_memaddr) & 0xffffffff) + (DFHack.memory_read_int32(@_memaddr+4) << 32) when 64;(DFHack.memory_read_int32(@_memaddr) & 0xffffffff) + (DFHack.memory_read_int32(@_memaddr+4) << 32)
end end
v &= (1 << @_bits) - 1 if not @_signed v &= (1 << @_bits) - 1 if not @_signed
v = DFHack.const_get(@_enum)::ENUM[v] || v if @_enum
v v
end end
def _set(v) def _set(v)
v = DFHack.const_get(@_enum).const_get(v) if @_enum and v.kind_of?(::Symbol)
case @_bits case @_bits
when 32; DFHack.memory_write_int32(@_memaddr, v) when 32; DFHack.memory_write_int32(@_memaddr, v)
when 16; DFHack.memory_write_int16(@_memaddr, v) when 16; DFHack.memory_write_int16(@_memaddr, v)
@ -190,10 +193,11 @@ class Float < MemStruct
end end
end end
class BitField < MemStruct class BitField < MemStruct
attr_accessor :_shift, :_len attr_accessor :_shift, :_len, :_enum
def initialize(shift, len) def initialize(shift, len, enum=nil)
@_shift = shift @_shift = shift
@_len = len @_len = len
@_enum = enum
end end
def _mask def _mask
(1 << @_len) - 1 (1 << @_len) - 1
@ -204,7 +208,9 @@ class BitField < MemStruct
if @_len == 1 if @_len == 1
((v & 1) == 0) ? false : true ((v & 1) == 0) ? false : true
else else
v & _mask v &= _mask
v = DFHack.const_get(@_enum)::ENUM[v] || v if @_enum
v
end end
end end
@ -213,6 +219,7 @@ class BitField < MemStruct
# allow 'bit = 0' # allow 'bit = 0'
v = (v && v != 0 ? 1 : 0) v = (v && v != 0 ? 1 : 0)
end end
v = DFHack.const_get(@_enum).const_get(v) if @_enum and v.kind_of?(::Symbol)
v = (v & _mask) << @_shift v = (v & _mask) << @_shift
ori = DFHack.memory_read_int32(@_memaddr) & 0xffffffff ori = DFHack.memory_read_int32(@_memaddr) & 0xffffffff
@ -683,7 +690,7 @@ end
# try to read the rtti classname from an object vtable pointer # try to read the rtti classname from an object vtable pointer
def self.rtti_readclassname(vptr) def self.rtti_readclassname(vptr)
unless n = @rtti_v2n[vptr] unless n = @rtti_v2n[vptr]
n = @rtti_v2n[vptr] = get_rtti_classname(vptr) n = @rtti_v2n[vptr] = get_rtti_classname(vptr).to_sym
@rtti_n2v[n] = vptr @rtti_n2v[n] = vptr
end end
n n

@ -86,13 +86,13 @@ module DFHack
def find_unit(what=:selected) def find_unit(what=:selected)
if what == :selected if what == :selected
case ui.main.mode case ui.main.mode
when UiSidebarMode::ViewUnits when :ViewUnits
# nobody selected => idx == 0 # nobody selected => idx == 0
v = world.units.other[0][ui_selected_unit] v = world.units.other[0][ui_selected_unit]
v if v and v.pos.z == cursor.z v if v and v.pos.z == cursor.z
when UiSidebarMode::LookAround when :LookAround
k = ui_look_list.items[ui_look_cursor] k = ui_look_list.items[ui_look_cursor]
k.unit if k.type == UiLookList::Unit k.unit if k.type == :Unit
end end
elsif what.kind_of?(Integer) elsif what.kind_of?(Integer)
world.units.all.find { |u| u.id == what } world.units.all.find { |u| u.id == what }
@ -110,9 +110,9 @@ module DFHack
def find_item(what=:selected) def find_item(what=:selected)
if what == :selected if what == :selected
case ui.main.mode case ui.main.mode
when UiSidebarMode::LookAround when :LookAround
k = ui_look_list.items[ui_look_cursor] k = ui_look_list.items[ui_look_cursor]
k.item if k.type == UiLookList::Item k.item if k.type == :Item
end end
elsif what.kind_of?(Integer) elsif what.kind_of?(Integer)
world.items.all.find { |i| i.id == what } world.items.all.find { |i| i.id == what }