ruby: tweak enums

develop
jj 2012-05-10 23:27:42 +02:00
parent 987cf697db
commit 607cd9c8f2
4 changed files with 61 additions and 43 deletions

@ -27,13 +27,6 @@ sub rb_ucase {
return join("", map { ucfirst $_ } (split('_', $name)));
}
my %global_type_renderer = (
'enum-type' => \&render_global_enum,
'struct-type' => \&render_global_struct,
'class-type' => \&render_global_class,
'bitfield-type' => \&render_global_bitfield,
);
my %item_renderer = (
'global' => \&render_item_global,
'number' => \&render_item_number,
@ -51,7 +44,7 @@ sub render_global_enum {
my ($name, $type) = @_;
my $rbname = rb_ucase($name);
push @lines_rb, "class $rbname";
push @lines_rb, "class $rbname < MemHack::Enum";
indent_rb {
render_enum_fields($type);
};
@ -61,8 +54,8 @@ sub render_enum_fields {
my ($type) = @_;
my $value = -1;
my $idxname = 'ENUM';
push @lines_rb, "$idxname = Hash.new";
push @lines_rb, "ENUM = Hash.new";
push @lines_rb, "NUME = Hash.new";
my %attr_type;
my %attr_list;
@ -100,7 +93,7 @@ sub render_enum_fields {
if ($elemname) {
my $rbelemname = rb_ucase($elemname);
push @lines_rb, "$rbelemname = $value ; ${idxname}[$value] = :$rbelemname";
push @lines_rb, "ENUM[$value] = :$rbelemname ; NUME[:$rbelemname] = $value";
for my $iattr ($item->findnodes('child::item-attr')) {
my $ian = $iattr->getAttribute('name');
my $iav = $iattr->getAttribute('value');
@ -119,6 +112,10 @@ sub render_enum_fields {
sub render_global_bitfield {
my ($name, $type) = @_;
push @lines_cpp, "}" if @include_cpp;
push @lines_cpp, "void cpp_$name(FILE *fout) {";
push @include_cpp, $name;
my $rbname = rb_ucase($name);
push @lines_rb, "class $rbname < MemHack::Compound";
indent_rb {
@ -146,7 +143,7 @@ sub render_bitfield_fields {
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);
push @lines_rb, "field(:$name, 0) { bits $shift, $count, $enum }" if ($name);
} else {
push @lines_rb, "field(:$name, 0) { bits $shift, $count }" if ($name);
}
@ -367,7 +364,7 @@ sub render_item_number {
return;
}
$lines_rb[$#lines_rb] .= ", $initvalue" if ($initvalue);
$lines_rb[$#lines_rb] .= ", :$typename" if ($typename);
$lines_rb[$#lines_rb] .= ", $typename" if ($typename);
}
sub render_item_compound {
@ -391,7 +388,7 @@ sub render_item_compound {
};
push @lines_rb, "}"
} elsif ($subtype eq 'enum') {
push @lines_rb, "class ::DFHack::$classname";
push @lines_rb, "class ::DFHack::$classname < MemHack::Enum";
indent_rb {
# declare constants
render_enum_fields($item);
@ -425,7 +422,7 @@ sub render_item_container {
push @lines_rb, "}";
} elsif ($indexenum) {
$indexenum = rb_ucase($indexenum);
push @lines_rb, "$rbmethod(:$indexenum)";
push @lines_rb, "$rbmethod($indexenum)";
} else {
push @lines_rb, "$rbmethod";
}
@ -457,7 +454,7 @@ sub render_item_staticarray {
my $indexenum = $item->getAttribute('index-enum');
if ($indexenum) {
$indexenum = rb_ucase($indexenum);
push @lines_rb, "static_array($count, $tglen, :$indexenum) {";
push @lines_rb, "static_array($count, $tglen, $indexenum) {";
} else {
push @lines_rb, "static_array($count, $tglen) {";
}
@ -602,12 +599,26 @@ if ($offsetfile) {
my $doc = XML::LibXML->new()->parse_file($input);
$global_types{$_->getAttribute('type-name')} = $_ foreach $doc->findnodes('/ld:data-definition/ld:global-type');
my @nonenums;
for my $name (sort { $a cmp $b } keys %global_types) {
my $type = $global_types{$name};
my $meta = $type->getAttribute('ld:meta');
my $renderer = $global_type_renderer{$meta};
if ($renderer) {
$renderer->($name, $type);
if ($meta eq 'enum-type') {
render_global_enum($name, $type);
} else {
push @nonenums, $name;
}
}
for my $name (@nonenums) {
my $type = $global_types{$name};
my $meta = $type->getAttribute('ld:meta');
if ($meta eq 'struct-type') {
render_global_struct($name, $type);
} elsif ($meta eq 'class-type') {
render_global_class($name, $type);
} elsif ($meta eq 'bitfield-type') {
render_global_bitfield($name, $type);
} else {
print "no render global type $meta\n";
}

@ -3,7 +3,7 @@ module DFHack
def self.unit_citizens
race = ui.race_id
civ = ui.civ_id
world.units.other[0].find_all { |u|
world.units.active.find_all { |u|
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

@ -160,6 +160,25 @@ class Compound < MemStruct
end
end
class Enum
# number -> symbol
def self.enum
# ruby weirdness, needed to make the constants 'virtual'
@enum ||= const_get(:ENUM)
end
# symbol -> number
def self.nume
@nume ||= const_get(:NUME)
end
def self.to_i(i)
nume[i] || i
end
def self.to_sym(i)
enum[i] || i
end
end
class Number < MemStruct
attr_accessor :_bits, :_signed, :_initvalue, :_enum
def initialize(bits, signed, initvalue, enum)
@ -177,12 +196,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 = @_enum.to_sym(v) if @_enum
v
end
def _set(v)
v = DFHack.const_get(@_enum).const_get(v) if @_enum and v.kind_of?(::Symbol)
v = @_enum.to_i(v) if @_enum
case @_bits
when 32; DFHack.memory_write_int32(@_memaddr, v)
when 16; DFHack.memory_write_int16(@_memaddr, v)
@ -225,7 +244,7 @@ class BitField < MemStruct
((v & 1) == 0) ? false : true
else
v &= _mask
v = DFHack.const_get(@_enum)::ENUM[v] || v if @_enum
v = @_enum.to_sym(v) if @_enum
v
end
end
@ -235,7 +254,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 = @_enum.to_i(v) if @_enum
v = (v & _mask) << @_shift
ori = DFHack.memory_read_int32(@_memaddr) & 0xffffffff
@ -313,21 +332,11 @@ class PointerAry < MemStruct
def inspect ; ptr = _getp ; (ptr == 0) ? 'NULL' : "#<PointerAry #{'0x%X' % ptr}>" ; end
end
module IndexEnum
def indexenum(idx)
if idx.kind_of?(::Symbol) or idx.kind_of?(::String) and _indexenum
DFHack.const_get(_indexenum).const_get(idx) || idx
else
idx
end
end
end
module Enumerable
include ::Enumerable
attr_accessor :_indexenum
def each ; (0...length).each { |i| yield self[i] } ; end
def inspect
enum = DFHack.const_get(_indexenum)::ENUM if _indexenum
out = '['
each_with_index { |e, idx|
out << ', ' if out.length > 1
@ -335,7 +344,7 @@ module Enumerable
out << '...'
break
end
out << "#{enum[idx] || idx}=" if enum
out << "#{_indexenum.to_sym(idx)}=" if _indexenum
out << e.inspect
}
out << ']'
@ -344,7 +353,6 @@ module Enumerable
def flatten ; map { |e| e.respond_to?(:flatten) ? e.flatten : e }.flatten ; end
end
class StaticArray < MemStruct
include IndexEnum
attr_accessor :_tglen, :_length, :_indexenum, :_tg
def initialize(tglen, length, indexenum, tg)
@_tglen = tglen
@ -364,12 +372,12 @@ class StaticArray < MemStruct
@_tg._at(@_memaddr + i*@_tglen) if i >= 0 and i < @_length
end
def [](i)
i = indexenum(i)
i = _indexenum.to_i(i) if _indexenum
i += @_length if i < 0
_tgat(i)._get
end
def []=(i, v)
i = indexenum(i)
i = _indexenum.to_i(i) if _indexenum
i += @_length if i < 0
_tgat(i)._set(v)
end
@ -547,7 +555,6 @@ class StlDeque < MemStruct
end
class DfFlagarray < MemStruct
include IndexEnum
attr_accessor :_indexenum
def initialize(indexenum)
@_indexenum = indexenum
@ -561,12 +568,12 @@ class DfFlagarray < MemStruct
DFHack.memory_bitarray_resize(@_memaddr, len)
end
def [](idx)
idx = indexenum(idx)
idx = _indexenum.to_i(idx) if _indexenum
idx += length if idx < 0
DFHack.memory_bitarray_isset(@_memaddr, idx) if idx >= 0 and idx < length
end
def []=(idx, v)
idx = indexenum(idx)
idx = _indexenum.to_i(idx) if _indexenum
idx += length if idx < 0
if idx >= length or idx < 0
raise 'invalid idx'

@ -88,7 +88,7 @@ module DFHack
case ui.main.mode
when :ViewUnits
# nobody selected => idx == 0
v = world.units.other[0][ui_selected_unit]
v = world.units.active[ui_selected_unit]
v if v and v.pos.z == cursor.z
when :LookAround
k = ui_look_list.items[ui_look_cursor]
@ -261,7 +261,7 @@ module DFHack
# link a job to the world
# allocate & set job.id, allocate a JobListLink, link to job & world.job_list
def link_job(job)
def job_link(job)
lastjob = world.job_list
lastjob = lastjob.next while lastjob.next
joblink = JobListLink.cpp_new