This is a Flutter plugin monorepo for the parsec math equation parser library that provides cross-platform native C++ math evaluation capabilities.
This repository follows a federated Flutter plugin architecture:
- parsec/: Main plugin package that depends on platform implementations
- parsec_platform_interface/: Common interface for all platform implementations
- parsec_android/: Android platform implementation using JNI
- parsec_linux/: Linux platform implementation using FFI
- parsec_windows/: Windows platform implementation using FFI
- parsec_web/: Web/JavaScript implementation (separate library)
- Flutter SDK: >=3.19.0
- Dart SDK: >=3.3.0 <4.0.0
- Linting: Uses
flutter_lints ^4.0.0for all packages - Testing: Standard Flutter test framework with platform-specific mocking
# Generate WebAssembly files for parsec_web (required for web platform)
cd parsec_web && dart bin/generate.dart# Test all packages from their respective directories
cd parsec && flutter test
cd parsec_android && flutter test
cd parsec_linux && flutter test
cd parsec_windows && flutter test
cd parsec_platform_interface && flutter test
# Web platform testing (requires WASM files)
cd parsec && flutter test --platform chrome# Run analysis on each package
cd parsec && flutter analyze
cd parsec_android && flutter analyze
cd parsec_linux && flutter analyze
cd parsec_windows && flutter analyze
cd parsec_platform_interface && flutter analyzecd parsec/example
flutter build [linux|windows|apk]Always apply these core principles when working with this codebase:
-
DRY (Don't Repeat Yourself): If code is identical or very similar, extract it into a generalized function. Parameters are your friends.
-
KISS (Keep It Simple Stupid): Make code so "stupid" that a 5-year-old could understand it.
-
SRP (Single Responsibility Principle): Separate code into simple, well-defined, well-intentioned tasks with clear names. Prevents "spaghetti code".
-
Avoid Hadouken IFs: Avoid nested IFs → Solution: Early Returns and/or Switch-Cases.
-
Avoid Negative Conditionals: Positive conditionals reduce mental strain and make code easier to reason about.
-
Encapsulate Conditionals: For conditions with 3+ comparisons, extract into functions that convey the intent. Create names that reveal the conditional's purpose.
-
Avoid Flag Arguments: Avoid boolean arguments (true/false) to functions. Use descriptive strings or enums instead.
-
Avoid Comments: Code should be self-documenting with intention-revealing names. If comments are necessary, explain the "why" not the "what". Use SRP and intention-revealing names as your primary tools.
-
Good Nomenclatures: Use descriptive variable names that reveal intent. Use pronounceable and searchable names. Follow language, business, and team conventions.
-
Use Vertical Formatting: Code should read top to bottom without "jumping". Similar and dependent functions should be vertically close.
-
Boy Scout Rule: Always leave the codebase cleaner than you found it. Improve Clean Code whenever you touch existing code.
When working with this project, AI agents just execute tests from changed files
Philosophy: User-centric testing principles ensure all tests are meaningful from the user's perspective.
Structure: Tests must prioritize clarity, consistency, and maintainability. Write tests for people to read, not machines to execute.
Real-world Testing: Favor real-world interactions over mocks/stubs. Avoid mocks and stubs wherever possible.
-
describe()blocks: Describe scenarios using subordinating conjunctions- Pattern: Start with "when", "after", "while", "with"
- Examples:
- "when filtering by different column types"
- "after the database is populated"
- "with multiple conditions"
-
before()/before(:all): Prepare scenarios for testing- Setup database schema, create items, configure environment
- Declare important
@variablesfor testing - Execute operations and prerequisites
-
it()blocks: Test specific outcomes and assertions- Pattern: Start with "should"
- Examples:
- "should find exact string matches"
- "should be case sensitive"
- "should create and associate items correctly"
- Uses the Platform Interface pattern with
plugin_platform_interface - Each platform implementation extends
ParsecPlatformabstract class - Method channel communication with native C++ libraries
- JSON-based result parsing with type safety
- Package names: Snake_case with
parsec_prefix - Classes: PascalCase (e.g.,
ParsecLinux,ParsecAndroid) - Methods: camelCase (e.g.,
nativeEval,parseNativeEvalResult) - Constants: UPPER_SNAKE_CASE
- Custom exception:
ParsecEvalExceptionfor math evaluation errors - JSON response format:
{"val": "result", "type": "i|f|b|s", "error": null} - Platform-specific error propagation through method channels
- Mock
MethodChannelfor platform implementations - Test registration of platform instances
- Focus on interface compliance rather than native C++ logic
lib/parsec.dart: Main API class with simpleeval(String)method- Depends on platform interface, no direct platform dependencies
lib/parsec_platform.dart: Abstract base class for all platformslib/parsec_eval_exception.dart: Custom exception typeslib/method_channel_parsec.dart: Default method channel implementation
Each follows identical structure:
lib/
parsec_{platform}.dart # Main platform class
test/
parsec_{platform}_test.dart # Registration tests
pubspec.yaml # Platform-specific dependencies
- Platform Interface Version: Currently ^0.2.1 across all implementations
- Flutter Lints: ^4.0.0 (latest) for strict code quality
- Plugin Platform Interface: ^2.1.8 for base platform functionality
- Android: JNI bridge to C++ equations-parser library
- Linux: FFI integration with compiled C++ library
- Windows: FFI integration with compiled C++ library
- Method Channels: Standard Flutter communication pattern
- This is a federated plugin - changes to platform interface affect all implementations
- Native libraries are pre-built and included in platform packages
- Local path dependencies are used for development (see pubspec.yaml files)
- No iOS/macOS/Web support in main plugin (separate web library exists)
The parsec_web package uses WebAssembly compiled from C++ for high performance:
- Emscripten: Required to compile C++ to WebAssembly
# Ubuntu/Debian sudo apt-get install emscripten # Or install via emsdk git clone https://github.com/emscripten-core/emsdk.git cd emsdk && ./emsdk install latest && ./emsdk activate latest source ./emsdk_env.sh
- Generate WASM files:
cd parsec_web && dart bin/generate.dart - Test functionality:
cd parsec_web/lib/parsec-web && npm test - Integration testing:
cd parsec && flutter test --platform chrome
- Validates parsec-web submodule exists
- Compiles C++ equations-parser (38 source files) to WebAssembly using Emscripten
- Generates
wasm/equations_parser.js(WASM glue + binary, ~635KB) - Verifies JavaScript wrapper and WASM files are present
- Provides user-friendly output and next steps
parsec_web uses evalRaw() function for direct C++ JSON output:
- Data flow: Dart →
evalRaw()→ WebAssembly → Raw JSON → Dart - Platform consistency: All platforms receive identical JSON from C++
- Simplified code: Eliminated complex type conversion layers
- Generate WASM first - run
cd parsec_web && dart bin/generate.dartbefore web testing - Always test across platforms - changes to interface affect all implementations
- Maintain version consistency - keep platform interface versions aligned
- Follow Flutter plugin conventions - use established patterns for method channels
- Preserve JSON contract - native libraries expect specific response format
- Update documentation - especially README.md examples if API changes
- Run analysis - ensure all packages pass
flutter analyzebefore commits
ONLY When prompted with "draft a pull request":
-
Analyze changes
- Run
git diff upstream/mainand check the changes. - Summarize all relevant commits, file modifications, and key impacts.
- Run
-
Create a Markdown draft
- Produce content that can be pasted directly into the PR title and description fields.
- Structure the description with the template imported below: .github/pull_request_template.md
- Enhance clarity with markdown code fences with language tags, colors, tables, blockquotes for callouts, admonitions (GitHub alerts), mermaid diagrams, images, collapsible details and etc.
-
Write the Test Guidance section
- Assume a tester is going to test the changes proposed on this pull request.
- Describe step-by-step checks needs to be performed to carefully test it.
-
Generate a Markdown file
- Generate a
pull_request.mdfile containing the Pull Request title and description
- Generate a