diff --git a/bin/pruebas_d4rt.dart b/bin/pruebas_d4rt.dart deleted file mode 100644 index 90f6e8a..0000000 --- a/bin/pruebas_d4rt.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:d4rt/d4rt.dart'; - -void main() { - final code = ''' - int fib(int n) { - if (n <= 1) return n; - return fib(n - 1) + fib(n - 2); - } - main() { - return fib(6); - } - '''; - - final interpreter = D4rt(); - final result = interpreter.execute(source: code); - print('Result: $result'); // Result: 8 -} diff --git a/lib/database/database_service.dart b/lib/database/database_service.dart index 06dc034..54033d2 100644 --- a/lib/database/database_service.dart +++ b/lib/database/database_service.dart @@ -1,3 +1,4 @@ +import '../formula_models.dart'; import 'corpus_database_interface.dart'; import 'formulas_database.dart'; import 'package:d4rt_formulas/formula_models.dart' as models; @@ -11,7 +12,7 @@ extension CorpusDatabaseExtension on FormulasDatabase { for (final element in elements) { try { - final parsed = models.parseCorpusElements('[${element.elementText}]'); + final parsed = SetUtils.parseCorpusElements('[${element.elementText}]'); print("PARSED:$element"); parsedElements.addAll(parsed); } catch (e) { diff --git a/lib/formula_models.dart b/lib/formula_models.dart index 7c79574..faeab2e 100644 --- a/lib/formula_models.dart +++ b/lib/formula_models.dart @@ -2,6 +2,8 @@ import 'package:d4rt/d4rt.dart'; import 'package:collection/collection.dart'; import 'package:d4rt_formulas/d4rt_formulas.dart'; +typedef Number = double; + abstract class SetUtils { static Object safeGet(Map map, String key) { if (!map.containsKey(key)) { @@ -21,60 +23,55 @@ abstract class SetUtils { static Number numberValue(Map map, String key) { return double.parse(stringValue(map, key)); } -} -/// Parses a d4rt array literal (containing maps and arrays) to a List -/// using d4rt -List parseD4rtLiteral(String arrayStringLiteral) { - var d4rt = D4rt(); - final buffer = StringBuffer(); - buffer.write("main(){ return $arrayStringLiteral; }"); - final code = buffer.toString(); + /// Parses a d4rt array literal (containing maps and arrays) to a List + /// using d4rt + static List parseD4rtLiteral(String arrayStringLiteral) { + var d4rt = D4rt(); + final buffer = StringBuffer(); + buffer.write("main(){ return $arrayStringLiteral; }"); + final code = buffer.toString(); - final List list = d4rt.execute(source: code); + final List list = d4rt.execute(source: code); - return list; -} - -/// Escapes special characters in a string for use in D4RT literals -String escapeD4rtString(String input) { - return input - .replaceAll(r'\', r'\\') // Escape backslashes first - .replaceAll('\n', r'\n') // Escape newlines - .replaceAll('\r', r'\r') // Escape carriage returns - .replaceAll('\t', r'\t') // Escape tabs - .replaceAll('"', r'\"'); // Escape quotes last -} - -/// Parses corpus elements from an array string literal. -/// Determines if each element is a formula or a unit and converts accordingly. -List parseCorpusElements(String arrayStringLiteral) { - final List elements = parseD4rtLiteral(arrayStringLiteral); - - final List result = []; - for (final element in elements) { - if (element is Map) { - // Check if it's a formula by looking for required formula properties - // Formulas typically have 'd4rtCode' and 'input'/'output' properties - if (element.containsKey('d4rtCode')) { - result.add(Formula.fromSet(element)); - } - // Units typically have 'name', 'symbol', and 'baseUnit' properties - else if (element.containsKey('name') && element.containsKey('symbol')) { - result.add(UnitSpec.fromSet(element)); - } - else { - throw ArgumentError('Unknown element type: $element'); - } - } else { - throw ArgumentError('Element must be a Map: $element'); - } + return list; } - return result; + /// Escapes special characters in a string for use in D4RT literals + static String escapeD4rtString(String input) { + return input + .replaceAll(r'\\', r'\\\\') // escape backslashes first + .replaceAll('\n', r'\\n') + .replaceAll('\r', r'\\r') + .replaceAll('\t', r'\\t') + .replaceAll('"', r'\\"'); + } + + /// Parses corpus elements from an array string literal. + /// Determines if each element is a formula or a unit and converts accordingly. + static List parseCorpusElements(String arrayStringLiteral) { + final List elements = parseD4rtLiteral(arrayStringLiteral); + + final List result = []; + for (final element in elements) { + if (element is Map) { + if (element.containsKey('d4rtCode')) { + result.add(Formula.fromSet(element)); + } else + if (element.containsKey('name') && element.containsKey('symbol')) { + result.add(UnitSpec.fromSet(element)); + } else { + throw ArgumentError('Unknown element type: $element'); + } + } else { + throw ArgumentError('Element must be a Map: $element'); + } + } + + return result; + } } -typedef Number = double; /// Abstract base class for formula elements abstract class FormulaElement { @@ -104,7 +101,7 @@ class UnitSpec implements FormulaElement { String name = SetUtils.stringValue(theSet, "name"); String symbol = SetUtils.stringValue(theSet, "symbol"); - if( theSet.containsKey("isBase") ){ + if (theSet.containsKey("isBase")) { return UnitSpec(name: name, baseUnit: name, symbol: symbol, factorFromUnitToBase: 1); } @@ -118,32 +115,24 @@ class UnitSpec implements FormulaElement { symbol: symbol, factorFromUnitToBase: factorFromUnitToBase, ); - } - else if( theSet.containsKey("toBase")) { - String codeFromBaseToUnit = SetUtils.stringValue( - theSet, - "fromBase", + } else if (theSet.containsKey("toBase")) { + String codeFromBaseToUnit = SetUtils.stringValue(theSet, "fromBase"); + String codeFromUnitToBase = SetUtils.stringValue(theSet, "toBase"); + + return UnitSpec( + name: name, + baseUnit: baseUnit, + symbol: symbol, + codeFromBaseToUnit: codeFromBaseToUnit, + codeFromUnitToBase: codeFromUnitToBase, ); - String codeFromUnitToBase = SetUtils.stringValue( - theSet, - "toBase", - ); - - return UnitSpec(name: name, - baseUnit: baseUnit, - symbol: symbol, - codeFromBaseToUnit: codeFromBaseToUnit, - codeFromUnitToBase: codeFromUnitToBase); + } else { + throw ArgumentError("Need factor or toBase/fromBase"); } - else{ - throw ArgumentError( "Need factor or toBase/fromBase"); - } - - } static List fromArrayStringLiteral(String arrayStringLiteral) { - final List list = parseD4rtLiteral(arrayStringLiteral); + final List list = SetUtils.parseD4rtLiteral(arrayStringLiteral); final units = list.map((set) => UnitSpec.fromSet(set as Map)); @@ -153,18 +142,17 @@ class UnitSpec implements FormulaElement { @override String toStringLiteral() { final buffer = StringBuffer('{'); - buffer.write('"name": "${escapeD4rtString(name)}", "symbol": "${escapeD4rtString(symbol)}"'); + buffer.write('"name": "${SetUtils.escapeD4rtString(name)}", "symbol": "${SetUtils.escapeD4rtString(symbol)}"'); if (name == baseUnit && factorFromUnitToBase == 1) { - // This is a base unit buffer.write(', "isBase": true'); } else { - buffer.write(', "baseUnit": "${escapeD4rtString(baseUnit)}"'); + buffer.write(', "baseUnit": "${SetUtils.escapeD4rtString(baseUnit)}"'); if (factorFromUnitToBase != null) { buffer.write(', "factor": $factorFromUnitToBase'); } else if (codeFromUnitToBase != null && codeFromBaseToUnit != null) { - buffer.write(', "toBase": "${escapeD4rtString(codeFromUnitToBase!)}", "fromBase": "${escapeD4rtString(codeFromBaseToUnit!)}"'); + buffer.write(', "toBase": "${SetUtils.escapeD4rtString(codeFromUnitToBase!)}", "fromBase": "${SetUtils.escapeD4rtString(codeFromBaseToUnit!)}"'); } } @@ -178,16 +166,16 @@ class VariableSpec { final String? unit; final List? values; - VariableSpec({required this.name, this.unit, this.values}){ + VariableSpec({required this.name, this.unit, this.values}) { validate(); } - void validate(){ - if( FormulaEvaluator.reservedVariableNames.contains(name) ){ + void validate() { + if (FormulaEvaluator.reservedVariableNames.contains(name)) { throw ArgumentError("$name: is a reserved variable name for FormulaEvaluator"); } final valuesValid = values != null && values?.isNotEmpty == true; - if( unit == null && !valuesValid ){ + if (unit == null && !valuesValid) { throw ArgumentError("$name: at least unit or allowedValues should be valid"); } } @@ -210,20 +198,20 @@ class VariableSpec { @override String toStringLiteral() { final buffer = StringBuffer('{'); - buffer.write('"name": "${escapeD4rtString(name)}"'); + buffer.write('"name": "${SetUtils.escapeD4rtString(name)}"'); if (unit != null) { - buffer.write(', "unit": "${escapeD4rtString(unit!)}"'); + buffer.write(', "unit": "${SetUtils.escapeD4rtString(unit!)}"'); } if (values != null && values!.isNotEmpty) { buffer.write(', "values": [${values!.map((value) { if (value is String) { - return '"${escapeD4rtString(value)}"'; + return '"${SetUtils.escapeD4rtString(value)}"'; } else { return value.toString(); } - }).join(", ")}]'); + }).join(", ")} ]'); } buffer.write('}'); @@ -276,8 +264,7 @@ class Formula implements FormulaElement { int get hashCode => Object.hash(name, description, ListEquality().hash(input), output, d4rtCode, ListEquality().hash(tags)); - List inputVarNames() => - input.map((v) => v.name).toList(growable: false); + List inputVarNames() => input.map((v) => v.name).toList(growable: false); factory Formula.fromStringLiteral(String setStringLiteral) { var d4rt = D4rt(); @@ -291,7 +278,7 @@ class Formula implements FormulaElement { } static List fromArrayStringLiteral(String arrayStringLiteral) { - final List list = parseD4rtLiteral(arrayStringLiteral); + final List list = SetUtils.parseD4rtLiteral(arrayStringLiteral); final formulas = list.map((set) => Formula.fromSet(set as Map)); @@ -323,13 +310,11 @@ class Formula implements FormulaElement { } String name = SetUtils.stringValue(theSet, "name"); - String? description = theSet ["description"] as String?; + String? description = theSet["description"] as String?; List tags = (theSet["tags"] as List? ?? []).map((t) => t.toString()).toList(); final List inputSet = SetUtils.listValue(theSet, "input"); - List input = inputSet - .map((v) => parseVar(v as Map)) - .toList(growable: false); - Map outputSet = theSet.get("output"); + List input = inputSet.map((v) => parseVar(v as Map)).toList(growable: false); + Map outputSet = theSet['output'] as Map; VariableSpec output = parseVar(outputSet); String d4rtCode = SetUtils.stringValue(theSet, "d4rtCode"); @@ -350,7 +335,7 @@ class Formula implements FormulaElement { final inputStrings = input.map((varSpec) => varSpec.toStringLiteral()).toList(); final buffer = StringBuffer('{'); - buffer.write('"name": "$name"'); + buffer.write('"name": "${SetUtils.escapeD4rtString(name)}"'); if (description != null) { buffer.write(', "description": r"""${description!}"""'); @@ -362,7 +347,7 @@ class Formula implements FormulaElement { buffer.write(', "d4rtCode": r"""$d4rtCode"""'); if (tags.isNotEmpty) { - buffer.write(', "tags": [${tags.map((tag) => '"${escapeD4rtString(tag)}"').join(", ")}]'); + buffer.write(', "tags": [${tags.map((tag) => '"${SetUtils.escapeD4rtString(tag)}"').join(", ")}]'); } buffer.write('}'); diff --git a/lib/main.dart b/lib/main.dart index a1e6684..bb2421a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,7 +2,6 @@ import 'package:d4rt_formulas/d4rt_formulas.dart'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import 'database/database_service.dart'; -import 'package:drift/drift.dart' as drift; import 'service_locator.dart'; import 'ai/formula_list.dart'; diff --git a/test/dart_test.dart b/test/dart_test.dart index ccedad0..64802b5 100644 --- a/test/dart_test.dart +++ b/test/dart_test.dart @@ -1,5 +1,5 @@ import 'package:test/test.dart'; -import 'package:d4rt/d4rt.dart'; + void main(){ diff --git a/test/formula_models_test.dart b/test/formula_models_test.dart index 01a9953..af71609 100644 --- a/test/formula_models_test.dart +++ b/test/formula_models_test.dart @@ -154,7 +154,7 @@ void main() { ); final literal = originalUnit.toStringLiteral(); - final parsedList = parseD4rtLiteral('[${literal}]'); + final parsedList = SetUtils.parseD4rtLiteral('[${literal}]'); final parsedMap = parsedList[0] as Map; final parsedUnit = UnitSpec.fromSet(parsedMap);