Skip to content

openedges/ocl-lang

ocl-lang

Pure Rust implementation of Object Constraint Language (OCL) 2.4 with Eclipse OCL compatible APIs.

Workspace

  • crates/tree-sitter-ocl: tree-sitter grammar and bindings
  • crates/ocl: core parsing and evaluation library

Notes

  • The tree-sitter parser sources (src/parser.c) are generated by tree-sitter generate.
  • Run tree-sitter generate inside crates/tree-sitter-ocl before building if the parser is missing.
  • Use ./scripts/tree-sitter-test.sh to run corpus tests without writing to your home directory.
  • External tooling locations are documented in tools/README.md.
  • Enum literals are supported in expressions using TypeName::LITERAL.

Quickstart

# Generate the parser once (requires tree-sitter CLI)
./scripts/generate-tree-sitter.sh

# Build workspace
cargo build

Cargo Dependency

[dependencies]
ocl = { package = "ocl-lang", version = "0.1" }

Usage

use ocl::{Metamodel, Ocl, OclBindable, OclValue};

struct EmptyMetamodel;

impl Metamodel for EmptyMetamodel {
    type Classifier = String;
    type Operation = String;
    type Property = String;

    fn get_classifier(&self, name: &str) -> Option<Self::Classifier> {
        Some(name.to_string())
    }
    fn get_properties(&self, _classifier: &Self::Classifier) -> Vec<Self::Property> {
        Vec::new()
    }
    fn get_operations(&self, _classifier: &Self::Classifier) -> Vec<Self::Operation> {
        Vec::new()
    }
    fn conforms_to(&self, subtype: &Self::Classifier, supertype: &Self::Classifier) -> bool {
        subtype == supertype
    }
    fn property_type(&self, _property: &Self::Property) -> Self::Classifier {
        "OclAny".to_string()
    }
    fn operation_return_type(&self, _operation: &Self::Operation) -> Self::Classifier {
        "OclAny".to_string()
    }
}

struct EmptyContext;

impl OclBindable for EmptyContext {
    fn to_ocl_value(&self) -> OclValue {
        OclValue::Null
    }
    fn get_property(&self, _name: &str) -> Option<OclValue> {
        None
    }
    fn ocl_type_name(&self) -> &str {
        "OclVoid"
    }
}

let ocl = Ocl::new(EmptyMetamodel);
let result = ocl.evaluate("1 + 2", &EmptyContext).unwrap();
assert!(matches!(result, OclValue::Integer(3)));

Compatibility Levels

Level 1: Core OCL 2.4 support (expressions, collections/iterators, stdlib, constraints/defs, null/invalid propagation, metamodel-backed property/operation resolution).

Level 2: Model integration parity (EMF/UML/Pivot + Complete OCL environments).

Level 3: Eclipse tooling parity (IDE/validation/codegen + full upstream suite and perf gates).

Current status: Level 1 is implemented. Extracted Eclipse OCL evaluation fixtures (tests/conformance/eclipse) pass 100% (1,983 tests after the latest import). Use cargo run -p ocl-lang --bin conformance_report -- --dir tests/conformance/eclipse to recompute counts and pass rate.

Parsing Helpers

let mut ocl = Ocl::new(EmptyMetamodel);
let expr = ocl.parse_expression("1 + 2").unwrap();
let query = ocl.create_query(&expr);
let result = query.evaluate(&EmptyContext).unwrap();
assert!(matches!(result, OclValue::Integer(3)));

let query = ocl.create_query_from_str("1 + 2").unwrap();
let result = query.evaluate(&EmptyContext).unwrap();
assert!(matches!(result, OclValue::Integer(3)));

let env = ocl.create_helper().into_environment();
let query = ocl
    .create_query_from_str_with_environment("1 + 2", env)
    .unwrap();
let result = query.evaluate(&EmptyContext).unwrap();
assert!(matches!(result, OclValue::Integer(3)));

let document = ocl
    .parse_document("context Person def: label: String = 'person'")
    .unwrap();
let mut helper = ocl.create_helper();
helper.apply_document(&document);

// Or apply definitions directly to the facade.
ocl.apply_document(&document);

Use OclHelper::set_constraint_context to attach context metadata when building constraints with helper methods. Use OclHelper::clear_context to reset definition scoping between helper definitions. Use OclHelper::clear_operation_context to reset stored operation context metadata. Use OclHelper::clear_constraint_context to reset stored constraint metadata.

Query with Bindings

Assuming the EmptyMetamodel and EmptyContext from above:

use ocl::OclValue;

let ocl = Ocl::new(EmptyMetamodel);
let helper = ocl.create_helper();
let expr = helper.create_query("x + 1").unwrap();

let mut query = ocl.create_query(&expr);
query
    .evaluation_environment()
    .add("x", OclValue::Integer(41));

let result = query.evaluate(&EmptyContext).unwrap();
assert!(matches!(result, OclValue::Integer(42)));

Examples

Example sources live under crates/ocl/examples.

  • cargo run -p ocl-lang --example basic
  • cargo run -p ocl-lang --example collections
  • cargo run -p ocl-lang --example enum_literals
  • cargo run -p ocl-lang --example document
  • cargo run -p ocl-lang --example definitions
  • cargo run -p ocl-lang --example query
  • cargo run -p ocl-lang --example constraints

Testing and Benchmarks

  • Rust tests: cargo test -p ocl-lang (unit + integration under crates/ocl/tests, set CONFORMANCE_DIR to run against external fixtures, CONFORMANCE_SUITE to filter suites).
  • Tree-sitter corpus tests: ./scripts/tree-sitter-test.sh (set TREE_SITTER_BIN to override the CLI path).
  • Conformance tests live in tests/conformance.
  • Conformance summary: ./scripts/conformance-report.sh (requires python3, add --suite NAME or --dir PATH to filter/override, or set CONFORMANCE_SUITE).
  • Conformance fixture validation: ./scripts/validate-conformance.sh (requires python3, add --suite NAME, --dir PATH, --fail-duplicates, --no-warn-duplicates, or set CONFORMANCE_DIR/CONFORMANCE_SUITE).
  • Conformance pass rate: cargo run -p ocl-lang --bin conformance_report (add --suite NAME, --dir PATH, or set CONFORMANCE_DIR/CONFORMANCE_SUITE).
  • Release smoke checks: ./scripts/release-check.sh (add --suite NAME, --dir PATH, CONFORMANCE_DIR, CONFORMANCE_SUITE, --skip-validation, --skip-conformance, --skip-conformance-tests, --skip-tree-sitter, --fail-duplicates, or --no-warn-duplicates).
  • Prereq check: ./scripts/check-prereqs.sh (add --strict to fail on missing tools, --versions to print versions).
  • Criterion bench: OCL_BENCH_FILTER=collect OCL_BENCH_LIMIT=10 OCL_BENCH_FILE=benchmarks/expressions.txt cargo bench -p ocl-lang --bench eval_bench.
  • Benchmark workflow details: benchmarks/README.md.
  • Script reference: scripts/README.md.
  • Crate docs: crates/ocl/README.md and crates/tree-sitter-ocl/README.md.
  • Import Eclipse OCL JSON fixtures with ./scripts/import-eclipse-tests.sh (requires python3, add --source/--output/--clean as needed).
  • Bootstrap Eclipse OCL sources with ./scripts/setup-eclipse-ocl.sh (use --import or --all; override repo with ECLIPSE_OCL_TESTS_REPO).
  • Install Eclipse OCL plugins into an Eclipse app: ./scripts/install-eclipse-ocl-plugins.sh (defaults to tools/Eclipse.app, override with ECLIPSE_APP/ECLIPSE_HOME/ECLIPSE_BIN).
  • Optional env helper: source ./scripts/eclipse-ocl-env.sh.
  • CLI eval helper: cargo run -p ocl-lang --bin ocl_eval -- "1 + 2" (or --file path/to/expr.ocl).
  • Standalone app via Eclipse plugins: ./scripts/run-eclipse-ocl-cli.sh --plugins /path/to/eclipse/plugins --query "1 + 2" (optionally set ECLIPSE_OCL_CLASSPATH via ./scripts/eclipse-ocl-classpath.sh).
  • Benchmark comparison script: ./scripts/benchmark-compare.sh (requires Java and an Eclipse plugins directory; supports env overrides like OCL_EVAL_BIN, EXPRESSIONS_FILE, ITERATIONS, WARMUP, PERF_TOLERANCE, REPEATS, SLEEP_BETWEEN, SLEEP_BETWEEN_EXPR, EXPR_FILTER, EXPR_LIMIT, TIME_BIN (auto-detected), ECLIPSE_OCL_PLUGINS, ECLIPSE_OCL_CLASSPATH, ECLIPSE_OCL_OUTPUT, ECLIPSE_HOME, ECLIPSE_OCL_HOME, JAVA_BIN, JAVA_OPTS, and matching CLI flags; use --list to print the selected expressions; run with --help for the full list).
  • Both helpers default to tools/Eclipse.app/Contents/Eclipse when present, so ECLIPSE_HOME is optional.

Release

  • Publishing checklist: RELEASE.md

Status

This repository is under active development. See AGENTS.md for the implementation plan and milestones.

About

OCL Language for Pure Rust

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors