Skip to content

Commit

Permalink
- Added more trigonometric functions inside the Number class.
Browse files Browse the repository at this point in the history
- Added checks for some trigonometric functions to return complex numbers for certain values.
- Added support for a new syntax to change or add a given variable inside a class.

Example:
	local Num!PREC = 42;	# changes the precision for numbers
	say sqrt(2);		# calculates the square root of 2 using only 42 bits

The feature works for user-defined classes as well.

- Changed the behavior of the Complex comparison operators, such as >, <, >=, <=.

All of them will check the absolute values, which means that:

	Complex(1, 2) <= Complex(3, 4)

is equivalent with:

	Complex(1, 2).abs <= Complex(3, 4).abs

- Fixed the deparsing of static variables declared with an empty expression.

Example:
	static x = ();		# works now, by assigning nil to x

This is true for constants as well.

- Updated the Optimizer to cover a few more methods.
- Improved the +/- Infinity types.
- Added the Number.commify method.
  • Loading branch information
trizen committed Dec 30, 2015
1 parent 734392a commit b6ed0b9
Show file tree
Hide file tree
Showing 8 changed files with 591 additions and 215 deletions.
29 changes: 18 additions & 11 deletions lib/Sidef/Deparse/Perl.pm
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,19 @@ HEADER
}
}

sub _dump_reftype {
sub _get_reftype {
my ($self, $obj) = @_;

my $ref = ref($obj);
$self->_dump_string(
$ref eq 'Sidef::Variable::ClassInit' ? $self->_dump_class_name($obj)
: $ref eq 'Sidef::Variable::Ref' ? 'REF'
: $ref eq 'Sidef::Types::Block::BlockInit' ? 'Sidef::Types::Block::Block'
: $ref
);
$ref eq 'Sidef::Variable::ClassInit' ? $self->_dump_class_name($obj)
: $ref eq 'Sidef::Variable::Ref' ? 'REF'
: $ref eq 'Sidef::Types::Block::BlockInit' ? 'Sidef::Types::Block::Block'
: $ref;
}

sub _dump_reftype {
my ($self, $obj) = @_;
$self->_dump_string($self->_get_reftype($obj));
}

sub _dump_string {
Expand Down Expand Up @@ -594,7 +597,10 @@ HEADER
$code = 'local ' . $self->deparse_script($obj->{expr});
}
elsif ($ref eq 'Sidef::Variable::Global') {
$code = '$' . $obj->{class} . '::' . $obj->{name},;
$code = '$' . $obj->{class} . '::' . $obj->{name};
}
elsif ($ref eq 'Sidef::Variable::ClassVar') {
$code = '$' . $self->_get_reftype($obj->{class}) . '::' . $obj->{name};
}
elsif ($ref eq 'Sidef::Variable::Define') {
my $name = $obj->{name} . $refaddr;
Expand All @@ -615,13 +621,13 @@ HEADER
if (exists $self->{function} or exists $self->{class}) {
$self->top_add("use experimental 'lexical_subs';\n");
$code = "state sub $name() { state \$_$refaddr"
. (defined($obj->{expr}) ? (" = " . $self->deparse_script($obj->{expr})) : '') . " }";
. (defined($obj->{expr}) ? (" = do{" . $self->deparse_script($obj->{expr}) . '}') : '') . " }";
}

# Otherwise, use static constants
else {
$code = "sub $name() { state \$_$refaddr"
. (defined($obj->{expr}) ? " = " . ($self->deparse_script($obj->{expr})) : '') . "}";
. (defined($obj->{expr}) ? " = do{" . ($self->deparse_script($obj->{expr}) . '}') : '') . "}";
}
}
else {
Expand All @@ -633,7 +639,8 @@ HEADER
my $value = "\$$name";
if (not exists $obj->{inited}) {
$obj->{inited} = 1;
$code = "(state \$$name" . (defined($obj->{expr}) ? (" = " . $self->deparse_script($obj->{expr})) : '') . ")";
$code = "(state \$$name"
. (defined($obj->{expr}) ? (' = do{' . $self->deparse_script($obj->{expr}) . '}') : '') . ")";
}
else {
$code = $value;
Expand Down
23 changes: 19 additions & 4 deletions lib/Sidef/Deparse/Sidef.pm
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ package Sidef::Deparse::Sidef {
elsif ($ref eq 'Sidef::Variable::Global') {
$code = 'global ' . $obj->{class} . '::' . $obj->{name},;
}
elsif ($ref eq 'Sidef::Variable::ClassVar') {
$code = $self->_dump_reftype($obj->{class}) . '!' . $obj->{name};
}
elsif ($ref eq 'Sidef::Variable::Init') {
$code = $self->_dump_init_vars($obj, 'var');
}
Expand All @@ -218,7 +221,10 @@ package Sidef::Deparse::Sidef {
my $name = $obj->{name};
if (not exists $obj->{inited}) {
$obj->{inited} = 1;
$code = "define $name = (" . $self->deparse_script($obj->{expr}) . ')';
$code = "define $name";
if (defined $obj->{expr}) {
$code .= ' = (' . $self->deparse_script($obj->{expr}) . ')';
}
}
else {
$code = $name;
Expand All @@ -228,7 +234,10 @@ package Sidef::Deparse::Sidef {
my $name = $obj->{name};
if (not exists $obj->{inited}) {
$obj->{inited} = 1;
$code = "const $name = (" . $self->deparse_script($obj->{expr}) . ')';
$code = "const $name";
if (defined $obj->{expr}) {
$code .= ' = (' . $self->deparse_script($obj->{expr}) . ')';
}
}
else {
$code = $name;
Expand All @@ -238,7 +247,10 @@ package Sidef::Deparse::Sidef {
my $name = $obj->{name};
if (not exists $obj->{inited}) {
$obj->{inited} = 1;
$code = "static $name = (" . $self->deparse_script($obj->{expr}) . ')';
$code = "static $name";
if (defined $obj->{expr}) {
$code .= ' = (' . $self->deparse_script($obj->{expr}) . ')';
}
}
else {
$code = $name;
Expand Down Expand Up @@ -471,7 +483,10 @@ package Sidef::Deparse::Sidef {
$code = 'Sig';
}
elsif ($ref eq 'Sidef::Types::Number::Number') {
$code = $self->_dump_number($obj->get_value);
$code = $self->_dump_number($obj->_get_frac);
if (index($code, '/') != -1) {
$code = qq{Number("$code")};
}
}
elsif ($ref eq 'Sidef::Types::Number::Inf') {
$code = 'Inf';
Expand Down
154 changes: 71 additions & 83 deletions lib/Sidef/Optimizer.pm
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ package Sidef::Optimizer {
exists($INC{$module}) || require($module);
map {

# defined(&{$package . '::' . $_})
# or warn "Invalid method $package: $_";
defined(&{$package . '::' . $_})
or die "Invalid method $package: $_";

\&{$package . '::' . $_}
} @names;
Expand Down Expand Up @@ -195,26 +195,32 @@ package Sidef::Optimizer {

(NUMBER) => [

# Number.method(Number)
# Number.method(String | Number)
(
map {
{ $_, [table(NUMBER)] }
{ $_, [table(STRING, NUMBER)] }
} methods(NUMBER, qw(
new call
)
)
),

+ - / * % **
# Number.method(Number)
(
map {
{ $_, [table(NUMBER)] }
} methods(NUMBER, qw(
+ - / * % %% **
lt gt le ge cmp acmp
eq ne
and or xor
digit
complex
root log
npow
next_pow
max min
round roundf
digit
roundf
nok
modinv
rdiv
Expand All @@ -226,6 +232,16 @@ package Sidef::Optimizer {
)
),

# Number.method(String, Number)
(
map {
{ $_, [table(STRING), table(NUMBER)] }
} methods(NUMBER, qw(
new call
)
)
),

# Number.method()
(
map {
Expand All @@ -236,20 +252,60 @@ package Sidef::Optimizer {
factorial
sqrt
npow2
troot
next_pow2
abs
hex oct bin
exp int
cos sin
log ln log10 log2
sin
asin
sinh
asinh
cos
acos
cosh
acosh
tan
atan
tanh
atanh
cot
acot
coth
acoth
sec
sech
asec
asech
csc
csch
acsc
acsch
cot
acot
coth
acoth
inf
neg
sign
nan
chr
pi
ln2
phi
tau
e
Y
G
is_zero
is_one
Expand All @@ -259,6 +315,7 @@ package Sidef::Optimizer {
is_even
is_odd
is_inf
is_ninf
is_int
ceil
Expand All @@ -273,11 +330,11 @@ package Sidef::Optimizer {
as_bin
as_oct
as_hex
as_rat
rat
complex i
sstr
dump
commify
)
Expand Down Expand Up @@ -416,67 +473,6 @@ package Sidef::Optimizer {

(MATH) => [

# Math.method(Number)
(
map {
{ $_, [table(NUMBER)] }
} methods(MATH, qw(
sqrt
root
pow
exp
e
pi
atan
atan2
cos
sin
asin
log
log2
log10
npow2
abs
ceil
floor
)
)
),

# Math.method(Number, Number)
(
map {
{ $_, [table(NUMBER), table(NUMBER)] }
} methods(MATH, qw(
exp
atan
atan2
cos
sin
asin
log
npow
)
)
),

# Math.method()
(
map {
{ $_, [] }
} methods(MATH, qw(
e
pi
inf
)
)
),

# Math.method(String)
(
map {
Expand Down Expand Up @@ -591,31 +587,23 @@ package Sidef::Optimizer {
acoth
pi
int
neg
not
sign
real
imaginary
is_zero
is_one
is_nan
is_pos
is_neg
is_even
is_odd
is_real
is_inf
is_int
ceil
floor
sstr
dump
factorial
)
)
),
Expand Down
9 changes: 8 additions & 1 deletion lib/Sidef/Parser.pm
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ package Sidef::Parser {
| <<(?<reduce>[_\pL][_\pL\pN]*|(?&ops))>> # reduce operator (e.g.: <<add>> or <<+>>)
| «(?<reduce>[_\pL][_\pL\pN]*|(?&ops))» # reduce operator (e.g.: «add» or «+»)
| \h*\^(?<op>[_\pL][_\pL\pN]*[!:?]?)\^\h* # method-like operator (e.g.: ^add^)
| \^(?<op>[_\pL][_\pL\pN]*[!:?]?)\^ # method-like operator (e.g.: ^add^)
| (?<op>(?&ops)) # primitive operator (e.g.: +, -, *, /)
}x;
},
Expand Down Expand Up @@ -1877,6 +1877,13 @@ package Sidef::Parser {
return Sidef::Types::Regex::Regex->new($string, /\G($self->{match_flags_re})/goc ? $1 : undef);
}

# Class variable in form of `Class!var_name`
if (/\G($self->{var_name_re})!($self->{var_name_re})/goc) {
my ($class_name, $var_name) = ($1, $2);
my $class_obj = $self->parse_expr(code => \$class_name);
return (bless {class => $class_obj, name => $var_name}, 'Sidef::Variable::ClassVar');
}

# Static object (like String or nil)
if (/$self->{static_obj_re}/goc) {
return $^R;
Expand Down
Loading

0 comments on commit b6ed0b9

Please sign in to comment.