forked from openwebwork/pg
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontextLimitedPoint.pl
168 lines (134 loc) · 5.14 KB
/
contextLimitedPoint.pl
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
################################################################################
# WeBWorK Online Homework Delivery System
# Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/
# $CVSHeader: pg/macros/contextLimitedPoint.pl,v 1.14 2009/06/25 23:28:44 gage Exp $
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of either: (a) the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version, or (b) the "Artistic License" which comes with this package.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
# Artistic License for more details.
################################################################################
=head1 NAME
contextLimitedPoint.pl - Allow point entry but no point operations.
=head1 DESCRIPTION
Implements a context in which points can be entered,
but no operations are permitted between points. So
students will be able to perform operations within the
coordinates of the points, but not between points.
Context("LimitedPoint")
=cut
loadMacros("MathObjects.pl");
sub _contextLimitedPoint_init {LimitedPoint::Init()}; # don't load it again
##################################################
#
# Handle common checking for BOPs
#
package LimitedPoint::BOP;
#
# Do original check and then if the operands are numbers, its OK.
# Otherwise report an error.
#
sub _check {
my $self = shift;
my $super = ref($self); $super =~ s/LimitedPoint/Parser/;
&{$super."::_check"}($self);
return if $self->checkNumbers;
my $bop = $self->{def}{string} || $self->{bop};
$self->Error("In this context, '%s' can only be used with Numbers",$bop);
}
##############################################
#
# Now we get the individual replacements for the operators
# that we don't want to allow. We inherit everything from
# the original Parser::BOP class, except the _check
# routine, which comes from LimitedPoint::BOP above.
#
package LimitedPoint::BOP::add;
our @ISA = qw(LimitedPoint::BOP Parser::BOP::add);
##############################################
package LimitedPoint::BOP::subtract;
our @ISA = qw(LimitedPoint::BOP Parser::BOP::subtract);
##############################################
package LimitedPoint::BOP::multiply;
our @ISA = qw(LimitedPoint::BOP Parser::BOP::multiply);
##############################################
package LimitedPoint::BOP::divide;
our @ISA = qw(LimitedPoint::BOP Parser::BOP::divide);
##############################################
##############################################
#
# Now we do the same for the unary operators
#
package LimitedPoint::UOP;
sub _check {
my $self = shift;
my $super = ref($self); $super =~ s/LimitedPoint/Parser/;
&{$super."::_check"}($self);
return if $self->checkNumber;
my $uop = $self->{def}{string} || $self->{uop};
$self->Error("In this context, '%s' can only be used with Numbers",$uop);
}
##############################################
package LimitedPoint::UOP::plus;
our @ISA = qw(LimitedPoint::UOP Parser::UOP::plus);
##############################################
package LimitedPoint::UOP::minus;
our @ISA = qw(LimitedPoint::UOP Parser::UOP::minus);
##############################################
##############################################
#
# Absolute value does vector norm, so we
# trap that as well.
#
package LimitedPoint::List::AbsoluteValue;
our @ISA = qw(Parser::List::AbsoluteValue);
sub _check {
my $self = shift;
$self->SUPER::_check;
return if $self->{coords}[0]->type eq 'Number';
$self->Error("Vector norm is not allowed in this context");
}
##############################################
##############################################
package LimitedPoint;
sub Init {
#
# Build the new context that calls the
# above classes rather than the usual ones
#
my $context = $main::context{LimitedPoint} = Parser::Context->getCopy("Point");
$context->{name} = "LimitedPoint";
$context->operators->set(
'+' => {class => 'LimitedPoint::BOP::add'},
'-' => {class => 'LimitedPoint::BOP::subtract'},
'*' => {class => 'LimitedPoint::BOP::multiply'},
'* ' => {class => 'LimitedPoint::BOP::multiply'},
' *' => {class => 'LimitedPoint::BOP::multiply'},
' ' => {class => 'LimitedPoint::BOP::multiply'},
'/' => {class => 'LimitedPoint::BOP::divide'},
' /' => {class => 'LimitedPoint::BOP::divide'},
'/ ' => {class => 'LimitedPoint::BOP::divide'},
'u+' => {class => 'LimitedPoint::UOP::plus'},
'u-' => {class => 'LimitedPoint::UOP::minus'},
);
#
# Remove these operators and functions
#
$context->operators->undefine('_','U','><','.');
$context->functions->undefine('norm','unit');
$context->lists->set(
AbsoluteValue => {class => 'LimitedPoint::List::AbsoluteValue'},
);
$context->parens->set(
'(' => {formMatrix => 0},
'[' => {formMatrix => 0},
);
$context->variables->are(x=>'Real');
main::Context("LimitedPoint"); ### FIXME: probably should require author to set this explicitly
}
1;