#!/usr/bin/perl

package Graph;
use Lib;

use strict;
use warnings;

our $graph;

my %double_modes = (
	'oi' => sub { $_[0] = $_[1] * 2; 1 },
	'io' => sub { $_[1] = $_[0] / 2; 1 },
);
sub double {
	relation(\@_, \%double_modes);
}

sub relation {
	my ($args, $modes) = @_;
	$graph->add($args, $modes);
}

sub quad {
	my ($quad, $once) = \(@_);
	my ($twice);
	double($twice, $$once);
	double($$quad, $twice);
}

sub several {
	my ($op) = @_;
	my $i = 0;
	my @list;
	sub {
		++$i;
		if ($i == 1) {
			@list = $op->(@_);
		}
		my $n = @list;
		if ($n) {
			@_[0..$#_] = @{shift @list};
		}
		return $n;
	}
}

my %square_modes = (
	'oi' => sub { $_[0] = $_[1] * $_[1]; 1 },
	'io' => several sub {
				my ($square, $root) = @_;
				if ($square > 0) {
					$root = sqrt($square);
					([$square, $root], [$square, -$root]);
				} elsif ($square == 0) {
					([0, 0])
				} else {
					()
				}
			},
);
sub square {
	relation(\@_, \%square_modes);
}


sub graph (&) {
	my ($rels) = @_;
	local $graph = Graph->new;
	$rels->();
	return $graph;
}

sub calc {
}

sub new {
	my ($class) = @_;
	my $self = {};
	bless $self, $class;
	return $self;
}

sub add {
}


sub test {
	my ($a, $b, $c);
	my $g = graph {
		quad($b, $a);
		square($b, $c);
	};
	$a = 3;
	$g->to($a, $b, $c);
	while ($g->calc) {
		print "$a $b\n";
	}
}


__END__

sub add {
	my ($sum, $a, $b) = \(@_);
	# return a function which will produce all solutions 1 by 1
	return sub {
	}
}



		{
			'io' => sub {
			},
}
	return sub {
		if (!defined $$twice && defined $$once) {
			$$twice = 2 * $$once;
		} elsif (defined $$twice && !defined $$once) {
			$$once = $$twice / 2;
		}
	}
}


sub mul {
	my ($prod, $a, $b) = \(@_);
}

sub square {
	my ($square, $root) = \(@_);
}




sub hypot {
	my ($a, $b, $c) = \(@_);
	my ($aa, $bb, $cc);
	square($aa, $a);
	square($bb, $b);
	square($cc, $c);
	add($cc, $aa, $bb);
}



