Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: output statement #1262

Merged
merged 22 commits into from
Nov 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d95d8a7
feat: update grammar
lars-reimann Nov 9, 2024
de68235
feat: update VS Code syntaxes
lars-reimann Nov 9, 2024
2caf8a4
feat: update formatter
lars-reimann Nov 9, 2024
c784767
feat: update warning if statement does nothing
lars-reimann Nov 9, 2024
8c2f033
feat: error if output statement is used outside a pipeline
lars-reimann Nov 9, 2024
9a9dd84
feat: error if expression in output statement produces no values
lars-reimann Nov 9, 2024
335bf72
feat: update purity computer and slicer
lars-reimann Nov 9, 2024
bbe3a5d
refactor: rename method of slicer
lars-reimann Nov 9, 2024
cc945c6
feat: update code lens provider
lars-reimann Nov 9, 2024
accf7fe
feat: update command handlers (part 1)
lars-reimann Nov 9, 2024
1b05205
feat: remove command "refresh webview"
lars-reimann Nov 9, 2024
9ab9ddf
refactor: handle "safeds.exploreTable" command in server
lars-reimann Nov 9, 2024
a6d56b8
feat: handle output statements in slicer
lars-reimann Nov 9, 2024
e34dd4b
feat: pass list of target statements to generator
lars-reimann Nov 9, 2024
3655679
feat: shorter text for code lens
lars-reimann Nov 9, 2024
b71a569
refactor: remove index parameter
lars-reimann Nov 9, 2024
be4e1d9
feat: update code generator
lars-reimann Nov 9, 2024
e66cff6
refactor: extract method to get value names
lars-reimann Nov 10, 2024
127a9c3
feat: update EDA tool
lars-reimann Nov 10, 2024
a75f6ed
docs: update documentation
lars-reimann Nov 10, 2024
732515f
test: fix failing test
lars-reimann Nov 10, 2024
4304a47
style: fix linter errors
lars-reimann Nov 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions docs/api/safeds/data/tabular/containers/Column.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pipeline example {
*/
attr type: DataType

/*
/**
* Return the distinct values in the column.
*
* @param ignoreMissingValues Whether to ignore missing values.
Expand Down Expand Up @@ -915,17 +915,29 @@ pipeline example {

## <code class="doc-symbol doc-symbol-function"></code> `getDistinctValues` {#safeds.data.tabular.containers.Column.getDistinctValues data-toc-label='[function] getDistinctValues'}

Return the distinct values in the column.

**Parameters:**

| Name | Type | Description | Default |
|------|------|-------------|---------|
| `ignoreMissingValues` | [`Boolean`][safeds.lang.Boolean] | - | `#!sds true` |
| `ignoreMissingValues` | [`Boolean`][safeds.lang.Boolean] | Whether to ignore missing values. | `#!sds true` |

**Results:**

| Name | Type | Description |
|------|------|-------------|
| `distinctValues` | [`List<T?>`][safeds.lang.List] | - |
| `distinctValues` | [`List<T?>`][safeds.lang.List] | The distinct values in the column. |

**Examples:**

```sds hl_lines="3"
pipeline example {
val column = Column("test", [1, 2, 3, 2]);
val result = column.getDistinctValues();
// [1, 2, 3]
}
```

??? quote "Stub code in `Column.sdsstub`"

Expand Down
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ nav:
- pipeline-language/statements/README.md
- Expression Statements: pipeline-language/statements/expression-statements.md
- Assignments: pipeline-language/statements/assignments.md
- Output Statements: pipeline-language/statements/output-statements.md
- Expressions:
- pipeline-language/expressions/README.md
- Literals: pipeline-language/expressions/literals.md
Expand Down
12 changes: 7 additions & 5 deletions docs/pipeline-language/statements/README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# Statements

Statements are used to run some action. Safe-DS has only two type of statements:
Statements are used to run some action. Safe-DS only has three type of statements:

- [Expression statements][expression-statements] evaluate an [expression][expressions] and discard any results. They are
only useful if the expression has side effects, such as writing to a file.
- [Assignments][assignments] also evaluate an [expression][expressions], but then store results in
[placeholders][placeholders]. This allows reusing the results multiple times without having to recompute them.
- [Output statements][output-statements] evaluate an [expression][expressions] as well, and provide options to inspect
its results. Unlike when using assignments, the result cannot be reused.


[assignments]: ./assignments.md
[expression-statements]: ./expression-statements.md
[assignments]: assignments.md
[expression-statements]: expression-statements.md
[output-statements]: output-statements.md
[expressions]: ../expressions/README.md
[placeholders]: ./assignments.md#declaring-placeholders
[placeholders]: assignments.md#declaring-placeholders
6 changes: 4 additions & 2 deletions docs/pipeline-language/statements/assignments.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ This assignment to a placeholder has the following syntactic elements:
- The name of the placeholder, here `titanic`. It can be any combination of lower- and uppercase letters, underscores,
and numbers, as long as it does not start with a number.
- An `#!sds =` sign.
- The expression to evaluate (right-hand side).
- The [expression][expressions] to evaluate (right-hand side).
- A semicolon at the end.

??? info "Name convention"

Use `#!sds lowerCamelCase` for the name of the placeholder. You may prefix the name of an unused placeholder with an
underscore (`_`) to indicate that it is intentionally unused, e.g. to
[inspect its value](#inspecting-placeholder-values-in-vs-code). This disables the "unused" warning.
[inspect its value](#inspecting-placeholder-values-in-vs-code). This disables the "unused" warning. For value
inspection, also consider using an [output statement][output-statements] instead.

### References to Placeholder

Expand Down Expand Up @@ -104,6 +105,7 @@ such cases.
[expressions]: ../expressions/README.md
[expression-statements]: expression-statements.md
[installation]: ../../getting-started/installation.md
[output-statements]: output-statements.md
[references]: ../expressions/references.md#references
[runner]: https://github.com/Safe-DS/Runner
[results]: ../segments.md#results
26 changes: 26 additions & 0 deletions docs/pipeline-language/statements/output-statements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Output Statements

Output statements are used to evaluate an expression and inspect its results. Unlike when using assignments, the results
cannot be reused. However, it is also not necessary to think of unique names for placeholders, which saves time and
keeps the namespace clean.

The next snippet shows how the singular result of an expression (the loaded
[`Table`][safeds.data.tabular.containers.Table]) can be inspected:

```sds
out Table.fromCsvFile("titanic.csv");
```

This output statement has the following syntactic elements:

- The keyword `#!sds out`, which indicates that we want to inspect the results of an expression.
- The expression to evaluate.
- A semicolon at the end.

Inspecting values requires a working installation of the [Safe-DS Runner][runner]. Follow the instructions in the
[installation guide][installation] to install it. Afterward, you can inspect values of various types via
_code lenses_ in the editor, as explained for [assignments][value-inspection].

[installation]: ../../getting-started/installation.md
[runner]: https://github.com/Safe-DS/Runner
[value-inspection]: assignments.md#inspecting-placeholder-values-in-vs-code
2 changes: 1 addition & 1 deletion packages/safe-ds-cli/src/cli/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const generate = async (fsPaths: string[], options: GenerateOptions): Pro
const generatedFiles = services.generation.PythonGenerator.generate(document, {
destination: URI.file(path.resolve(options.out)),
createSourceMaps: options.sourcemaps,
targetPlaceholders: undefined,
targetStatements: undefined,
disableRunnerIntegration: false,
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const COMMAND_EXPLORE_TABLE = 'safe-ds.exploreTable';
export const COMMAND_PRINT_VALUE = 'safe-ds.printValue';
export const COMMAND_RUN_PIPELINE = 'safe-ds.runPipeline';
export const COMMAND_SHOW_IMAGE = 'safe-ds.showImage';
34 changes: 34 additions & 0 deletions packages/safe-ds-lang/src/language/communication/rpc.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { MessageDirection, NotificationType0, RequestType0 } from 'vscode-languageserver';
import { NotificationType } from 'vscode-languageserver-protocol';
import { UUID } from 'node:crypto';

export namespace InstallRunnerNotification {
export const method = 'runner/install' as const;
Expand Down Expand Up @@ -32,6 +33,39 @@ export namespace UpdateRunnerNotification {
export const type = new NotificationType0(method);
}

export namespace ExploreTableNotification {
export const method = 'runner/exploreTable' as const;
export const messageDirection = MessageDirection.serverToClient;
export const type = new NotificationType<ExploreTableNotification>(method);
}

export interface ExploreTableNotification {
/**
* The ID of the pipeline execution.
*/
pipelineExecutionId: UUID;

/**
* The URI of the pipeline document.
*/
uri: string;

/**
* The name of the pipeline.
*/
pipelineName: string;

/**
* The end offset of the pipeline node. This is used to add more code to the pipeline by the EDA tool.
*/
pipelineNodeEndOffset: number;

/**
* The name of the placeholder containing the table.
*/
placeholderName: string;
}

export namespace ShowImageNotification {
export const method = 'runner/showImage' as const;
export const messageDirection = MessageDirection.serverToClient;
Expand Down
27 changes: 16 additions & 11 deletions packages/safe-ds-lang/src/language/flow/safe-ds-slicer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,19 @@ export class SafeDsSlicer {
/**
* Computes the subset of the given statements that are needed to calculate the target placeholders.
*/
computeBackwardSlice(statements: SdsStatement[], targets: SdsPlaceholder[]): SdsStatement[] {
const aggregator = new BackwardSliceAggregator(this.purityComputer, targets);
computeBackwardSliceToTargets(statements: SdsStatement[], targets: SdsStatement[]): SdsStatement[] {
const aggregator = new BackwardSliceAggregator(this.purityComputer);

for (const statement of statements.reverse()) {
// Keep if it declares a target
if (
// Keep if it is a target
if (targets.includes(statement)) {
aggregator.addStatement(statement);
}

// Keep if it declares a referenced placeholder
else if (
isSdsAssignment(statement) &&
getAssignees(statement).some((it) => isSdsPlaceholder(it) && aggregator.targets.has(it))
getAssignees(statement).some((it) => isSdsPlaceholder(it) && aggregator.referencedPlaceholders.has(it))
) {
aggregator.addStatement(statement);
}
Expand All @@ -49,32 +54,32 @@ class BackwardSliceAggregator {
private readonly purityComputer: SafeDsPurityComputer;

/**
* The statements that are needed to calculate the target placeholders.
* The statements that are needed to calculate the target statements.
*/
readonly statements: SdsStatement[] = [];

/**
* The target placeholders that should be calculated.
* The placeholders that are needed to calculate the target statements.
*/
readonly targets: Set<SdsPlaceholder>;
readonly referencedPlaceholders: Set<SdsPlaceholder>;

/**
* The impurity reasons of the collected statements.
*/
readonly impurityReasons: ImpurityReason[] = [];

constructor(purityComputer: SafeDsPurityComputer, initialTargets: SdsPlaceholder[]) {
constructor(purityComputer: SafeDsPurityComputer) {
this.purityComputer = purityComputer;

this.targets = new Set(initialTargets);
this.referencedPlaceholders = new Set();
}

addStatement(statement: SdsStatement): void {
this.statements.unshift(statement);

// Remember all referenced placeholders
this.getReferencedPlaceholders(statement).forEach((it) => {
this.targets.add(it);
this.referencedPlaceholders.add(it);
});

// Remember all impurity reasons
Expand Down
Loading