Test for d4rt
This commit is contained in:
parent
80d6c7d0df
commit
ba6c761cee
5 changed files with 150 additions and 60 deletions
|
|
@ -5,11 +5,11 @@
|
||||||
"description": '''
|
"description": '''
|
||||||
Calculates vertical displacement under constant gravity
|
Calculates vertical displacement under constant gravity
|
||||||
|
|
||||||
`h = ½gt²`
|
$$h = \\frac{1}{2}gt^2$$
|
||||||
|
|
||||||
Where:
|
Where:
|
||||||
- `g` = Gravitational acceleration (9.81 m/s² on Earth)
|
- $g$: Gravitational acceleration ($9.81\\ \\mathrm{m/s^2}$ on Earth)
|
||||||
- `t` = Time in free fall (seconds)
|
- $t$: Time in free fall (seconds)
|
||||||
|
|
||||||
''',
|
''',
|
||||||
"input": [
|
"input": [
|
||||||
|
|
@ -17,7 +17,7 @@ Where:
|
||||||
{"name": "g", "unit": "meters per second"} // Gravitational acceleration
|
{"name": "g", "unit": "meters per second"} // Gravitational acceleration
|
||||||
],
|
],
|
||||||
"output": {"name": "h", "unit": "meter"}, // Height in meters
|
"output": {"name": "h", "unit": "meter"}, // Height in meters
|
||||||
"d4rtCode": "h = 0.5 * g * Math.pow(t, 2);",
|
"d4rtCode": "h = 0.5 * g * pow(t, 2);",
|
||||||
"tags": ["physics", "kinematics"]
|
"tags": ["physics", "kinematics"]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -27,12 +27,12 @@ Where:
|
||||||
"description": '''
|
"description": '''
|
||||||
Newton's law of universal gravitation
|
Newton's law of universal gravitation
|
||||||
|
|
||||||
`F = G(m₁m₂)/r²`
|
$$F = G\\frac{m_1m_2}{r^2}$$
|
||||||
|
|
||||||
Where:
|
Where:
|
||||||
- `G` = Gravitational constant (6.674×10⁻¹¹ N·m²/kg²)
|
- $G$: Gravitational constant ($6.674\\times 10^{-11}\\ \\mathrm{N\\cdot m^2/kg^2}$)
|
||||||
- `m₁`, `m₂` = Masses of two objects
|
- $m_1, m_2$: Masses of two objects
|
||||||
- `r` = Distance between centers of masses
|
- $r$: Distance between centers of masses
|
||||||
|
|
||||||
''',
|
''',
|
||||||
"input": [
|
"input": [
|
||||||
|
|
@ -41,7 +41,7 @@ Where:
|
||||||
{"name": "r", "unit": "meter"} // Distance between masses
|
{"name": "r", "unit": "meter"} // Distance between masses
|
||||||
],
|
],
|
||||||
"output": {"name": "F", "unit": "newton"}, // Force in newtons
|
"output": {"name": "F", "unit": "newton"}, // Force in newtons
|
||||||
"d4rtCode": "F = (6.67430e-11 * m1 * m2) / Math.pow(r, 2);",
|
"d4rtCode": "F = (6.67430e-11 * m1 * m2) / pow(r, 2);",
|
||||||
"tags": ["physics", "astronomy", "gravity"]
|
"tags": ["physics", "astronomy", "gravity"]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -51,11 +51,11 @@ Where:
|
||||||
"description": '''
|
"description": '''
|
||||||
Energy possessed by a moving object
|
Energy possessed by a moving object
|
||||||
|
|
||||||
`KE = ½mv²`
|
$$KE = \\frac{1}{2}mv^2$$
|
||||||
|
|
||||||
Where:
|
Where:
|
||||||
- `m` = Mass of object
|
- $m$: Mass of object
|
||||||
- `v` = Velocity of object
|
- $v$: Velocity of object
|
||||||
|
|
||||||
''',
|
''',
|
||||||
"input": [
|
"input": [
|
||||||
|
|
@ -63,7 +63,7 @@ Where:
|
||||||
{"name": "v", "unit": "meters per second"} // Velocity
|
{"name": "v", "unit": "meters per second"} // Velocity
|
||||||
],
|
],
|
||||||
"output": {"name": "KE", "unit": "joule"}, // Energy in joules
|
"output": {"name": "KE", "unit": "joule"}, // Energy in joules
|
||||||
"d4rtCode": "KE = 0.5 * m * Math.pow(v, 2);",
|
"d4rtCode": "KE = 0.5 * m * pow(v, 2);",
|
||||||
"tags": ["physics", "energy", "mechanics"]
|
"tags": ["physics", "energy", "mechanics"]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -71,18 +71,21 @@ Where:
|
||||||
{
|
{
|
||||||
"name": "Projectile Range",
|
"name": "Projectile Range",
|
||||||
"description": "Calculates horizontal distance of projectile motion\n\n"
|
"description": "Calculates horizontal distance of projectile motion\n\n"
|
||||||
"`R = (v² sin(2θ))/g`\n\n"
|
"$$R = \\frac{v^2 \\sin(2\\theta)}{g}$$\n\n"
|
||||||
"Where:\n"
|
"Where:\n"
|
||||||
"- `v` = Initial velocity\n"
|
"- $v$: Initial velocity\n"
|
||||||
"- `θ` = Launch angle\n"
|
"- $\\theta$: Launch angle\n"
|
||||||
"- `g` = Gravitational acceleration\n\n"
|
"- $g$: Gravitational acceleration\n\n"
|
||||||
"",
|
"",
|
||||||
"input": [
|
"input": [
|
||||||
{"name": "v", "unit": "meters per second"}, // Initial velocity
|
{"name": "v", "unit": "meters per second"}, // Initial velocity
|
||||||
{"name": "θ", "unit": "degree"} // Launch angle
|
{"name": "a", "unit": "degree"} // Launch angle
|
||||||
],
|
],
|
||||||
"output": {"name": "R", "unit": "meter"}, // Horizontal distance
|
"output": {"name": "R", "unit": "meter"}, // Horizontal distance
|
||||||
"d4rtCode": "R = (Math.pow(v, 2) * sin(2 * radians(θ))) / 9.80665;",
|
"d4rtCode": """
|
||||||
|
var radians = a * (pi / 180);
|
||||||
|
R = (pow(v, 2) * sin(2 * radians)) / 9.80665;
|
||||||
|
""",
|
||||||
"tags": ["physics", "kinematics", "projectile"]
|
"tags": ["physics", "kinematics", "projectile"]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -91,11 +94,11 @@ Where:
|
||||||
"description": '''
|
"description": '''
|
||||||
Force equals mass times acceleration
|
Force equals mass times acceleration
|
||||||
|
|
||||||
`F = m * a`
|
$$F = m \\cdot a$$
|
||||||
|
|
||||||
Where:
|
Where:
|
||||||
- `m` = Mass of object (kg)
|
- $m$: Mass of object ($\\mathrm{kg}$)
|
||||||
- `a` = Acceleration (m/s²)
|
- $a$: Acceleration ($\\mathrm{m/s^2}$)
|
||||||
|
|
||||||
''',
|
''',
|
||||||
"input": [
|
"input": [
|
||||||
|
|
|
||||||
|
|
@ -46,30 +46,22 @@ class FormulaEvaluator {
|
||||||
final Number exp = getNumberValueOf( positionalArgs[1].toString() );
|
final Number exp = getNumberValueOf( positionalArgs[1].toString() );
|
||||||
return MyMath.pow(base,exp);
|
return MyMath.pow(base,exp);
|
||||||
},
|
},
|
||||||
|
'log': (visitor, positionalArgs, namedArgs) {
|
||||||
|
final Number x = getNumberValueOf( positionalArgs[0].toString() );
|
||||||
|
return MyMath.log(x);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
interpreter.registerBridgedClass(myMathDefinition, 'package:myapp/my_math.dart');
|
interpreter.registerBridgedClass(myMathDefinition, "package:d4rt_formulas.dart");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
dynamic evaluate(Formula formula, Map<String, dynamic> inputValues) {
|
dynamic evaluate(Formula formula, Map<String, dynamic> inputValues) {
|
||||||
_validateInputValues(formula, inputValues);
|
_validateInputValues(formula, inputValues);
|
||||||
|
final completeSource = _buildCompleteSource(formula, inputValues);
|
||||||
try {
|
final result = _interpreter.execute(source: completeSource);
|
||||||
// Build the complete d4rt source code with variable declarations
|
return result;
|
||||||
final completeSource = _buildCompleteSource(formula, inputValues);
|
|
||||||
|
|
||||||
// Execute the code using d4rt (no args needed since variables are in source)
|
|
||||||
final result = _interpreter.execute(source: completeSource);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (e) {
|
|
||||||
throw FormulaEvaluationException(
|
|
||||||
'Failed to execute formula "${formula.name}"',
|
|
||||||
e,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _validateInputValues(Formula formula, Map<String, dynamic> inputValues) {
|
void _validateInputValues(Formula formula, Map<String, dynamic> inputValues) {
|
||||||
|
|
@ -104,8 +96,17 @@ class FormulaEvaluator {
|
||||||
String _buildCompleteSource(Formula formula, Map<String, dynamic> inputValues) {
|
String _buildCompleteSource(Formula formula, Map<String, dynamic> inputValues) {
|
||||||
final buffer = StringBuffer();
|
final buffer = StringBuffer();
|
||||||
|
|
||||||
buffer.writeln("import 'package:myapp/my_math.dart';");
|
buffer.writeln("""
|
||||||
buffer.writeln("main(){");
|
import 'dart:math';
|
||||||
|
|
||||||
|
//log(x) => M.log(x);
|
||||||
|
//pow(a,b) => M.pow(a,b);
|
||||||
|
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
"""
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
for (final entry in inputValues.entries) {
|
for (final entry in inputValues.entries) {
|
||||||
final varName = entry.key;
|
final varName = entry.key;
|
||||||
|
|
@ -113,16 +114,22 @@ class FormulaEvaluator {
|
||||||
|
|
||||||
if (value is String) {
|
if (value is String) {
|
||||||
final escapedValue = value.replaceAll('"', '\\"');
|
final escapedValue = value.replaceAll('"', '\\"');
|
||||||
buffer.writeln('var $varName = "$escapedValue";');
|
buffer.writeln("""
|
||||||
|
final $varName = "$escapedValue";
|
||||||
|
""");
|
||||||
} else {
|
} else {
|
||||||
buffer.writeln('var $varName = $value;');
|
buffer.writeln("""
|
||||||
|
final $varName = $value;
|
||||||
|
""");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer.writeln("late var ${getOutputVariableName(formula)};");
|
buffer.writeln("""
|
||||||
|
late var ${getOutputVariableName(formula)};
|
||||||
buffer.writeln(formula.d4rtCode);
|
${formula.d4rtCode}
|
||||||
buffer.writeln("return ${getOutputVariableName(formula)};");
|
return ${getOutputVariableName(formula)};
|
||||||
buffer.writeln("}");
|
}
|
||||||
|
"""
|
||||||
|
);
|
||||||
|
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
56
pubspec.lock
56
pubspec.lock
|
|
@ -299,6 +299,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
|
nested:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: nested
|
||||||
|
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
node_preamble:
|
node_preamble:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -323,6 +331,30 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.1"
|
version: "1.9.1"
|
||||||
|
path_drawing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_drawing
|
||||||
|
sha256: "3bdd251dae9ffaef944450b73f168610db7e968e7b20daf0c3907f8b4aafc8a2"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.1+1"
|
||||||
|
path_parsing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_parsing
|
||||||
|
sha256: ee5c47c1058ad66b4a41746ec3996af9593d0858872807bcd64ac118f0700337
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.1"
|
||||||
|
petitparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: petitparser
|
||||||
|
sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.4.0"
|
||||||
pool:
|
pool:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -331,6 +363,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.1"
|
version: "1.5.1"
|
||||||
|
provider:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: provider
|
||||||
|
sha256: "59471e0a4595e264625d3496af567ac85bdae1148ec985aff1e0555786f53ecf"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.0"
|
||||||
pub_semver:
|
pub_semver:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -464,6 +504,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.12"
|
version: "0.6.12"
|
||||||
|
tuple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: tuple
|
||||||
|
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -528,6 +576,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.1"
|
version: "1.2.1"
|
||||||
|
xml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xml
|
||||||
|
sha256: "80d494c09849dc3f899d227a78c30c5b949b985ededf884cb3f3bcd39f4b447a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.4.1"
|
||||||
yaml:
|
yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
37
test/d4rt_test.dart
Normal file
37
test/d4rt_test.dart
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:d4rt/d4rt.dart';
|
||||||
|
import 'dart:math' as Math;
|
||||||
|
|
||||||
|
|
||||||
|
main(){
|
||||||
|
test('Access to Math', () {
|
||||||
|
|
||||||
|
final completeSource = """
|
||||||
|
import 'dart:math';
|
||||||
|
main() => sin(42);
|
||||||
|
|
||||||
|
""";
|
||||||
|
final interpreter = D4rt();
|
||||||
|
final result = interpreter.execute(source: completeSource);
|
||||||
|
|
||||||
|
expect(result, Math.sin(42));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Access to IO', () {
|
||||||
|
|
||||||
|
final completeSource = """
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
File file = File('/etc/passwd');
|
||||||
|
String contents = file.readAsStringSync();
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
final interpreter = D4rt();
|
||||||
|
final result = interpreter.execute(source: completeSource);
|
||||||
|
|
||||||
|
expect(result, contains("root"));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -141,19 +141,6 @@ void main() {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('throws exception for invalid d4rt code', () {
|
|
||||||
final formula = Formula(
|
|
||||||
name: 'Invalid code formula',
|
|
||||||
input: [VariableSpec(name: 'x', unit: 'scalar')],
|
|
||||||
output: VariableSpec(name: 'result', unit: 'scalar'),
|
|
||||||
d4rtCode: 'invalid dart code here!',
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(
|
|
||||||
() => evaluator.evaluate(formula, {'x': 1}),
|
|
||||||
throwsA(isA<FormulaEvaluationException>()),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
group('Utility methods', () {
|
group('Utility methods', () {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue