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 %seen_enum_name;
our %seen_enum_name;
sub render_global_enum {
my ($name, $type) = @_;
@ -72,6 +72,7 @@ sub render_enum_fields {
for my $attr ($type->findnodes('child::enum-attr')) {
my $rbattr = rb_ucase($attr->getAttribute('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 ($global_types{$typeattr}) {
$attr_type{$rbattr} = 'symbol';
@ -85,6 +86,7 @@ sub render_enum_fields {
my $def = $attr->getAttribute('default-value');
if ($def) {
$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');
push @lines_rb, "$rbattr = Hash.new($def)";
} else {
@ -106,6 +108,7 @@ sub render_enum_fields {
my $iav = $iattr->getAttribute('value');
my $rbattr = rb_ucase($ian);
$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');
$lines_rb[$#lines_rb] .= " ; ${rbattr}[$value] = $iav";
}
@ -137,10 +140,14 @@ sub render_bitfield_fields {
for my $field ($type->findnodes('child::ld:field')) {
my $count = $field->getAttribute('count') || 1;
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);
print "bitfield $name !number\n" if (!($field->getAttribute('ld:meta') eq 'number'));
if ($count == 1) {
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 {
push @lines_rb, "field(:$name, 0) { bits $shift, $count }" if ($name);
}
@ -189,7 +196,7 @@ sub render_global_class {
indent_rb {
my $sz = query_cpp("sizeof($cppns)");
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");
};
push @lines_rb, "end\n";
@ -292,10 +299,13 @@ sub render_item_number {
my $subtype = $item->getAttribute('ld:subtype');
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');
# XXX needs pre-declaration of the enum...
$initvalue = rb_ucase($item->getAttribute('type-name')) . '::' . $initvalue if ($initvalue and $subtype and $subtype eq 'enum' and $initvalue =~ /[a-zA-Z]/);
$initvalue = ":$initvalue" if ($initvalue and $typename 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 = 'int32_t' if (!$subtype);
@ -324,6 +334,7 @@ sub render_item_number {
return;
}
$lines_rb[$#lines_rb] .= ", $initvalue" if ($initvalue);
$lines_rb[$#lines_rb] .= ", :$typename" if ($typename);
}
sub render_item_compound {
@ -342,10 +353,19 @@ sub render_item_compound {
};
push @lines_rb, "}"
} elsif ($subtype eq 'enum') {
# declare constants
render_enum_fields($item);
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
render_enum_fields($item);
};
push @lines_rb, "end\n";
# actual field
render_item_number($item, $cppns);
render_item_number($item, $enumclassname);
} else {
print "no render compound $subtype\n";
}

@ -3,7 +3,7 @@ def self.each_tree(material=:any)
@raws_tree_name ||= {}
if @raws_tree_name.empty?
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
@ -25,7 +25,7 @@ def self.each_shrub(material=:any)
@raws_shrub_name ||= {}
if @raws_tree_name.empty?
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
@ -61,8 +61,8 @@ def self.cuttrees(material=nil, count_max=100)
b = map_block_at(plant)
d = b.designation[plant.pos.x%16][plant.pos.y%16]
next if d.hidden
if d.dig == TileDigDesignation::No
d.dig = TileDigDesignation::Default
if d.dig == :No
d.dig = :Default
b.flags.designated = true
cnt += 1
break if cnt == count_max
@ -116,9 +116,9 @@ def self.growcrops(material=nil, count_max=100)
if !material
cnt = Hash.new(0)
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.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]
cnt[seed.mat_index] += 1
}
@ -137,10 +137,10 @@ def self.growcrops(material=nil, count_max=100)
cnt = 0
suspend {
world.items.other[ItemsOtherId::SEEDS].each { |seed|
world.items.other[:SEEDS].each { |seed|
next if wantmat and seed.mat_index != wantmat
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]
seed.grow_counter = @raws_plant_growdur[seed.mat_index]
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.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.mood != MoodType::Berserk
u.mood != :Berserk
# TODO check curse ; currently this should keep vampires, but may include werebeasts
}
end
@ -15,9 +15,9 @@ end
# list workers (citizen, not crazy / child / inmood / noble)
def self.unit_workers
unit_citizens.find_all { |u|
u.mood == MoodType::None and
Profession::ENUM[u.profession] != :CHILD and
Profession::ENUM[u.profession] != :BABY and
u.mood == :None and
u.profession != :CHILD and
u.profession != :BABY and
# TODO MENIAL_WORK_EXEMPTION_SPOUSE
!unit_entitypositions(u).find { |pos| pos.flags[:MENIAL_WORK_EXEMPTION] }
}
@ -33,7 +33,7 @@ def self.unit_idlers
# filter soldiers (TODO check schedule)
u.military.squad_index == -1 and
# 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
@ -41,7 +41,7 @@ def self.unit_entitypositions(unit)
list = []
return list if not hf = world.history.figures.binsearch(unit.hist_figure_id)
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 pa = ent.positions.assignments.binsearch(el.assignment_id)
next if not pos = ent.positions.own.binsearch(pa.position_id)

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

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