Mercurial > repo
diff interps/clc-intercal/CLC-INTERCAL-Base-1.-94.-2/INTERCAL/DataItem.pm @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/interps/clc-intercal/CLC-INTERCAL-Base-1.-94.-2/INTERCAL/DataItem.pm Sun Dec 09 19:30:08 2012 +0000 @@ -0,0 +1,185 @@ +package Language::INTERCAL::DataItem; + +# Base class for all data items (Arrays, Numbers, Whirlpool) + +# This file is part of CLC-INTERCAL + +# Copyright (c) 2006-2008 Claudio Calvelli, all rights reserved. + +# CLC-INTERCAL is copyrighted software. However, permission to use, modify, +# and distribute it is granted provided that the conditions set out in the +# licence agreement are met. See files README and COPYING in the distribution. + +use strict; +use vars qw($VERSION $PERVERSION); +($VERSION) = ($PERVERSION = "CLC-INTERCAL/Base INTERCAL/DataItem.pm 1.-94.-2") =~ /\s(\S+)$/; + +use Carp; +use Language::INTERCAL::Exporter '1.-94.-2'; +use Language::INTERCAL::Splats '1.-94.-2', qw(:SP); +use vars qw(@EXPORT); +@EXPORT = qw(_make_subscripts); + +# note: _make_subscripts is exported, not accessed by inheriting it, +# because we sometimes want to call it without an object + +sub _make_subscripts { + my ($di, $subscripts, $zero_ok) = @_; + return () if ! defined $subscripts; + if (ref $subscripts) { + if (UNIVERSAL::isa($subscripts, 'Language::INTERCAL::Arrays')) { + $subscripts = [ $subscripts->as_list() ]; + } elsif (UNIVERSAL::isa($subscripts, 'Language::INTERCAL::Numbers')) { + $subscripts = [ $subscripts->number() ]; + } elsif (ref $subscripts ne 'ARRAY') { + faint(SP_ARRAY, "Subscripts aren't numbers"); + } + } else { + $subscripts = [$subscripts]; + } + my @subscripts = (); + $zero_ok ||= $di->{zero_ok} if $di; + my $min = $zero_ok ? 0 : 1; + for my $s (@$subscripts) { + if (ref $s) { + UNIVERSAL::isa($s, 'Language::INTERCAL::Numbers') + or faint(SP_ARRAY, "Subscript is not a number"); + $s = $s->number; + $s < $min || $s > 0xffff + and faint(SP_ARRAY, "Subscript out of range"); + push @subscripts, $s; + } else { + $s =~ /^\d+$/ + or faint(SP_ARRAY, "Subscript is not a number"); + $s < $min || $s > 0xffff + and faint(SP_ARRAY, "Subscript out of range"); + push @subscripts, $s; + } + } + if ($di) { + if (! exists $di->{subscripts}) { + faint(SP_NOARRAY) if @subscripts; + return (); + } + faint(SP_NODIM) unless @{$di->{subscripts}}; + @subscripts == @{$di->{subscripts}} + or faint(SP_SUBSIZE, scalar @subscripts, + scalar @{$di->{subscripts}}); + for (my $i = 0; $i < @subscripts; $i++) { + $subscripts[$i] >= $min + or faint(SP_SUBSCRIPT, $subscripts[$i], 'too small'); + $subscripts[$i] <= $di->{subscripts}[$i] + or faint(SP_SUBSCRIPT, $subscripts[$i], + "is greater than $di->{subscripts}[$i]"); + } + } + @subscripts; +} + +sub use { + if (@_ == 2) { + my ($di, $subs) = @_; + if ($di->{overload} && ! $di->{in_overload}) { + $di->{in_overload} = 1; + my $r = &{$di->{overload}}($subs); + delete $di->{in_overload}; + return $r; + } + my @s = _make_subscripts($di, $subs); + return $di if ! @s; + return $di->_get(\@s); + } + if (@_ == 3) { + my ($di, $subs, $value) = @_; + if ($di->{overload} && ! $di->{in_overload}) { + $di->{in_overload} = 1; + my $r = &{$di->{overload}}($subs, $value); + delete $di->{in_overload}; + return $r; + } + my @s = _make_subscripts($di, $subs); + return $di->_assign($value) if ! @s; + return $di->_store(\@s, $value); + } + croak "Usage: DATA_ITEM->use(SUBSCRIPTS [, VALUE])"; +} + +sub assign { + @_ == 2 or croak "Usage: DATA_ITEM->assign(VALUE)"; + my ($di, $value) = @_; + if ($di->{overload} && ! $di->{in_overload}) { + $di->{in_overload} = 1; + my $r = &{$di->{overload}}([], $value); + delete $di->{in_overload}; + return $r; + } + return $di->_assign($value); +} + +sub value { + @_ == 1 or croak "Usage: DATA_ITEM->value"; + my ($di) = @_; + if ($di->{overload} && ! $di->{in_overload}) { + $di->{in_overload} = 1; + my $r = &{$di->{overload}}([]); + delete $di->{in_overload}; + return $r; + } + return $di; +} + +sub store { + @_ == 3 or croak "Usage: DATA_ITEM->store(SUBSCRIPTS, VALUE)"; + my ($di, $subs, $value) = @_; + if ($di->{overload} && ! $di->{in_overload}) { + $di->{in_overload} = 1; + my $r = &{$di->{overload}}($subs, $value); + delete $di->{in_overload}; + return $r; + } + return $di->_store($subs, $value); +} + +sub get { + @_ == 2 or croak "Usage: DATA_ITEM->get(SUBSCRIPTS)"; + my ($di, $subs) = @_; + if ($di->{overload} && ! $di->{in_overload}) { + $di->{in_overload} = 1; + my $r = &{$di->{overload}}($subs); + delete $di->{in_overload}; + return $r; + } + return $di->_get($subs); +} + +sub overload { + @_ == 2 || @_ == 3 + or croak "Usage: DATAITEM->overload(SUBSCRIPTS [,CODE])"; + my ($di, $subs, $code) = @_; + defined $code && ref $code ne 'CODE' + and croak "CODE is not a code reference"; + if ($subs && @$subs) { + $di->get($subs)->overload(undef, $code); + } else { + $di->{overload} = $code; + } + $di; +} + +sub get_overload { + @_ == 2 or croak "Usage: DATAITEM->get_overload(SUBSCRIPTS)"; + my ($di, $subs) = @_; + if ($subs && @$subs) { + return $di->get($subs)->get_overload(undef); + } else { + return $di->{overload}; + } +} + +sub bits { + @_ == 1 or croak "Usage: NUMBER->bits"; + my ($num) = @_; + $num->{bits}; +} + +1;