My project involves the translation of Python 2.7 code to Dart code. In order to fully emulate all the features of Python data types I have created wrapper classes in Dart which extend the functionality of the primitive Dart data types to match the corresponding Python type. There are wrappers for all types such as $PyNum for numbers, $PyString for strings and so on. All is fine and the translated code works fine. For code is like:
def fib(n):
if n <= 2:
return 1
else:
return fib (n - 1) + fib (n - 2)
print (fib(36))
The corresponding generated Dart code is:
import 'lib/inbuilts.dart';
import 'dart:io';
fib(n) {
if (n <= new $PyNum(2)) {
return new $PyNum(1);
} else {
return (fib((n - new $PyNum(1))) + fib((n - new $PyNum(2))));
}
}
main() {
stdout.writeln(fib(new $PyNum(36)));
}
The code works fine but in codes like this where there is extreme recursions, the excessive number of wrapper objects created at each function instance is taking a severe toll on the running time of the code. For example the unwrapped Dart code:
import'dart:io';
fib(n) {
if (n <= 2) {
return 1;
} else {
return (fib((n - 1)) + fib((n - 2)));
}
}
main() {
stdout.writeln(fib(36));
}
This runs almost 15x faster than the wrapped code for obvious reasons. All calculations involving wrapped data types return a new instance of that Class. Its absolutely critical for me to emulate all features that Python provides in its data types via Dart and wrapping is the only thing that comes to my mind at the moment. I tried using singleton classes to make a common object for calculations but fails in recursive and threaded situations.
My $PyNum wrapper class is like this:
class $PyNum {
num _value;
$PyNum(value) {
switch ($getType(value)) {
case 6:
_value = value;
break;
case 7:
try {
_value = num.parse(value);
} catch (ex) {
print("Invalid string literal for num parsing");
exit(1);
}
break;
case 5:
_value = value.value();
break;
default:
throw "Invalid input for num conversion";
}
}
value() => _value;
toString() => _value.toString();
operator +(other) => new $PyNum(_value + other.value());
operator -(other) => new $PyNum(_value - other.value());
operator *(other) => new $PyNum(_value * other.value());
operator ~/(other) => new $PyNum(_value ~/ other.value());
operator |(other) => new $PyNum(_value | other.value());
operator &(other) => new $PyNum(_value & other.value());
operator ^(other) => new $PyNum(_value ^ other.value());
operator %(other) => new $PyNum(_value % other.value());
operator <<(other) => new $PyNum(_value << other.value());
operator >>(other) => new $PyNum(_value >> other.value());
operator ==(other) {
switch ($getType(other)) {
case 6:
return _value == other;
case 5:
return _value == other.value();
default:
return false;
}
}
operator <(other) {
switch ($getType(other)) {
case 6:
return _value < other;
case 5:
return _value < other.value();
default:
return true;
}
}
operator >(other) => !(this < other) && (this != other);
operator <=(other) => (this < other) || (this == other);
operator >=(other) => (this > other) || (this == other);
}
$getType(variable) {
if (variable is bool)
return 0;
else if (variable is $PyBool)
return 1;
else if (variable is $PyDict)
return 2;
else if (variable is $PyList)
return 3;
else if (variable is List)
return 4;
else if (variable is $PyNum)
return 5;
else if (variable is num)
return 6;
else if (variable is $PyString)
return 7;
else if (variable is $PyTuple)
return 8;
else
return -1;
}
can const objects be made out off this class? I am not very sure how to do it exactly.
Is there any other way to efficiently do this and still be able to emulate all of Python's features? Any help is much appreciated!