| 164 | 1 package IMPL::lang; | 
|  | 2 use strict; | 
|  | 3 use warnings; | 
|  | 4 | 
| 165 | 5 use parent qw(Exporter); | 
| 164 | 6 use IMPL::_core::version; | 
| 173 | 7 use IMPL::clone qw(clone); | 
| 164 | 8 | 
| 167 | 9 require IMPL::Class::PropertyInfo; | 
| 164 | 10 | 
| 167 | 11 our @EXPORT      = qw(&is); | 
|  | 12 our %EXPORT_TAGS = ( | 
|  | 13 	base => [ | 
|  | 14 		qw( | 
|  | 15 		  &is | 
| 173 | 16 		  &clone | 
| 167 | 17 		  ) | 
|  | 18 	], | 
|  | 19 	constants => [ | 
|  | 20 		qw( | 
|  | 21 		  &ACCESS_PUBLIC | 
|  | 22 		  &ACCESS_PROTECTED | 
|  | 23 		  &ACCESS_PRIVATE | 
|  | 24 		  &PROP_GET | 
|  | 25 		  &PROP_SET | 
|  | 26 		  &PROP_OWNERSET | 
|  | 27 		  &PROP_LIST | 
|  | 28 		  &PROP_ALL | 
|  | 29 		  ) | 
|  | 30 	], | 
|  | 31 | 
|  | 32 	declare => [ | 
|  | 33 		qw( | 
|  | 34 		  &public | 
|  | 35 		  &protected | 
|  | 36 		  &private | 
|  | 37 		  &virtual | 
|  | 38 		  &property | 
|  | 39 		  &static | 
|  | 40 		  &property | 
|  | 41 		  ) | 
|  | 42 	], | 
|  | 43 	compare => [ | 
|  | 44 		qw( | 
|  | 45 		  &equals | 
|  | 46 		  &equals_s | 
| 168 | 47 		  &hashCompare | 
|  | 48 		  ) | 
|  | 49 	], | 
|  | 50 	hash => [ | 
|  | 51 		qw( | 
|  | 52 		  &hashApply | 
|  | 53 		  &hashMerge | 
|  | 54 		  &hashDiff | 
|  | 55 		  &hashCompare | 
| 176 | 56 		  &hashParse | 
| 167 | 57 		  ) | 
|  | 58 	] | 
|  | 59 ); | 
|  | 60 | 
|  | 61 our @EXPORT_OK = keys %{ { map (($_,1) , map (@{$_}, values %EXPORT_TAGS) ) } }; | 
|  | 62 | 
|  | 63 use constant { | 
|  | 64 	ACCESS_PUBLIC    => 1, | 
|  | 65 	ACCESS_PROTECTED => 2, | 
|  | 66 	ACCESS_PRIVATE   => 3, | 
|  | 67 	PROP_GET         => 1, | 
|  | 68 	PROP_SET         => 2, | 
|  | 69 	PROP_OWNERSET    => 10, | 
|  | 70 	PROP_LIST        => 4, | 
|  | 71 	PROP_ALL         => 3 | 
|  | 72 }; | 
| 164 | 73 | 
|  | 74 sub is($$) { | 
| 167 | 75 	eval { $_[0]->isa( $_[1] ) }; | 
|  | 76 } | 
|  | 77 | 
|  | 78 sub virtual($) { | 
|  | 79 	$_[0]->Virtual(1); | 
|  | 80 	$_[0]; | 
|  | 81 } | 
|  | 82 | 
|  | 83 sub public($) { | 
|  | 84 	$_[0]->Access(ACCESS_PUBLIC); | 
|  | 85 	$_[0]->Implement; | 
|  | 86 	$_[0]; | 
|  | 87 } | 
|  | 88 | 
|  | 89 sub private($) { | 
|  | 90 	$_[0]->Access(ACCESS_PRIVATE); | 
|  | 91 	$_[0]->Implement; | 
|  | 92 	$_[0]; | 
|  | 93 } | 
|  | 94 | 
|  | 95 sub protected($) { | 
|  | 96 	$_[0]->Access(ACCESS_PROTECTED); | 
|  | 97 	$_[0]->Implement; | 
|  | 98 	$_[0]; | 
| 164 | 99 } | 
|  | 100 | 
| 167 | 101 sub property($$;$) { | 
|  | 102 	my ( $propName, $mutators, $attributes ) = @_; | 
|  | 103 	my $Info = new IMPL::Class::PropertyInfo( | 
|  | 104 		{ | 
|  | 105 			Name       => $propName, | 
|  | 106 			Mutators   => $mutators, | 
|  | 107 			Class      => scalar(caller), | 
|  | 108 			Attributes => $attributes | 
|  | 109 		} | 
|  | 110 	); | 
|  | 111 	return $Info; | 
|  | 112 } | 
|  | 113 | 
|  | 114 sub static($$) { | 
|  | 115 	my ( $name, $value ) = @_; | 
|  | 116 	my $class = caller; | 
|  | 117 	$class->static_accessor( $name, $value ); | 
|  | 118 } | 
|  | 119 | 
|  | 120 sub equals { | 
|  | 121 	if (defined $_[0]) { | 
|  | 122 		return 0 if (not defined $_[1]); | 
|  | 123 | 
|  | 124 		return $_[0] == $_[1]; | 
|  | 125 	}  else { | 
|  | 126 		return 0 if defined $_[1]; | 
|  | 127 | 
|  | 128 		return 1; | 
|  | 129 	} | 
|  | 130 } | 
|  | 131 | 
|  | 132 sub equals_s { | 
|  | 133 	if (defined $_[0]) { | 
|  | 134 		return 0 if (not defined $_[1]); | 
|  | 135 | 
|  | 136 		return $_[0] eq $_[1]; | 
|  | 137 	}  else { | 
|  | 138 		return 0 if defined $_[1]; | 
|  | 139 | 
|  | 140 		return 1; | 
|  | 141 	} | 
|  | 142 } | 
|  | 143 | 
| 168 | 144 sub hashDiff { | 
|  | 145 	my ($src,$dst) = @_; | 
|  | 146 | 
| 169 | 147 	$dst = $dst ? { %$dst } : {} ; | 
|  | 148 	$src ||= {}; | 
| 168 | 149 | 
|  | 150 	my %result; | 
|  | 151 | 
|  | 152 	foreach my $key ( keys %$src ) { | 
|  | 153 		if (exists $dst->{$key}) { | 
|  | 154 			$result{"+$key"} = $dst->{$key} unless equals_s($dst->{$key}, $src->{$key}); | 
|  | 155 			delete $dst->{$key}; | 
|  | 156 		} else { | 
|  | 157 			$result{"-$key"} = 1; | 
|  | 158 		} | 
|  | 159 	} | 
|  | 160 | 
|  | 161 	$result{"+$_"} = $dst->{$_} foreach keys %$dst; | 
|  | 162 | 
|  | 163 	return \%result; | 
|  | 164 } | 
|  | 165 | 
|  | 166 sub hashMerge { | 
|  | 167 	return hashApply( { %{$_[0]} }, $_[1] ); | 
|  | 168 } | 
|  | 169 | 
|  | 170 sub hashApply { | 
|  | 171 	my ($target,$diff) = @_; | 
|  | 172 | 
|  | 173 	while ( my ($key,$value) = each %$diff) { | 
|  | 174 		$key =~ /^(\+|-)?(.*)$/; | 
|  | 175 		my $op = $1 || '+'; | 
|  | 176 		$key = $2; | 
|  | 177 | 
|  | 178 		if ($op eq '-') { | 
|  | 179 			delete $target->{$key}; | 
|  | 180 		} else { | 
|  | 181 			$target->{$key} = $value; | 
|  | 182 		} | 
|  | 183 	} | 
|  | 184 | 
|  | 185 	return $target; | 
|  | 186 } | 
|  | 187 | 
|  | 188 sub hashCompare { | 
|  | 189 	my ($l,$r,$cmp) = @_; | 
|  | 190 | 
|  | 191 	$cmp ||= \&equals_s; | 
|  | 192 | 
|  | 193 	return 0 unless scalar keys %$l == scalar keys %$r; | 
|  | 194 	&$cmp($l->{$_},$r->{$_}) || return 0 foreach keys %$l; | 
|  | 195 | 
|  | 196 	return 1; | 
|  | 197 } | 
|  | 198 | 
| 174 | 199 sub hashParse { | 
|  | 200 	my ($s,$p,$d) = @_; | 
|  | 201 | 
|  | 202 	$p = $p ? qr/$p/ : qr/\n+/; | 
|  | 203 	$d = $d ? qr/$d/ : qr/\s*=\s*/; | 
|  | 204 | 
|  | 205 	return { | 
|  | 206 		map split($d,$_,2), split($p,$s) | 
|  | 207 	}; | 
|  | 208 } | 
|  | 209 | 
|  | 210 sub hashSave { | 
|  | 211 | 
|  | 212 } | 
|  | 213 | 
| 167 | 214 1; |