File: Register.pm

package info (click to toggle)
latexml 0.8.8-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 31,920 kB
  • sloc: xml: 109,048; perl: 30,224; sh: 179; javascript: 28; makefile: 13
file content (172 lines) | stat: -rw-r--r-- 6,457 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# /=====================================================================\ #
# |  LaTeXML::Core::Definition::Register                                | #
# | Representation of definitions of Control Sequences                  | #
# |=====================================================================| #
# | Part of LaTeXML:                                                    | #
# |  Public domain software, produced as part of work done by the       | #
# |  United States Government & not subject to copyright in the US.     | #
# |---------------------------------------------------------------------| #
# | Bruce Miller <bruce.miller@nist.gov>                        #_#     | #
# | http://dlmf.nist.gov/LaTeXML/                              (o o)    | #
# \=========================================================ooo==U==ooo=/ #
package LaTeXML::Core::Definition::Register;
use strict;
use warnings;
use LaTeXML::Global;
use LaTeXML::Common::Object;
use LaTeXML::Common::Error;
use base qw(LaTeXML::Core::Definition::Primitive);

# Known Traits:
#    address : address to store in State's value table; defaults to the cs
#    getter : a sub to get the value; otherwise stores in State value table under address
#    setter : a sub to set the value; ditto
#    registerType : the type of register value (a LaTeXML class)
#    beforeDigest, afterDigest : code for before/after digestion daemons
#    readonly : whether this register can only be read
#    default  : default value; safety for when no value assigned
sub new {
  my ($class, $cs, $parameters, %traits) = @_;
  $traits{address} = ToString($cs) unless defined $traits{address};
  return bless { cs => $cs, parameters => $parameters,
    locator => $STATE->getStomach->getGullet->getMouth->getLocator,
    %traits }, $class; }

sub isPrefix {
  return 0; }

sub isRegister {
  my ($self) = @_;
  return $$self{registerType}; }

sub getAddress {
  my ($self) = @_;
  return $$self{address} || $self->getCSName; }

sub isReadonly {
  my ($self) = @_;
  return $$self{readonly}; }

sub valueOf {
  my ($self, @args) = @_;
  if (my $getter = $$self{getter}) {
    return &{ $$self{getter} }(@args); }
  else {
    my $loc = (@args ? join('', $$self{address}, map { ToString($_) } @args) : $$self{address});
    return $STATE->lookupValue($loc) || $$self{default}; } }

sub setValue {
  my ($self, $value, $scope, @args) = @_;
  my $tracing = (($STATE->lookupValue('TRACING') || 0) & TRACE_COMMANDS);
  if ($tracing) {
    my $scope  = $STATE->getPrefix('global') ? 'globally ' : '';
    my $csname = ToString($$self{cs});
    Debug("{$scope" . "changing " . $csname . "=" . ToString($self->valueOf(@args)) . "}"); }
  if (my $setter = $$self{setter}) {
    &{ $$self{setter} }($value, $scope, @args); }
  elsif ($$self{readonly}) {
    Warn('unexpected', $$self{cs}, $STATE->getStomach,
      "Can't assign readonly register " . ToString($$self{cs}) . " to " . ToString($value)); }
  else {
    my $loc = (@args ? join('', $$self{address}, map { ToString($_) } @args) : $$self{address});
    $STATE->assignValue($loc => $value, $scope); }
  Debug("{into " . ToString($$self{cs}) . "=" . ToString($self->valueOf(@args)) . "}") if $tracing;
  return; }

sub addValue {
  my ($self, $value, $scope, @args) = @_;
  my $oldvalue;
  if (my $getter = $$self{getter}) {
    $oldvalue = &{ $$self{getter} }(@args); }
  else {
    my $loc = (@args ? join('', $$self{address}, map { ToString($_) } @args) : $$self{address});
    $oldvalue = $STATE->lookupValue($loc) || $$self{default}; }
  my $newvalue = $oldvalue->add($value);
  if (my $setter = $$self{setter}) {
    &{ $$self{setter} }($newvalue, $scope, @args); }
  elsif ($$self{readonly}) {
    Warn('unexpected', $$self{cs}, $STATE->getStomach,
      "Can't assign readonly register $$self{address} to " . ToString($value)); }
  else {
    my $loc = (@args ? join('', $$self{address}, map { ToString($_) } @args) : $$self{address});
    $STATE->assignValue($loc => $newvalue, $scope); }
  return; }

# No before/after daemons ???
# (other than afterassign)
sub invoke {
  my ($self, $stomach) = @_;
  my $_tracing = $STATE->lookupValue('TRACING') || 0;
  my $profiled = ($_tracing & TRACE_PROFILE) && ($LaTeXML::CURRENT_TOKEN || $$self{cs});
  LaTeXML::Core::Definition::startProfiling($profiled, 'digest') if $profiled;

  my $gullet = $stomach->getGullet;
  my $parms  = $$self{parameters};
  my @args   = ($parms ? $parms->readArguments($gullet) : ());
  $gullet->readKeyword('=');    # Ignore
  my $value = $gullet->readValue($self->isRegister);
  $self->setValue($value, undef, @args);

  # Tracing ?
  if (my $after = $STATE->lookupValue('afterAssignment')) {
    $STATE->assignValue(afterAssignment => undef, 'global');
    $gullet->unread($after); }    # primitive returns boxes, so these need to be digested!
  LaTeXML::Core::Definition::stopProfiling($profiled, 'digest') if $profiled;
  return; }

sub equals {
  my ($self, $other) = @_;
  return (defined $other
      && (ref $self) eq (ref $other)) && Equals($self->getParameters, $other->getParameters)
    && Equals($$self{address}, $$other{address}); }

#===============================================================================
1;

__END__

=pod

=head1 NAME

C<LaTeXML::Core::Definition::Register>  - Control sequence definitions for Registers.

=head1 DESCRIPTION

These are set up as a speciallized primitive with a getter and setter
to access and store values in the Stomach.
See L<LaTeXML::Package> for the most convenient means to create them.

It extends L<LaTeXML::Core::Definition::Primitive>.

Registers generally store some value in the current C<LaTeXML::Core::State>, but are not
required to. Like TeX's registers, when they are digested, they expect an optional
C<=>, and then a value of the appropriate type. Register definitions support these
additional methods:

=head1 Methods

=over 4

=item C<< $value = $register->valueOf(@args); >>

Return the value associated with the register, by invoking it's C<getter> function.
The additional args are used by some registers
to index into a set, such as the index to C<\count>.

=item C<< $register->setValue($value,$scope,@args); >>

Assign a value to the register, by invoking it's C<setter> function.

=back

=head1 AUTHOR

Bruce Miller <bruce.miller@nist.gov>

=head1 COPYRIGHT

Public domain software, produced as part of work done by the
United States Government & not subject to copyright in the US.

=cut