Skip to content

Commit

Permalink
fix: pass optional arguments of memoized calls by name (#1095)
Browse files Browse the repository at this point in the history
Closes #1087

### Summary of Changes

Optional argument of memoized calls are now stored in a separate dict,
so they can be passed by name in the runner.
  • Loading branch information
lars-reimann authored Apr 24, 2024
1 parent 77a0c1f commit 39d9e5a
Show file tree
Hide file tree
Showing 19 changed files with 824 additions and 265 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const CODEGEN_PREFIX = '__gen_';

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { expandToNode, Generated } from 'langium/generate';

const CODEGEN_PREFIX = '__gen_';

export const eagerOr: UtilityFunction = {
name: `${CODEGEN_PREFIX}eager_or`,
code: expandToNode`
def ${CODEGEN_PREFIX}eager_or(left_operand: bool, right_operand: bool) -> bool:
return left_operand or right_operand
`,
};

export const eagerAnd: UtilityFunction = {
name: `${CODEGEN_PREFIX}eager_and`,
code: expandToNode`
def ${CODEGEN_PREFIX}eager_and(left_operand: bool, right_operand: bool) -> bool:
return left_operand and right_operand
`,
};

export const eagerElvis: UtilityFunction = {
name: `${CODEGEN_PREFIX}eager_elvis`,
code: expandToNode`
def ${CODEGEN_PREFIX}eager_elvis(left_operand: ${CODEGEN_PREFIX}T, right_operand: ${CODEGEN_PREFIX}T) -> ${CODEGEN_PREFIX}T:
return left_operand if left_operand is not None else right_operand
`,
typeVariables: [`${CODEGEN_PREFIX}T`],
};

export const nullSafeCall: UtilityFunction = {
name: `${CODEGEN_PREFIX}null_safe_call`,
code: expandToNode`
def ${CODEGEN_PREFIX}null_safe_call(receiver: Any, callable: Callable[[], ${CODEGEN_PREFIX}T]) -> ${CODEGEN_PREFIX}T | None:
return callable() if receiver is not None else None
`,
imports: [
{ importPath: 'typing', declarationName: 'Any' },
{ importPath: 'typing', declarationName: 'Callable' },
],
typeVariables: [`${CODEGEN_PREFIX}T`],
};

export const nullSafeIndexedAccess: UtilityFunction = {
name: `${CODEGEN_PREFIX}null_safe_indexed_access`,
code: expandToNode`
def ${CODEGEN_PREFIX}null_safe_indexed_access(receiver: Any, index: Any) -> ${CODEGEN_PREFIX}T | None:
return receiver[index] if receiver is not None else None
`,
imports: [{ importPath: 'typing', declarationName: 'Any' }],
typeVariables: [`${CODEGEN_PREFIX}T`],
};

export const nullSafeMemberAccess: UtilityFunction = {
name: `${CODEGEN_PREFIX}null_safe_member_access`,
code: expandToNode`
def ${CODEGEN_PREFIX}null_safe_member_access(receiver: Any, member_name: str) -> ${CODEGEN_PREFIX}T | None:
return getattr(receiver, member_name) if receiver is not None else None
`,
imports: [{ importPath: 'typing', declarationName: 'Any' }],
typeVariables: [`${CODEGEN_PREFIX}T`],
};

export interface UtilityFunction {
readonly name: string;
readonly code: Generated;
readonly imports?: ImportData[];
readonly typeVariables?: string[];
}

interface ImportData {
readonly importPath: string;
readonly declarationName?: string;
readonly alias?: string;
}
2 changes: 1 addition & 1 deletion packages/safe-ds-lang/src/language/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export * as commands from './communication/commands.js';
export * as rpc from './communication/rpc.js';

// Generation
export { CODEGEN_PREFIX } from './generation/safe-ds-python-generator.js';
export { CODEGEN_PREFIX } from './generation/python/constants.js';

// Dependencies
export const dependencies = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from './messages.js';
import { SourceMapConsumer } from 'source-map-js';
import { SafeDsAnnotations } from '../builtins/safe-ds-annotations.js';
import { SafeDsPythonGenerator } from '../generation/safe-ds-python-generator.js';
import { SafeDsPythonGenerator } from '../generation/python/safe-ds-python-generator.js';
import { isSdsModule, isSdsPipeline, isSdsPlaceholder } from '../generated/ast.js';
import { SafeDsLogger, SafeDsMessagingProvider } from '../communication/safe-ds-messaging-provider.js';
import crypto from 'crypto';
Expand Down
2 changes: 1 addition & 1 deletion packages/safe-ds-lang/src/language/safe-ds-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { SafeDsCommentProvider } from './documentation/safe-ds-comment-provider.
import { SafeDsDocumentationProvider } from './documentation/safe-ds-documentation-provider.js';
import { SafeDsCallGraphComputer } from './flow/safe-ds-call-graph-computer.js';
import { SafeDsGeneratedModule, SafeDsGeneratedSharedModule, SafeDsLanguageMetaData } from './generated/module.js';
import { SafeDsPythonGenerator } from './generation/safe-ds-python-generator.js';
import { SafeDsPythonGenerator } from './generation/python/safe-ds-python-generator.js';
import { SafeDsValueConverter } from './grammar/safe-ds-value-converter.js';
import { SafeDsNodeMapper } from './helpers/safe-ds-node-mapper.js';
import { SafeDsCallHierarchyProvider } from './lsp/safe-ds-call-hierarchy-provider.js';
Expand Down
2 changes: 1 addition & 1 deletion packages/safe-ds-lang/src/language/validation/names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
SdsSegment,
SdsTypeParameter,
} from '../generated/ast.js';
import { CODEGEN_PREFIX } from '../generation/safe-ds-python-generator.js';
import { CODEGEN_PREFIX } from '../generation/python/constants.js';
import { isInDevFile, isInPipelineFile, isInStubFile } from '../helpers/fileExtensions.js';
import {
getClassMembers,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,47 +22,155 @@ def segment_a(a):
# Pipelines --------------------------------------------------------------------

def test():
f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.g", lambda *_ : g(1, param2=2), [1, 2], []))
f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.g", lambda *_ : g(2, param2=1), [2, 1], []))
f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.h", lambda *_ : h(1, param_2=2), [1, 2], []))
f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.h", lambda *_ : h(2, param_2=1), [2, 1], []))
f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.h", h, [2, 0], []))
f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.g",
g,
[1],
{"param2": 2},
[]
))
f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.g",
g,
[2],
{"param2": 1},
[]
))
f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.h",
h,
[1],
{"param_2": 2},
[]
))
f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.h",
h,
[2],
{"param_2": 1},
[]
))
f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.h",
h,
[2],
{"param_2": 0},
[]
))
'abc'.i()
'abc'.j(123)
k(456, 1.23)
__gen_null_safe_call(f, lambda: f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.g", lambda *_ : g(1, param2=2), [1, 2], [])))
__gen_null_safe_call(f, lambda: f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.g", lambda *_ : g(2, param2=1), [2, 1], [])))
__gen_null_safe_call(f, lambda: f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.h", lambda *_ : h(1, param_2=2), [1, 2], [])))
__gen_null_safe_call(f, lambda: f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.h", lambda *_ : h(2, param_2=1), [2, 1], [])))
__gen_null_safe_call(f, lambda: f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.h", h, [2, 0], [])))
__gen_null_safe_call(f, lambda: f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.g",
g,
[1],
{"param2": 2},
[]
)))
__gen_null_safe_call(f, lambda: f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.g",
g,
[2],
{"param2": 1},
[]
)))
__gen_null_safe_call(f, lambda: f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.h",
h,
[1],
{"param_2": 2},
[]
)))
__gen_null_safe_call(f, lambda: f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.h",
h,
[2],
{"param_2": 1},
[]
)))
__gen_null_safe_call(f, lambda: f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.h",
h,
[2],
{"param_2": 0},
[]
)))
__gen_null_safe_call(i, lambda: 'abc'.i())
__gen_null_safe_call(j, lambda: 'abc'.j(123))
__gen_null_safe_call(k, lambda: k(456, 1.23))
f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.readFile", readFile, [], [safeds_runner.file_mtime('a.txt')]))
f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.readFile",
readFile,
[],
{},
[safeds_runner.file_mtime('a.txt')]
))
def __gen_lambda_0(a):
return segment_a(a)
f(l(__gen_lambda_0))
def __gen_lambda_1(a):
return (3) * (segment_a(a))
f(l(__gen_lambda_1))
def __gen_lambda_2(a):
return safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.m", m, [(3) * (segment_a(a))], [])
return safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.m",
m,
[(3) * (segment_a(a))],
{},
[]
)
f(l(__gen_lambda_2))
def __gen_lambda_3(a):
return (3) * (safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.m", m, [safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.m", m, [(3) * (segment_a(a))], [])], []))
return (3) * (safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.m",
m,
[safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.m",
m,
[(3) * (segment_a(a))],
{},
[]
)],
{},
[]
))
f(l(__gen_lambda_3))
def __gen_lambda_4(a):
__gen_block_lambda_result_result = segment_a(a)
return __gen_block_lambda_result_result
f(l(__gen_lambda_4))
def __gen_lambda_5(a):
__gen_block_lambda_result_result = safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.m", m, [segment_a(a)], [])
__gen_block_lambda_result_result = safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.m",
m,
[segment_a(a)],
{},
[]
)
return __gen_block_lambda_result_result
f(l(__gen_lambda_5))
def __gen_lambda_6(a):
return (3) * (a)
f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.l", l, [__gen_lambda_6], []))
f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.l",
l,
[__gen_lambda_6],
{},
[]
))
def __gen_lambda_7(a):
__gen_block_lambda_result_result = (3) * (safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.m", m, [a], []))
__gen_block_lambda_result_result = (3) * (safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.m",
m,
[a],
{},
[]
))
return __gen_block_lambda_result_result
f(safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.main.l", l, [__gen_lambda_7], []))
f(safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.main.l",
l,
[__gen_lambda_7],
{},
[]
))

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 @@ -6,5 +6,11 @@
# Pipelines --------------------------------------------------------------------

def test():
a = safeds_runner.memoized_static_call("tests.generator.runnerIntegration.expressions.calls.ofClasses.MyClass", MyClass, [0], [])
a = safeds_runner.memoized_static_call(
"tests.generator.runnerIntegration.expressions.calls.ofClasses.MyClass",
MyClass,
[0],
{},
[]
)
safeds_runner.save_placeholder('a', a)

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

Loading

0 comments on commit 39d9e5a

Please sign in to comment.