Anarres-Mud-Driver

 view release on metacpan or  search on metacpan

lib/Driver/Compiler/Generate.pm  view on Meta::CPAN

					# eval the args once outside scope of $__* vars
					# XXX Use the XSUB in Core
	StrRangeCstLL	=> 'substr(A, B, (C) - (B))',
	StrRangeCstLR	=> 'substr(A, B, (B) - (C))',
	StrRangeCstRL	=> 'substr(A, -(B), (C) - (B))',
	StrRangeCstRR	=> 'substr(A, -(B), (B) - (C))',

	StrRangeVarLL	=> 'do { my ($__a, $__b, $__c) = ((A), (B), (C)); '.
					'substr($__a, $__b, ($__c - $__b)) }',
	StrRangeVarLR	=> 'do { my ($__a, $__b, $__c) = ((A), (B), (C)); '.
					'substr($__a, $__b, ($__b - $__c)) }',
	StrRangeVarRL	=> 'do { my ($__a, $__b, $__c) = ((A), (B), (C)); '.
					'substr($__a, - $__b, ($__c - $__b)) }',
	StrRangeVarRR	=> 'do { my ($__a, $__b, $__c) = ((A), (B), (C)); '.
					'substr($__a, - $__b, ($__b - $__c)) }',

	ArrAdd			=> '[ @{A}, @{B} ]',
	ArrSub			=> 'do { my %__a = map { $_ => 1 } @{B}; ' .
					'[ grep { ! $__a{$_} } @{ A } ] }',

	MapAdd			=> '{ %{A}, %{B} }',

	Assign			=> 'A = B',
	Catch			=> 'do { eval { A; }, $@; }',

	StmtReturn		=> 'return A;',
	StmtContinue	=> 'next;',

	# We can add extra braces around statement|block tokens
	# This lot are all strictly cheating anyway! If this works ...
	StmtExp			=> 'A;',
	# Should we promote_to_block() B in these statements?
	# Bear in mind what happens if we do an empty block...?
	StmtDo			=> 'do { B } while (A);',
	StmtWhile		=> 'while (A) { B }',
	StmtFor			=> 'for (A; B; C) D',
	StmtForeachArr	=> 'foreach my A (@{ C }) D',
	StmtForeachMap	=> 'foreach my A (keys %{ C }) D',	# XXX FIXME: B
	StmtTry			=> 'eval A; if ($@) { my B = $@; C; }',
												# This uses blocks
	StmtCatch		=> 'eval A ;',				# A MudOS hack

	# This NOGEN business is really developer support and can be removed
	map { $_ => 'NOGEN' } qw(
							Variable
							Index Range
							Lsh Rsh
							Add Sub Mul Div Mod
							Eq Ne Lt Gt Le Ge Or
							And Xor
							
							AddEq SubEq DivEq MulEq ModEq
							AndEq OrEq XorEq
							LshEq RshEq

							StmtForeach
							),
		);

# XXX For the purposes of things like Member, I need to be able to
# insert both expanded and nonexpanded versions of tokens.
# So I need to be able to insert "A", _A_ and @A@ tokens, for example.

sub gensub {
	my ($self, $name, $code) = @_;

	confess "No code template for opcode '$name'" unless defined $code;

	foreach ('A'..'F') {	# Say ...
		my $arg = ord($_) - ord('A');
		# XXX This 'quote' routine doesn't necessarily quote
		# appropriately.
		$code =~ s/"$_"/' . quote(\$self->value($arg)) . '/g;
		$code =~ s/\b_$_\_\b/' . \$self->value($arg) . '/g;
		$code =~ s/\b$_\b/' . \$self->value($arg)->generate(\@_) . '/g;
	}

	$code = qq{ sub (\$) { my \$self = shift; return '$code'; } };
	# Remove empty concatenations - careful with the templates
	$code =~ s/'' \. //g;
	$code =~ s/ \. ''//g;

	# print "$name becomes $code\n";
	my $subref = eval $code;
	die $@ if $@;
	return $subref;
}

# "Refactor", I hear you say?
# This needs a magic token for line number...
sub generate ($) {
	my $self = shift;

	my $name = $self->opcode;
	# print "Finding code for $name\n";
	my $code = $OPCODETABLE{$name};
	return "GEN($name)" unless defined $code;

	# This is mostly for debugging. It can be safely removed.
	if ($code eq 'NOGEN') {
		print "XXX Attempt to generate NOGEN opcode $name\n";
		return "GEN($name)";
	}

	my $subref = $self->gensub($name, $code);

	{
		# Backpatch our original package.
		no strict qw(refs);
		*{ ref($self) . '::generate' } = $subref;
	}

	return $subref->($self, @_);
}

{
	package Anarres::Mud::Driver::Compiler::Node::String;
	use String::Escape qw(quote printable);
	sub generate {
		my $str = printable($_[0]->value(0));
		$str =~ s/([\$\@\%])/\\$1/g;



( run in 0.639 second using v1.01-cache-2.11-cpan-97f6503c9c8 )