From ba6c761ceeb2e4a28e8be9dc5f845aaca4c432ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Gonz=C3=A1lez?= Date: Mon, 22 Sep 2025 17:00:34 +0200 Subject: [PATCH] Test for d4rt --- lib/defaults/formulas.d4rt | 47 ++++++++++++++------------ lib/formula_evaluator.dart | 57 ++++++++++++++++++-------------- pubspec.lock | 56 +++++++++++++++++++++++++++++++ test/d4rt_test.dart | 37 +++++++++++++++++++++ test/formula_evaluator_test.dart | 13 -------- 5 files changed, 150 insertions(+), 60 deletions(-) create mode 100644 test/d4rt_test.dart diff --git a/lib/defaults/formulas.d4rt b/lib/defaults/formulas.d4rt index c6e6001..da40891 100644 --- a/lib/defaults/formulas.d4rt +++ b/lib/defaults/formulas.d4rt @@ -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": [ diff --git a/lib/formula_evaluator.dart b/lib/formula_evaluator.dart index 9b5b0a4..df42aaf 100644 --- a/lib/formula_evaluator.dart +++ b/lib/formula_evaluator.dart @@ -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 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, - ); - } + final completeSource = _buildCompleteSource(formula, inputValues); + final result = _interpreter.execute(source: completeSource); + return result; } void _validateInputValues(Formula formula, Map inputValues) { @@ -104,8 +96,17 @@ class FormulaEvaluator { String _buildCompleteSource(Formula formula, Map 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(); } diff --git a/pubspec.lock b/pubspec.lock index b1879fe..3b77547 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -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: diff --git a/test/d4rt_test.dart b/test/d4rt_test.dart new file mode 100644 index 0000000..bc68e6c --- /dev/null +++ b/test/d4rt_test.dart @@ -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")); + }); + +} diff --git a/test/formula_evaluator_test.dart b/test/formula_evaluator_test.dart index 38ab493..727759f 100644 --- a/test/formula_evaluator_test.dart +++ b/test/formula_evaluator_test.dart @@ -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()), - ); - }); }); group('Utility methods', () {