setutils: static util methods
This commit is contained in:
parent
aadfc9dac5
commit
bb468ff601
6 changed files with 80 additions and 112 deletions
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import '../formula_models.dart';
|
||||||
import 'corpus_database_interface.dart';
|
import 'corpus_database_interface.dart';
|
||||||
import 'formulas_database.dart';
|
import 'formulas_database.dart';
|
||||||
import 'package:d4rt_formulas/formula_models.dart' as models;
|
import 'package:d4rt_formulas/formula_models.dart' as models;
|
||||||
|
|
@ -11,7 +12,7 @@ extension CorpusDatabaseExtension on FormulasDatabase {
|
||||||
|
|
||||||
for (final element in elements) {
|
for (final element in elements) {
|
||||||
try {
|
try {
|
||||||
final parsed = models.parseCorpusElements('[${element.elementText}]');
|
final parsed = SetUtils.parseCorpusElements('[${element.elementText}]');
|
||||||
print("PARSED:$element");
|
print("PARSED:$element");
|
||||||
parsedElements.addAll(parsed);
|
parsedElements.addAll(parsed);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import 'package:d4rt/d4rt.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:d4rt_formulas/d4rt_formulas.dart';
|
import 'package:d4rt_formulas/d4rt_formulas.dart';
|
||||||
|
|
||||||
|
typedef Number = double;
|
||||||
|
|
||||||
abstract class SetUtils {
|
abstract class SetUtils {
|
||||||
static Object safeGet(Map<Object?, Object?> map, String key) {
|
static Object safeGet(Map<Object?, Object?> map, String key) {
|
||||||
if (!map.containsKey(key)) {
|
if (!map.containsKey(key)) {
|
||||||
|
|
@ -21,60 +23,55 @@ abstract class SetUtils {
|
||||||
static Number numberValue(Map<Object?, Object?> map, String key) {
|
static Number numberValue(Map<Object?, Object?> map, String key) {
|
||||||
return double.parse(stringValue(map, key));
|
return double.parse(stringValue(map, key));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Parses a d4rt array literal (containing maps and arrays) to a List<Object?>
|
/// Parses a d4rt array literal (containing maps and arrays) to a List<Object?>
|
||||||
/// using d4rt
|
/// using d4rt
|
||||||
List<Object?> parseD4rtLiteral(String arrayStringLiteral) {
|
static List<Object?> parseD4rtLiteral(String arrayStringLiteral) {
|
||||||
var d4rt = D4rt();
|
var d4rt = D4rt();
|
||||||
final buffer = StringBuffer();
|
final buffer = StringBuffer();
|
||||||
buffer.write("main(){ return $arrayStringLiteral; }");
|
buffer.write("main(){ return $arrayStringLiteral; }");
|
||||||
final code = buffer.toString();
|
final code = buffer.toString();
|
||||||
|
|
||||||
final List<Object?> list = d4rt.execute(source: code);
|
final List<Object?> list = d4rt.execute(source: code);
|
||||||
|
|
||||||
return list;
|
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<FormulaElement> parseCorpusElements(String arrayStringLiteral) {
|
|
||||||
final List<Object?> elements = parseD4rtLiteral(arrayStringLiteral);
|
|
||||||
|
|
||||||
final List<FormulaElement> result = [];
|
|
||||||
for (final element in elements) {
|
|
||||||
if (element is Map<Object?, Object?>) {
|
|
||||||
// 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 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<FormulaElement> parseCorpusElements(String arrayStringLiteral) {
|
||||||
|
final List<Object?> elements = parseD4rtLiteral(arrayStringLiteral);
|
||||||
|
|
||||||
|
final List<FormulaElement> result = [];
|
||||||
|
for (final element in elements) {
|
||||||
|
if (element is Map<Object?, Object?>) {
|
||||||
|
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 base class for formula elements
|
||||||
abstract class FormulaElement {
|
abstract class FormulaElement {
|
||||||
|
|
@ -104,7 +101,7 @@ class UnitSpec implements FormulaElement {
|
||||||
String name = SetUtils.stringValue(theSet, "name");
|
String name = SetUtils.stringValue(theSet, "name");
|
||||||
String symbol = SetUtils.stringValue(theSet, "symbol");
|
String symbol = SetUtils.stringValue(theSet, "symbol");
|
||||||
|
|
||||||
if( theSet.containsKey("isBase") ){
|
if (theSet.containsKey("isBase")) {
|
||||||
return UnitSpec(name: name, baseUnit: name, symbol: symbol, factorFromUnitToBase: 1);
|
return UnitSpec(name: name, baseUnit: name, symbol: symbol, factorFromUnitToBase: 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,32 +115,24 @@ class UnitSpec implements FormulaElement {
|
||||||
symbol: symbol,
|
symbol: symbol,
|
||||||
factorFromUnitToBase: factorFromUnitToBase,
|
factorFromUnitToBase: factorFromUnitToBase,
|
||||||
);
|
);
|
||||||
}
|
} else if (theSet.containsKey("toBase")) {
|
||||||
else if( theSet.containsKey("toBase")) {
|
String codeFromBaseToUnit = SetUtils.stringValue(theSet, "fromBase");
|
||||||
String codeFromBaseToUnit = SetUtils.stringValue(
|
String codeFromUnitToBase = SetUtils.stringValue(theSet, "toBase");
|
||||||
theSet,
|
|
||||||
"fromBase",
|
return UnitSpec(
|
||||||
|
name: name,
|
||||||
|
baseUnit: baseUnit,
|
||||||
|
symbol: symbol,
|
||||||
|
codeFromBaseToUnit: codeFromBaseToUnit,
|
||||||
|
codeFromUnitToBase: codeFromUnitToBase,
|
||||||
);
|
);
|
||||||
String codeFromUnitToBase = SetUtils.stringValue(
|
} else {
|
||||||
theSet,
|
throw ArgumentError("Need factor or toBase/fromBase");
|
||||||
"toBase",
|
|
||||||
);
|
|
||||||
|
|
||||||
return UnitSpec(name: name,
|
|
||||||
baseUnit: baseUnit,
|
|
||||||
symbol: symbol,
|
|
||||||
codeFromBaseToUnit: codeFromBaseToUnit,
|
|
||||||
codeFromUnitToBase: codeFromUnitToBase);
|
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
throw ArgumentError( "Need factor or toBase/fromBase");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<UnitSpec> fromArrayStringLiteral(String arrayStringLiteral) {
|
static List<UnitSpec> fromArrayStringLiteral(String arrayStringLiteral) {
|
||||||
final List<Object?> list = parseD4rtLiteral(arrayStringLiteral);
|
final List<Object?> list = SetUtils.parseD4rtLiteral(arrayStringLiteral);
|
||||||
|
|
||||||
final units = list.map((set) => UnitSpec.fromSet(set as Map));
|
final units = list.map((set) => UnitSpec.fromSet(set as Map));
|
||||||
|
|
||||||
|
|
@ -153,18 +142,17 @@ class UnitSpec implements FormulaElement {
|
||||||
@override
|
@override
|
||||||
String toStringLiteral() {
|
String toStringLiteral() {
|
||||||
final buffer = StringBuffer('{');
|
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) {
|
if (name == baseUnit && factorFromUnitToBase == 1) {
|
||||||
// This is a base unit
|
|
||||||
buffer.write(', "isBase": true');
|
buffer.write(', "isBase": true');
|
||||||
} else {
|
} else {
|
||||||
buffer.write(', "baseUnit": "${escapeD4rtString(baseUnit)}"');
|
buffer.write(', "baseUnit": "${SetUtils.escapeD4rtString(baseUnit)}"');
|
||||||
|
|
||||||
if (factorFromUnitToBase != null) {
|
if (factorFromUnitToBase != null) {
|
||||||
buffer.write(', "factor": $factorFromUnitToBase');
|
buffer.write(', "factor": $factorFromUnitToBase');
|
||||||
} else if (codeFromUnitToBase != null && codeFromBaseToUnit != null) {
|
} 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 String? unit;
|
||||||
final List<dynamic>? values;
|
final List<dynamic>? values;
|
||||||
|
|
||||||
VariableSpec({required this.name, this.unit, this.values}){
|
VariableSpec({required this.name, this.unit, this.values}) {
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void validate(){
|
void validate() {
|
||||||
if( FormulaEvaluator.reservedVariableNames.contains(name) ){
|
if (FormulaEvaluator.reservedVariableNames.contains(name)) {
|
||||||
throw ArgumentError("$name: is a reserved variable name for FormulaEvaluator");
|
throw ArgumentError("$name: is a reserved variable name for FormulaEvaluator");
|
||||||
}
|
}
|
||||||
final valuesValid = values != null && values?.isNotEmpty == true;
|
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");
|
throw ArgumentError("$name: at least unit or allowedValues should be valid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -210,20 +198,20 @@ class VariableSpec {
|
||||||
@override
|
@override
|
||||||
String toStringLiteral() {
|
String toStringLiteral() {
|
||||||
final buffer = StringBuffer('{');
|
final buffer = StringBuffer('{');
|
||||||
buffer.write('"name": "${escapeD4rtString(name)}"');
|
buffer.write('"name": "${SetUtils.escapeD4rtString(name)}"');
|
||||||
|
|
||||||
if (unit != null) {
|
if (unit != null) {
|
||||||
buffer.write(', "unit": "${escapeD4rtString(unit!)}"');
|
buffer.write(', "unit": "${SetUtils.escapeD4rtString(unit!)}"');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values != null && values!.isNotEmpty) {
|
if (values != null && values!.isNotEmpty) {
|
||||||
buffer.write(', "values": [${values!.map((value) {
|
buffer.write(', "values": [${values!.map((value) {
|
||||||
if (value is String) {
|
if (value is String) {
|
||||||
return '"${escapeD4rtString(value)}"';
|
return '"${SetUtils.escapeD4rtString(value)}"';
|
||||||
} else {
|
} else {
|
||||||
return value.toString();
|
return value.toString();
|
||||||
}
|
}
|
||||||
}).join(", ")}]');
|
}).join(", ")} ]');
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.write('}');
|
buffer.write('}');
|
||||||
|
|
@ -276,8 +264,7 @@ class Formula implements FormulaElement {
|
||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
Object.hash(name, description, ListEquality().hash(input), output, d4rtCode, ListEquality().hash(tags));
|
Object.hash(name, description, ListEquality().hash(input), output, d4rtCode, ListEquality().hash(tags));
|
||||||
|
|
||||||
List<String> inputVarNames() =>
|
List<String> inputVarNames() => input.map((v) => v.name).toList(growable: false);
|
||||||
input.map((v) => v.name).toList(growable: false);
|
|
||||||
|
|
||||||
factory Formula.fromStringLiteral(String setStringLiteral) {
|
factory Formula.fromStringLiteral(String setStringLiteral) {
|
||||||
var d4rt = D4rt();
|
var d4rt = D4rt();
|
||||||
|
|
@ -291,7 +278,7 @@ class Formula implements FormulaElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<Formula> fromArrayStringLiteral(String arrayStringLiteral) {
|
static List<Formula> fromArrayStringLiteral(String arrayStringLiteral) {
|
||||||
final List<Object?> list = parseD4rtLiteral(arrayStringLiteral);
|
final List<Object?> list = SetUtils.parseD4rtLiteral(arrayStringLiteral);
|
||||||
|
|
||||||
final formulas = list.map((set) => Formula.fromSet(set as Map));
|
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 name = SetUtils.stringValue(theSet, "name");
|
||||||
String? description = theSet ["description"] as String?;
|
String? description = theSet["description"] as String?;
|
||||||
List<String> tags = (theSet["tags"] as List<Object?>? ?? []).map((t) => t.toString()).toList();
|
List<String> tags = (theSet["tags"] as List<Object?>? ?? []).map((t) => t.toString()).toList();
|
||||||
final List<Object?> inputSet = SetUtils.listValue(theSet, "input");
|
final List<Object?> inputSet = SetUtils.listValue(theSet, "input");
|
||||||
List<VariableSpec> input = inputSet
|
List<VariableSpec> input = inputSet.map((v) => parseVar(v as Map)).toList(growable: false);
|
||||||
.map((v) => parseVar(v as Map))
|
Map<Object?, Object?> outputSet = theSet['output'] as Map<Object?, Object?>;
|
||||||
.toList(growable: false);
|
|
||||||
Map<Object?, Object?> outputSet = theSet.get("output");
|
|
||||||
VariableSpec output = parseVar(outputSet);
|
VariableSpec output = parseVar(outputSet);
|
||||||
String d4rtCode = SetUtils.stringValue(theSet, "d4rtCode");
|
String d4rtCode = SetUtils.stringValue(theSet, "d4rtCode");
|
||||||
|
|
||||||
|
|
@ -350,7 +335,7 @@ class Formula implements FormulaElement {
|
||||||
final inputStrings = input.map((varSpec) => varSpec.toStringLiteral()).toList();
|
final inputStrings = input.map((varSpec) => varSpec.toStringLiteral()).toList();
|
||||||
|
|
||||||
final buffer = StringBuffer('{');
|
final buffer = StringBuffer('{');
|
||||||
buffer.write('"name": "$name"');
|
buffer.write('"name": "${SetUtils.escapeD4rtString(name)}"');
|
||||||
|
|
||||||
if (description != null) {
|
if (description != null) {
|
||||||
buffer.write(', "description": r"""${description!}"""');
|
buffer.write(', "description": r"""${description!}"""');
|
||||||
|
|
@ -362,7 +347,7 @@ class Formula implements FormulaElement {
|
||||||
buffer.write(', "d4rtCode": r"""$d4rtCode"""');
|
buffer.write(', "d4rtCode": r"""$d4rtCode"""');
|
||||||
|
|
||||||
if (tags.isNotEmpty) {
|
if (tags.isNotEmpty) {
|
||||||
buffer.write(', "tags": [${tags.map((tag) => '"${escapeD4rtString(tag)}"').join(", ")}]');
|
buffer.write(', "tags": [${tags.map((tag) => '"${SetUtils.escapeD4rtString(tag)}"').join(", ")}]');
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.write('}');
|
buffer.write('}');
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import 'package:d4rt_formulas/d4rt_formulas.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'database/database_service.dart';
|
import 'database/database_service.dart';
|
||||||
import 'package:drift/drift.dart' as drift;
|
|
||||||
import 'service_locator.dart';
|
import 'service_locator.dart';
|
||||||
|
|
||||||
import 'ai/formula_list.dart';
|
import 'ai/formula_list.dart';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'package:d4rt/d4rt.dart';
|
|
||||||
|
|
||||||
|
|
||||||
void main(){
|
void main(){
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ void main() {
|
||||||
);
|
);
|
||||||
|
|
||||||
final literal = originalUnit.toStringLiteral();
|
final literal = originalUnit.toStringLiteral();
|
||||||
final parsedList = parseD4rtLiteral('[${literal}]');
|
final parsedList = SetUtils.parseD4rtLiteral('[${literal}]');
|
||||||
final parsedMap = parsedList[0] as Map<Object?, Object?>;
|
final parsedMap = parsedList[0] as Map<Object?, Object?>;
|
||||||
final parsedUnit = UnitSpec.fromSet(parsedMap);
|
final parsedUnit = UnitSpec.fromSet(parsedMap);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue