Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Fraction contexts as extensions so you can add fractions to other compatible contexts. #1108

Merged
merged 10 commits into from
Dec 3, 2024
9 changes: 4 additions & 5 deletions lib/Value.pm
Original file line number Diff line number Diff line change
Expand Up @@ -308,10 +308,9 @@ sub matchNumber { my $n = shift; $n =~ m/^$$Value::context->{pattern}{signedNu
sub matchInfinite { my $n = shift; $n =~ m/^$$Value::context->{pattern}{infinite}$/i }
sub isReal { classMatch(shift, 'Real') }
sub isComplex { classMatch(shift, 'Complex') }
# sub isContext {class(shift) eq 'Context'} # MEG
sub isContext { my $symbol = shift || ""; class($symbol) eq 'Context' }
sub isFormula { classMatch(shift, 'Formula') }
sub isParser { my $v = shift; isBlessed($v) && $v->isa('Parser::Item') }
sub isContext { class(shift // '') eq 'Context' }
sub isFormula { classMatch(shift, 'Formula') }
sub isParser { my $v = shift; isBlessed($v) && $v->isa('Parser::Item') }

sub isValue {
my $v = shift // '';
Expand All @@ -321,7 +320,7 @@ sub isValue {
sub isNumber {
my $n = shift;
return $n->{tree}->isNumber if isFormula($n);
return classMatch($n, 'Real', 'Complex') || matchNumber($n);
return (isValue($n) && ($n->type eq 'Number' || classMatch($n, 'Real', 'Complex'))) || matchNumber($n);
}

sub isRealNumber {
Expand Down
40 changes: 27 additions & 13 deletions macros/contexts/contextExtensions.pl
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,9 @@ sub makeSubclass {
# create a subclass of this class and define its extensionContext()
# method to return your base context name, and then include that
# subclass in your @ISA arrays for your new classes that override the
# original context's classes.
# original context's classes. (This is not strictly necessary, but
# it is more efficient to do this than to have the Super class
# have to figure it out every time a Super method is used.)
#
# For our quaternions example, you would use
#
Expand Down Expand Up @@ -364,6 +366,11 @@ sub makeSubclass {
#
# would get the string output from the original class.
#
# If you are defining a new() or make() method (where the $self could be
# the class name rather than a class instance), you will need to pass the
# context to mutate(), super(), or superClass(). See the example for
# new() below.
#
# The superClass() method gets you the name of the original class, in
# case you need to access any class variables from that.
#
Expand All @@ -373,8 +380,8 @@ package context::Extensions::Super;
# Get a method from the original class from the extended context
#
sub super {
my ($self, $method) = @_;
return $self->superClass->can($method);
my ($self, $method, $context) = @_;
return $self->superClass($context)->can($method);
}

#
Expand All @@ -384,7 +391,7 @@ sub superClass {
my $self = shift;
my $class = ref($self) || $self;
my $name = $self->extensionContext;
my $data = $self->context->{$name};
my $data = (shift || $self->context)->{$name};
my $op = $self->{bop} || $self->{uop};
return $op ? $data->{$op} : $data->{ substr($class, length($name) + 2) };
}
Expand All @@ -394,15 +401,15 @@ sub superClass {
# if there is one, or the object's super class if not.
#
sub mutate {
my ($self, $other) = @_;
my ($self, $context, $other) = @_;
if ($other) {
delete $self->{$_} for (keys %$self);
$self->{$_} = $other->{$_} for (keys %$other);
bless $self, ref($other);
} elsif (ref($self) eq '') {
$self = $self->superClass;
$self = $self->superClass($context);
} else {
bless $self, $self->superClass;
bless $self, $self->superClass($context);
}
return $self;
}
Expand All @@ -411,8 +418,9 @@ sub mutate {
# Use the super-class new() method
#
sub new {
my $self = shift;
return &{ $self->super("new") }($self, @_);
my $self = shift;
my $context = Value::isContext($_[0]) ? $_[0] : $self->context;
return &{ $self->super("new", $context) }($self, @_);
}

#
Expand All @@ -426,13 +434,19 @@ sub class {
}

#
# This method must be supplied by subclassing
# This method assumes the extension is in a class named
# "context::<name>" where <name> is replaced by the name of the
# context. E.g., context::Quaternions in our example.
#
# That assumption can be changed by subclassing
# context::Extensions::Super package and overriding this method with
# one that returns the extension context's name.
# one that returns the extension context's name. It is more efficient
# to do that, anyway, but you can get away without it.
#
sub extensionContext {
warn Value::traceback(1);
die "The context must subclass context::Extensions::Super and supply an extensionContext() method";
my $self = shift;
my $class = join('::', (split(/::/, ref($self) || $self))[ 0, 1 ]);
return $class;
}

#################################################################################################
Expand Down
Loading