Test for d4rt

This commit is contained in:
Álvaro González 2025-09-22 17:00:34 +02:00
parent 80d6c7d0df
commit ba6c761cee
5 changed files with 150 additions and 60 deletions

View file

@ -5,11 +5,11 @@
"description": '''
Calculates vertical displacement under constant gravity
`h = ½gt²`
$$h = \\frac{1}{2}gt^2$$
Where:
- `g` = Gravitational acceleration (9.81 m/s² on Earth)
- `t` = Time in free fall (seconds)
- $g$: Gravitational acceleration ($9.81\\ \\mathrm{m/s^2}$ on Earth)
- $t$: Time in free fall (seconds)
![Free Fall Diagram](https://altcalculator.com/wp-content/uploads/2023/08/Free-Fall.png)''',
"input": [
@ -17,7 +17,7 @@ Where:
{"name": "g", "unit": "meters per second"} // Gravitational acceleration
],
"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"]
},
@ -27,12 +27,12 @@ Where:
"description": '''
Newton's law of universal gravitation
`F = G(m₁m₂)/r²`
$$F = G\\frac{m_1m_2}{r^2}$$
Where:
- `G` = Gravitational constant (6.674×10⁻¹¹ N·m²/kg²)
- `m₁`, `m₂` = Masses of two objects
- `r` = Distance between centers of masses
- $G$: Gravitational constant ($6.674\\times 10^{-11}\\ \\mathrm{N\\cdot m^2/kg^2}$)
- $m_1, m_2$: Masses of two objects
- $r$: Distance between centers of masses
![Gravitation](https://upload.wikimedia.org/wikipedia/commons/thumb/3/33/NewtonsLawOfUniversalGravitation.svg/1200px-NewtonsLawOfUniversalGravitation.svg.png)''',
"input": [
@ -41,7 +41,7 @@ Where:
{"name": "r", "unit": "meter"} // Distance between masses
],
"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"]
},
@ -51,11 +51,11 @@ Where:
"description": '''
Energy possessed by a moving object
`KE = ½mv²`
$$KE = \\frac{1}{2}mv^2$$
Where:
- `m` = Mass of object
- `v` = Velocity of object
- $m$: Mass of object
- $v$: Velocity of object
![Kinetic Energy](https://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Kinetic_energy.svg/1200px-Kinetic_energy.svg.png)''',
"input": [
@ -63,7 +63,7 @@ Where:
{"name": "v", "unit": "meters per second"} // Velocity
],
"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"]
},
@ -71,18 +71,21 @@ Where:
{
"name": "Projectile Range",
"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"
"- `v` = Initial velocity\n"
"- `θ` = Launch angle\n"
"- `g` = Gravitational acceleration\n\n"
"- $v$: Initial velocity\n"
"- $\\theta$: Launch angle\n"
"- $g$: Gravitational acceleration\n\n"
"![Projectile Motion](https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/Projectile_motion_diagram.png/800px-Projectile_motion_diagram.png)",
"input": [
{"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
"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"]
},
@ -91,11 +94,11 @@ Where:
"description": '''
Force equals mass times acceleration
`F = m * a`
$$F = m \\cdot a$$
Where:
- `m` = Mass of object (kg)
- `a` = Acceleration (m/s²)
- $m$: Mass of object ($\\mathrm{kg}$)
- $a$: Acceleration ($\\mathrm{m/s^2}$)
![Newton's Second Law](https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Newtonslawsofmotion.jpg/800px-Newtonslawsofmotion.jpg)''',
"input": [

View file

@ -46,30 +46,22 @@ class FormulaEvaluator {
final Number exp = getNumberValueOf( positionalArgs[1].toString() );
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) {
_validateInputValues(formula, inputValues);
try {
// Build the complete d4rt source code with variable declarations
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) {
@ -104,8 +96,17 @@ class FormulaEvaluator {
String _buildCompleteSource(Formula formula, Map<String, dynamic> inputValues) {
final buffer = StringBuffer();
buffer.writeln("import 'package:myapp/my_math.dart';");
buffer.writeln("main(){");
buffer.writeln("""
import 'dart:math';
//log(x) => M.log(x);
//pow(a,b) => M.pow(a,b);
main()
{
"""
);
for (final entry in inputValues.entries) {
final varName = entry.key;
@ -113,16 +114,22 @@ class FormulaEvaluator {
if (value is String) {
final escapedValue = value.replaceAll('"', '\\"');
buffer.writeln('var $varName = "$escapedValue";');
buffer.writeln("""
final $varName = "$escapedValue";
""");
} else {
buffer.writeln('var $varName = $value;');
buffer.writeln("""
final $varName = $value;
""");
}
}
buffer.writeln("late var ${getOutputVariableName(formula)};");
buffer.writeln(formula.d4rtCode);
buffer.writeln("return ${getOutputVariableName(formula)};");
buffer.writeln("}");
buffer.writeln("""
late var ${getOutputVariableName(formula)};
${formula.d4rtCode}
return ${getOutputVariableName(formula)};
}
"""
);
return buffer.toString();
}

View file

@ -299,6 +299,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
node_preamble:
dependency: transitive
description:
@ -323,6 +331,30 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: transitive
description:
@ -331,6 +363,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.5.1"
provider:
dependency: transitive
description:
name: provider
sha256: "59471e0a4595e264625d3496af567ac85bdae1148ec985aff1e0555786f53ecf"
url: "https://pub.dev"
source: hosted
version: "5.0.0"
pub_semver:
dependency: transitive
description:
@ -464,6 +504,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.12"
tuple:
dependency: transitive
description:
name: tuple
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
url: "https://pub.dev"
source: hosted
version: "2.0.2"
typed_data:
dependency: transitive
description:
@ -528,6 +576,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.1"
xml:
dependency: transitive
description:
name: xml
sha256: "80d494c09849dc3f899d227a78c30c5b949b985ededf884cb3f3bcd39f4b447a"
url: "https://pub.dev"
source: hosted
version: "5.4.1"
yaml:
dependency: transitive
description:

37
test/d4rt_test.dart Normal file
View 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"));
});
}

View file

@ -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', () {