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: python server (runtime) #726

Merged
merged 34 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
80e65c8
feat: Added "safe-ds.runner.command" setting
WinPlay02 Nov 2, 2023
5b71c06
Merge branch 'main' of https://github.com/Safe-DS/DSL into runtime-se…
WinPlay02 Nov 2, 2023
76de0cb
feat: start python server and connect via ws
WinPlay02 Nov 5, 2023
a4acd4c
feat: start python server and connect via ws part 2
WinPlay02 Nov 6, 2023
4b011bf
Merge branch 'main' into runtime-server
WinPlay02 Nov 6, 2023
4fb1f01
feat: actual running of pipelines
WinPlay02 Nov 16, 2023
5848430
Merge branch 'main' of https://github.com/Safe-DS/DSL into runtime-se…
WinPlay02 Nov 16, 2023
ec68d51
feat: use common output channel for safe-ds
WinPlay02 Nov 20, 2023
ef3c7b8
Merge branch 'main' of https://github.com/Safe-DS/DSL into runtime-se…
WinPlay02 Nov 20, 2023
ae40a37
feat: print safe-ds stacktrace on error
WinPlay02 Nov 20, 2023
206e932
Merge branch 'main' of https://github.com/Safe-DS/DSL into runtime-se…
WinPlay02 Nov 20, 2023
a12e64a
misc: copy mappings.wasm to dist (from source-maps)
WinPlay02 Nov 20, 2023
471d0eb
Merge branch 'main' into runtime-server
WinPlay02 Nov 22, 2023
2322a33
feat: use actually random execution ids
WinPlay02 Nov 24, 2023
cf23b4a
Merge branch 'runtime-server' of https://github.com/Safe-DS/DSL into …
WinPlay02 Nov 24, 2023
e0965ef
Merge branch 'main' of https://github.com/Safe-DS/DSL into runtime-se…
WinPlay02 Nov 24, 2023
4d04f51
style: apply automated linter fixes
megalinter-bot Nov 24, 2023
fed02b5
Merge branch 'main' into runtime-server
WinPlay02 Nov 27, 2023
3109e86
feat: save placeholders in runner
WinPlay02 Nov 27, 2023
44dd489
Merge branch 'runtime-server' of https://github.com/Safe-DS/DSL into …
WinPlay02 Nov 27, 2023
b2fd9a2
feat: handle module path for program execution requests
WinPlay02 Nov 28, 2023
0229aed
style: apply automated linter fixes
megalinter-bot Nov 28, 2023
9f78034
Merge branch 'main' into runtime-server
WinPlay02 Nov 30, 2023
cb860f9
chore: update default runner command
lars-reimann Dec 1, 2023
4ec4bd9
misc: address review suggestions
WinPlay02 Dec 4, 2023
31a3317
Merge branch 'runtime-server' of https://github.com/Safe-DS/DSL into …
WinPlay02 Dec 4, 2023
23be8a3
style: apply automated linter fixes
megalinter-bot Dec 4, 2023
27ddc7e
feat: add function to remove previously registered python server mess…
WinPlay02 Dec 4, 2023
9296dfc
Merge branch 'runtime-server' of https://github.com/Safe-DS/DSL into …
WinPlay02 Dec 4, 2023
f7cced7
feat: use graceful shutdown with timeout
WinPlay02 Dec 5, 2023
48eef4f
style: apply automated linter fixes
megalinter-bot Dec 5, 2023
113ac3d
feat: use relative module paths for generating the pipeline entry point
WinPlay02 Dec 5, 2023
cc503f1
Merge branch 'runtime-server' of https://github.com/Safe-DS/DSL into …
WinPlay02 Dec 5, 2023
cc37d6c
refactor: add await
lars-reimann Dec 5, 2023
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
2 changes: 1 addition & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module.exports = {
},
overrides: [
{
files: ['packages/safe-ds-cli/src/**'],
files: ['packages/safe-ds-cli/src/**', 'packages/safe-ds-vscode/src/extension/output.ts'],
rules: {
'no-console': 'off',
},
Expand Down
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"args": ["--extensionDevelopmentPath=${workspaceFolder}/packages/safe-ds-vscode"],
"preLaunchTask": "npm: build",
"request": "launch",
"type": "extensionHost"
"type": "extensionHost",
"sourceMaps": true
}
]
}
34 changes: 33 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ const BLOCK_LAMBDA_RESULT_PREFIX = `${CODEGEN_PREFIX}block_lambda_result_`;
const YIELD_PREFIX = `${CODEGEN_PREFIX}yield_`;

const RUNNER_CODEGEN_PACKAGE = 'safeds_runner.codegen';
const RUNNER_SERVER_PIPELINE_MANAGER_PACKAGE = 'safeds_runner.server.pipeline_manager';
const PYTHON_INDENT = ' ';

const NLNL = new CompositeGeneratorNode(NL, NL);
Expand Down Expand Up @@ -138,7 +139,7 @@ export class SafeDsPythonGenerator {
);
}
generatedFiles.set(pythonOutputPath, text);
for (const pipeline of streamAllContents(node).filter(isSdsPipeline)) {
for (const pipeline of getModuleMembers(node).filter(isSdsPipeline)) {
const entryPointFilename = `${path.join(
parentDirectoryPath,
`${this.formatGeneratedFileName(name)}_${this.getPythonNameOrDefault(pipeline)}`,
Expand Down Expand Up @@ -313,7 +314,7 @@ export class SafeDsPythonGenerator {
}

private generatePipeline(pipeline: SdsPipeline, importSet: Map<String, ImportData>): CompositeGeneratorNode {
const infoFrame = new GenerationInfoFrame(importSet);
const infoFrame = new GenerationInfoFrame(importSet, true);
return expandTracedToNode(pipeline)`def ${traceToNode(
pipeline,
'name',
Expand Down Expand Up @@ -358,19 +359,31 @@ export class SafeDsPythonGenerator {
}
}

private generateBlock(block: SdsBlock, frame: GenerationInfoFrame): CompositeGeneratorNode {
private generateBlock(
block: SdsBlock,
frame: GenerationInfoFrame,
generateLambda: boolean = false,
): CompositeGeneratorNode {
let statements = getStatements(block).filter((stmt) => this.purityComputer.statementDoesSomething(stmt));
if (statements.length === 0) {
return traceToNode(block)('pass');
}
return joinTracedToNode(block, 'statements')(statements, (stmt) => this.generateStatement(stmt, frame), {
separator: NL,
})!;
return joinTracedToNode(block, 'statements')(
statements,
(stmt) => this.generateStatement(stmt, frame, generateLambda),
{
separator: NL,
},
)!;
}

private generateStatement(statement: SdsStatement, frame: GenerationInfoFrame): CompositeGeneratorNode {
private generateStatement(
statement: SdsStatement,
frame: GenerationInfoFrame,
generateLambda: boolean,
): CompositeGeneratorNode {
if (isSdsAssignment(statement)) {
return traceToNode(statement)(this.generateAssignment(statement, frame));
return traceToNode(statement)(this.generateAssignment(statement, frame, generateLambda));
} else if (isSdsExpressionStatement(statement)) {
const blockLambdaCode: CompositeGeneratorNode[] = [];
for (const lambda of streamAllContents(statement.expression).filter(isSdsBlockLambda)) {
Expand All @@ -386,28 +399,49 @@ export class SafeDsPythonGenerator {
throw new Error(`Unknown SdsStatement: ${statement}`);
}

private generateAssignment(assignment: SdsAssignment, frame: GenerationInfoFrame): CompositeGeneratorNode {
private generateAssignment(
assignment: SdsAssignment,
frame: GenerationInfoFrame,
generateLambda: boolean,
): CompositeGeneratorNode {
const requiredAssignees = isSdsCall(assignment.expression)
? getAbstractResults(this.nodeMapper.callToCallable(assignment.expression)).length
: /* c8 ignore next */
1;
const assignees = getAssignees(assignment);
if (assignees.some((value) => !isSdsWildcard(value))) {
const actualAssignees = assignees.map(this.generateAssignee);
let assignmentStatements = [];
if (requiredAssignees === actualAssignees.length) {
return expandTracedToNode(assignment)`${joinToNode(
actualAssignees,
(actualAssignee) => actualAssignee,
{ separator: ', ' },
)} = ${this.generateExpression(assignment.expression!, frame)}`;
assignmentStatements.push(
expandTracedToNode(assignment)`${joinToNode(actualAssignees, (actualAssignee) => actualAssignee, {
separator: ', ',
})} = ${this.generateExpression(assignment.expression!, frame)}`,
);
} else {
// Add wildcards to match given results
return expandTracedToNode(assignment)`${joinToNode(
actualAssignees.concat(Array(requiredAssignees - actualAssignees.length).fill('_')),
(actualAssignee) => actualAssignee,
{ separator: ', ' },
)} = ${this.generateExpression(assignment.expression!, frame)}`;
assignmentStatements.push(
expandTracedToNode(assignment)`${joinToNode(
actualAssignees.concat(Array(requiredAssignees - actualAssignees.length).fill('_')),
(actualAssignee) => actualAssignee,
{ separator: ', ' },
)} = ${this.generateExpression(assignment.expression!, frame)}`,
);
}
if (frame.isInsidePipeline() && !generateLambda) {
for (const savableAssignment of assignees.filter(isSdsPlaceholder)) {
// should always be SdsPlaceholder
frame.addImport({ importPath: RUNNER_SERVER_PIPELINE_MANAGER_PACKAGE });
assignmentStatements.push(
expandTracedToNode(
savableAssignment,
)`${RUNNER_SERVER_PIPELINE_MANAGER_PACKAGE}.runner_save_placeholder('${savableAssignment.name}', ${savableAssignment.name})`,
);
}
}
return joinTracedToNode(assignment)(assignmentStatements, (stmt) => stmt, {
separator: NL,
})!;
} else {
return traceToNode(assignment)(this.generateExpression(assignment.expression!, frame));
}
Expand Down Expand Up @@ -435,7 +469,7 @@ export class SafeDsPythonGenerator {

private generateBlockLambda(blockLambda: SdsBlockLambda, frame: GenerationInfoFrame): CompositeGeneratorNode {
const results = streamBlockLambdaResults(blockLambda).toArray();
let lambdaBlock = this.generateBlock(blockLambda.body, frame);
let lambdaBlock = this.generateBlock(blockLambda.body, frame, true);
WinPlay02 marked this conversation as resolved.
Show resolved Hide resolved
if (results.length !== 0) {
lambdaBlock.appendNewLine();
lambdaBlock.append(
Expand Down Expand Up @@ -773,10 +807,12 @@ interface ImportData {
class GenerationInfoFrame {
private readonly blockLambdaManager: IdManager<SdsBlockLambda>;
private readonly importSet: Map<String, ImportData>;
private readonly insidePipeline: boolean;

constructor(importSet: Map<String, ImportData> = new Map<String, ImportData>()) {
constructor(importSet: Map<String, ImportData> = new Map<String, ImportData>(), insidePipeline: boolean = false) {
this.blockLambdaManager = new IdManager<SdsBlockLambda>();
this.importSet = importSet;
this.insidePipeline = insidePipeline;
}

addImport(importData: ImportData | undefined) {
Expand All @@ -791,6 +827,10 @@ class GenerationInfoFrame {
getUniqueLambdaBlockName(lambda: SdsBlockLambda): string {
return `${BLOCK_LAMBDA_PREFIX}${this.blockLambdaManager.assignId(lambda)}`;
}

isInsidePipeline(): boolean {
return this.insidePipeline;
}
WinPlay02 marked this conversation as resolved.
Show resolved Hide resolved
}

export interface GenerateOptions {
Expand Down
1 change: 1 addition & 0 deletions packages/safe-ds-lang/src/language/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * as ast from './generated/ast.js';
export { SafeDsLanguageMetaData } from './generated/module.js';
export { startLanguageServer } from './main.js';
export { createSafeDsServices, createSafeDsServicesWithBuiltins } from './safe-ds-module.js';
export { SAFE_DS_FILE_EXTENSIONS } from './helpers/fileExtensions.js';
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ pipeline testPipeline {
val x = g();
f1(a);
f1(x);
val l, val m, val n = g();
f1(l);
f1(m);
f1(n);

f2(() {
_, _ ,_ = g();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Imports ----------------------------------------------------------------------

import safeds_runner.server.pipeline_manager

# Segments ---------------------------------------------------------------------

def testSegment():
Expand All @@ -13,9 +17,18 @@ def testSegment():
def testPipeline():
g()
a, _, _ = g()
safeds_runner.server.pipeline_manager.runner_save_placeholder('a', a)
x, _, _ = g()
safeds_runner.server.pipeline_manager.runner_save_placeholder('x', x)
f1(a)
f1(x)
l, m, n = g()
safeds_runner.server.pipeline_manager.runner_save_placeholder('l', l)
safeds_runner.server.pipeline_manager.runner_save_placeholder('m', m)
safeds_runner.server.pipeline_manager.runner_save_placeholder('n', n)
f1(l)
f1(m)
f1(n)
def __gen_block_lambda_0():
g()
a, _, __gen_block_lambda_result_c = g()
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions packages/safe-ds-vscode/esbuild.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ const plugins = [
},
watch,
}),
copy({
assets: {
from: ['../../node_modules/source-map/lib/mappings.wasm'],
to: ['./extension']
}
}
),
{
name: 'watch-plugin',
setup(build) {
Expand Down
27 changes: 26 additions & 1 deletion packages/safe-ds-vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@
"configuration": {
"title": "Safe-DS",
"properties": {
"safe-ds.runner.command": {
"description": "Command to start the Safe-DS runner",
"type": "string",
"default": "safe-ds-runner"
},
"safe-ds.validation.codeStyle": {
"type": "boolean",
"default": true,
Expand Down Expand Up @@ -112,6 +117,23 @@
"files.trimTrailingWhitespace": true
}
},
"menus": {
"editor/title/run": [
{
"command": "extension.safe-ds.runPipelineFile",
"when": "resourceLangId == safe-ds",
"group": "navigation@1"
}
]
},
"commands": [
{
"command": "extension.safe-ds.runPipelineFile",
"title": "Run Pipeline",
"category": "Safe-DS",
"icon": "$(play)"
}
],
"snippets": [
{
"language": "safe-ds",
Expand All @@ -131,11 +153,14 @@
"deploy": "vsce publish"
},
"dependencies": {
"vscode-languageclient": "^9.0.1"
"source-map": "^0.7.4",
"vscode-languageclient": "^9.0.1",
"ws": "^8.14.2"
},
"devDependencies": {
"@types/node": "^18.18.12",
"@types/vscode": "^1.84.2",
"@types/ws": "^8.5.8",
"@vscode/vsce": "^2.22.0",
"esbuild": "^0.19.8",
"esbuild-plugin-copy": "^2.1.1"
Expand Down
Loading