Skip to content
openedgesPublic

About

OCL Language for Pure Rust

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

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

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages