Skip to content

Conversation

@seidewitz
Copy link
Member

This PR implements the (non-model-level) evaluation of all the functions from the following Kernel Function Library packages that had not been previously implemented:

  • CollectionFunctions
  • ControlFunctions
  • SequenceFunctions

Implemented Functions

The following Kernel Functions Library functions are implemented in this PR.

CollectionFunctions

There are no LibraryFunction implementations of these functions, but they all have complete functional specifications in the library model, which evaluate correctly given the other updates in this PR (except for the '#' index functions, which already have model-level evaluation implementations).

ControlFunctions

  • exists
  • forAll
  • maximize
  • minimize
  • reduce
  • reject
  • selectOne

DataFunctions

These functions were implemented to support the implementation of maximize and minimize.

  • max
  • min

SequenceFunctions

  • excludingAt
  • excluding
  • head
  • includesOnly
  • includingAt
  • including
  • intersection
  • last
  • equals
  • same
  • subsequence
  • tail
  • union

Refactoring

The PR also includes some refactoring of the structure of packages related to library function implementations.

  1. The existing model-level evaluable LibraryFunction implementations in the package org.omg.sysml.expressions.function have been re-organized into Java subpackages based on the Kernel Function Library package of the function being implemented.
    • org.omg.sysml.expressions.function.base
    • org.omg.sysml.expressions.function.bool
    • org.omg.sysml.expressions.function.control
    • org.omg.sysml.expressions.function.data
  2. Existing and new non-model-level evaluable LibraryFunction implementations in the package org.omg.sysml.execution.expressions.function have been similarly re-organized into subpackages.
    • org.omg.sysml.execution.expressions.function.data
    • org.omg.sysml.execution.expressions.function.numerical
    • org.omg.sysml.execution.expressions.function.sequence
    • org.omg.sysml.execution.expressions.function.string

Other Changes

  1. Update the implementation of model-level evaluation of equals and not-equals functions to handle Collections.
  2. Fixed the utility method EvaluationUtil::expressionFor when the argument is a list or a body expression.
  3. Removed old hand-written overrides of getInput and getOutput in ExpressionImpl that are no longer necessary.

Created Java packages under corresponding to Kernel Function Library
packages.
- Also added tests to ExpressionEvaluationTest.
Functions are evaluated using modeled return expressions (except for
functions that are evaluated as model-level evaluable library
functions).
@seidewitz seidewitz added this to the 2025-12 milestone Jan 10, 2026
@seidewitz seidewitz self-assigned this Jan 10, 2026
@seidewitz seidewitz requested review from himi and hpdekoning January 10, 2026 00:01
@seidewitz
Copy link
Member Author

@himi @hpdekoning
If one or both of you could do at least a quick review of this in the next few days, I would appreciate it. But, if not, I will go ahead and merge it anyway based on my own testing.

- Also implemented DataFunctions::min and DataFunctions::max, used in
the implementation of ControlFunctions::minimize and maximize.

- Also removed old overrides of getInput and getOutput in
ExpressionImpl.
Type maxFunction = SysMLLibraryUtil.getLibraryType(expr, MIN_FUNCTION);
InvocationExpression maxInvocation = EvaluationUtil.createInvocationOf(maxFunction, result, exprValue.get(0));
EList<Element> newResult = evaluator.evaluateInvocation(maxInvocation, target);
return newResult == null || newResult.size() != 1? null: newResult.get(0);
Copy link
Member

@hpdekoning hpdekoning Jan 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am guessing you meant naming these minFunction, minInvocation. Looks like a copy/paste typo, does not change behavior & result.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, you are right. I've fixed it.

- maxFunction -> minFunction, maxInvocation -> minInvocaion

// ControlFunctions
put(new DotFunction());
put(new ConditionalFunction());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be named ConditionalIfFunction to show correspondence to KerML if function?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function corresponds to what is called a "conditional expression" in KerML and is described as a "conditional test" function. So I think ConditionalFunction is an OK name.

Copy link
Member

@hpdekoning hpdekoning left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks great. I could only do some rather random spot checks.

You may want to check that the copyright statement is updated for 2026 everywhere, but perhaps that is a global check just before release.

@himi
Copy link
Member

himi commented Jan 10, 2026

Thank you. I want to try these functions tonight. But please go ahead if you want to finish this PR.

@himi
Copy link
Member

himi commented Jan 11, 2026

I briefly tested these functions:

image image image

@himi
Copy link
Member

himi commented Jan 11, 2026

I could not find a written specification on these functions in KerML spec. Is the unionResult is intended? While intersection captures the equivalence of numbers, union does not. I found includesOnly seems to check the equality in set semantics, and please check it is intended.

@himi
Copy link
Member

himi commented Jan 11, 2026

I could not make an example to check the difference of == and === and therefore could not check the difference of same and equals. I tried the example below, but both eq2 and eq3 are false. Even if I tried bind ts1 = ts2;, they are false. But if I try timeslice ts2 = ts1;, both are true.

part TestEq {
    timeslice ts1;
    timeslice ts2 {
        :>> startShot = ts1.startShot;
    }
    
    attribute eq2 = ts1 == ts2;
    attribute dq3 = ts1 === ts2;
}

@seidewitz
Copy link
Member Author

@himi

I could not find a written specification on these functions in KerML spec. Is the unionResult is intended? While intersection captures the equivalence of numbers, union does not. I found includesOnly seems to check the equality in set semantics, and please check it is intended.

In general, many of the library functions are really not well specified right now. However, many of the sequence functions actually have complete definitions in SequenceFunctions.kerml, and the Java implementations are intended to be conform to these definitions (except for excludes which is erroneous defined circularly in terms of itself right now!).

The definition of union is that it operates on ordered, non-unique sequences and that it is equivalent to using the , operator:

	function union{ in seq1: Anything[0..*] ordered nonunique; in seq2: Anything[0..*] ordered nonunique;
		return : Anything[0..*] ordered nonunique = (seq1, seq2);
	}

So, unionResult is as expected.

The definition of intersection is

	function intersection{ in seq1: Anything[0..*] ordered nonunique; in seq2: Anything[0..*] ordered nonunique;
		return : Anything[0..*] ordered nonunique = seq1->select {in x; seq2->includes(x)};
	}

So, it selects the values in seq1, in order, including duplicates, that are also included inseq2 (regardless of duplicates in seq2). So intersectionResult is also as expected.

The definition of includesOnly is

	function includesOnly{ in seq1: Anything[0..*] nonunique; in seq2: Anything[0..*] nonunique;
		return : Boolean[1] = seq1->includes(seq2) and seq2->includes(seq1);
	}

And this is exactly how it is implement, by checking inclusion of each sequence in the other. The intent of includesOnly is to essentially provide a set-based equality check, as opposed to equals, which checks value-by-value equality in order.

One could possibly propose changes in how these functions are defined, but that would be a specification issue, not an implementation issue.

@seidewitz
Copy link
Member Author

I could not make an example to check the difference of == and === and therefore could not check the difference of same and equals. I tried the example below, but both eq2 and eq3 are false. Even if I tried bind ts1 = ts2;, they are false. But if I try timeslice ts2 = ts1;, both are true.

There currently is no difference in the implementation of == and === (or SequenceFunctions::equals and SequenceFunctions::same). These functions are the same, anyway, for data values. And the current evaluation implementation does no support the semantics of change over time, so it does not include the difference between them for occurrences, either.

Copy link
Member

@himi himi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@seidewitz thank you for confirming it. To be honest, union() seems confusing to me because it is actually concat(). But I understand it is intended. I think we need a proper documentation on these. Also I think we need unique() for set semantics and we can implement it with collect and reduce but the complexity will be O^2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants