[system] / trunk / pg / macros / contextLimitedVector.pl Repository:
ViewVC logotype

Annotation of /trunk/pg/macros/contextLimitedVector.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3371 - (view) (download) (as text)

1 : dpvc 2726 loadMacros("Parser.pl");
2 :    
3 :     sub _contextLimitedVector_init {}; # don't load it again
4 :    
5 :     ##########################################################
6 :     #
7 :     # Implements a context in which vectors can be entered,
8 :     # but no vector operations are permitted. So students will
9 :     # be able to perform operations within the coordinates
10 :     # of the vectors, but not between vectors.
11 :     #
12 :     # Vectors can still be entered either in < , , > or ijk format.
13 :     # Most of the complication here is to handle ijk format
14 :     # properly. Each coordinate vector is allowed to appear
15 :     # only once, so we have to keep track of that, and allow
16 :     # SOME vector operations, but only when one term is
17 :     # one of the coordinate constants, or one of the formulas
18 :     # we've already OKed.
19 :     #
20 :     # You control which format to use by setting the context
21 :     # to one of the following:
22 :     #
23 :     # Context("LimitedVector-coordinate");
24 :     # Context("LimitedVector-ijk");
25 :     # Context("LimitedVector"); # either one
26 :     #
27 :    
28 :     #
29 :     # Handle common checking for BOPs
30 :     #
31 :     package LimitedVector::BOP;
32 :    
33 :     #
34 :     # Do original check and then if the operands are numbers, its OK.
35 :     # Otherwise, check if there is a duplicate constant from either term
36 :     # Otherwise, do an operator-specific check for if vectors are OK.
37 :     # Otherwise report an error.
38 :     #
39 :     sub _check {
40 :     my $self = shift;
41 :     my $super = ref($self); $super =~ s/LimitedVector/Parser/;
42 :     &{$super."::_check"}($self);
43 :     return if $self->checkNumbers;
44 :     if ($self->{equation}{context}{flags}{vector_format} ne 'coordinate') {
45 :     $self->checkConstants($self->{lop});
46 :     $self->checkConstants($self->{rop});
47 :     return if $self->checkVectors;
48 :     }
49 :     my $bop = $self->{def}{string} || $self->{bop};
50 : dpvc 3371 $self->Error("In this context, '%s' can only be used with Numbers",$bop)
51 : dpvc 2726 if $self->{equation}{context}{flags}{vector_format} eq 'coordinate';
52 : dpvc 3371 $self->Error("In this context, '%s' can only be used with Numbers or i,j and k",$bop);
53 : dpvc 2726 }
54 :    
55 :     #
56 :     # filled in by subclasses
57 :     #
58 :     sub checkVectors {return 0}
59 :    
60 :     #
61 :     # Check if a constant has been repeated
62 :     # (we maintain a hash that lists if one is below us in the parse tree)
63 :     #
64 :     sub checkConstants {
65 :     my $self = shift; my $op = shift;
66 :     my $duplicate = '';
67 :     if ($op->class eq 'Constant') {
68 :     return unless $op->{name} =~ m/^[ijk]$/;
69 :     $duplicate = $op->{name} if $self->{ijk}{$op->{name}};
70 :     $self->{ijk}{$op->{name}} = 1;
71 :     } else {
72 :     foreach my $x ('i','j','k') {
73 :     $duplicate = $x if $self->{ijk}{$x} && $op->{ijk}{$x};
74 :     $self->{ijk}{$x} = $self->{ijk}{$x} || $op->{ijk}{$x};
75 :     }
76 :     }
77 : dpvc 3371 Value::Error("The constant '%s' may appear only once in your formula",$duplicate)
78 : dpvc 2726 if $duplicate;
79 :     }
80 :    
81 :     ##############################################
82 :     #
83 :     # Now we get the individual replacements for the operators
84 :     # that we don't want to allow. We inherit everything from
85 :     # the original Parser::BOP class, and just add the
86 :     # vector checks here.
87 :     #
88 :    
89 :     package LimitedVector::BOP::add;
90 :     our @ISA = qw(LimitedVector::BOP Parser::BOP::add);
91 :    
92 :     sub checkVectors {
93 :     my $self = shift;
94 :     return (($self->{lop}->class eq 'Constant' || $self->{lop}->class =~ m/[BU]OP/) &&
95 :     ($self->{rop}->class eq 'Constant' || $self->{rop}->class =~ m/[BU]OP/));
96 :     }
97 :    
98 :     ##############################################
99 :    
100 :     package LimitedVector::BOP::subtract;
101 :     our @ISA = qw(LimitedVector::BOP Parser::BOP::subtract);
102 :    
103 :     sub checkVectors {
104 :     my $self = shift;
105 :     return (($self->{lop}->class eq 'Constant' || $self->{lop}->class =~ m/[BU]OP/) &&
106 :     ($self->{rop}->class eq 'Constant' || $self->{rop}->class =~ m/[BU]OP/));
107 :     }
108 :    
109 :     ##############################################
110 :    
111 :     package LimitedVector::BOP::multiply;
112 :     our @ISA = qw(LimitedVector::BOP Parser::BOP::multiply);
113 :    
114 :     sub checkVectors {
115 :     my $self = shift;
116 :     return (($self->{lop}->class eq 'Constant' || $self->{lop}->type eq 'Number') &&
117 :     ($self->{rop}->class eq 'Constant' || $self->{rop}->type eq 'Number'));
118 :     }
119 :    
120 :     ##############################################
121 :    
122 :     package LimitedVector::BOP::divide;
123 :     our @ISA = qw(LimitedVector::BOP Parser::BOP::divide);
124 :    
125 :     sub checkVectors {
126 :     my $self = shift;
127 :     my $bop = $self->{def}{string} || $self->{bop};
128 : dpvc 3371 $self->Error("In this context, '%s' can only be used with Numbers",$bop);
129 : dpvc 2726 }
130 :    
131 :     ##############################################
132 :     ##############################################
133 :     #
134 :     # Now we do the same for the unary operators
135 :     #
136 :    
137 :     package LimitedVector::UOP;
138 :    
139 :     sub _check {
140 :     my $self = shift;
141 :     my $super = ref($self); $super =~ s/LimitedVector/Parser/;
142 :     &{$super."::_check"}($self);
143 :     return if $self->checkNumber;
144 :     if ($self->{equation}{context}{flags}{vector_format} ne 'coordinate') {
145 :     LimitedVector::BOP::checkConstants($self,$self->{op});
146 :     return if $self->checkVector;
147 :     }
148 :     my $uop = $self->{def}{string} || $self->{uop};
149 : dpvc 3371 $self->Error("In this context, '%s' can only be used with Numbers",$uop)
150 : dpvc 2726 if $self->{equation}{context}{flags}{vector_format} eq 'coordinate';
151 : dpvc 3371 $self->Error("In this context, '%s' can only be used with Numbers or i,j and k",$uop);
152 : dpvc 2726 }
153 :    
154 :     sub checkVector {return 0}
155 :    
156 :     ##############################################
157 :    
158 :     package LimitedVector::UOP::plus;
159 :     our @ISA = qw(LimitedVector::UOP Parser::UOP::plus);
160 :    
161 :     sub checkVector {return shift->{op}->class eq 'Constant'}
162 :    
163 :     ##############################################
164 :    
165 :     package LimitedVector::UOP::minus;
166 :     our @ISA = qw(LimitedVector::UOP Parser::UOP::minus);
167 :    
168 :     sub checkVector {return shift->{op}->class eq 'Constant'}
169 :    
170 :     ##############################################
171 :     ##############################################
172 :     #
173 :     # Absolute value does vector norm, so we
174 :     # trap that as well.
175 :     #
176 :    
177 :     package LimitedVector::List::AbsoluteValue;
178 :     our @ISA = qw(Parser::List::AbsoluteValue);
179 :    
180 :     sub _check {
181 :     my $self = shift;
182 :     $self->SUPER::_check;
183 :     return if $self->{coords}[0]->type eq 'Number';
184 :     $self->Error("Vector norm is not allowed in this context");
185 :     }
186 :    
187 :     ##############################################
188 :    
189 :     package LimitedVector::List::Vector;
190 :     our @ISA = qw(Parser::List::Vector);
191 :    
192 :     sub _check {
193 :     my $self = shift;
194 :     $self->SUPER::_check;
195 :     return if $self->{equation}{context}{flags}{vector_format} ne 'ijk';
196 :     $self->Error("Vectors must be given in the form 'ai+bj+ck' in this context");
197 :     }
198 :    
199 :     ##############################################
200 :     ##############################################
201 :    
202 :     package main;
203 :    
204 :     #
205 :     # Now build the new context that calls the
206 :     # above classes rather than the usual ones
207 :     #
208 :    
209 :     $context{LimitedVector} = Context("Vector");
210 :     $context{LimitedVector}->operators->set(
211 :     '+' => {class => 'LimitedVector::BOP::add'},
212 :     '-' => {class => 'LimitedVector::BOP::subtract'},
213 :     '*' => {class => 'LimitedVector::BOP::multiply'},
214 :     '* ' => {class => 'LimitedVector::BOP::multiply'},
215 :     ' *' => {class => 'LimitedVector::BOP::multiply'},
216 :     ' ' => {class => 'LimitedVector::BOP::multiply'},
217 :     '/' => {class => 'LimitedVector::BOP::divide'},
218 :     ' /' => {class => 'LimitedVector::BOP::divide'},
219 :     '/ ' => {class => 'LimitedVector::BOP::divide'},
220 :     'u+' => {class => 'LimitedVector::UOP::plus'},
221 :     'u-' => {class => 'LimitedVector::UOP::minus'},
222 :     );
223 :     #
224 :     # Remove these operators and functions
225 :     #
226 :     $context{LimitedVector}->operators->undefine('_','U','><','.');
227 :     $context{LimitedVector}->functions->undefine('norm','unit');
228 :     $context{LimitedVector}->lists->set(
229 :     AbsoluteValue => {class => 'LimitedVector::List::AbsoluteValue'},
230 :     Vector => {class => 'LimitedVector::List::Vector'},
231 :     );
232 :     #
233 :     # Format can be 'coordinate', 'ijk', or 'either'
234 :     #
235 :     $context{LimitedVector}->flags->set(vector_format => 'either');
236 :    
237 :     $context{'LimitedVector-ijk'} = $context{LimitedVector}->copy;
238 :     $context{'LimitedVector-ijk'}->flags->set(vector_format => 'ijk');
239 :    
240 :     $context{'LimitedVector-coordinate'} = $context{LimitedVector}->copy;
241 :     $context{'LimitedVector-coordinate'}->flags->set(vector_format => 'coordinate');
242 :     $context{'LimitedVector-coordinate'}->constants->undefine('i','j','k');
243 :    
244 :     Context("LimitedVector");

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9