-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cause i wanted to think about something different
- Loading branch information
1 parent
4313a35
commit f6d2d98
Showing
5 changed files
with
293 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id'; | ||
import type { | ||
FlowrSearchElement, | ||
FlowrSearchElements, | ||
FlowrSearchGeneratorNode, FlowrSearchGetFilters, | ||
FlowrSearchInput, FlowrSearchTransformerNode | ||
} from './flowr-search'; | ||
import type { Pipeline } from '../core/steps/pipeline/pipeline'; | ||
import type { FlowrFilterExpression } from './flowr-search-filters'; | ||
import type { NoInfo } from '../r-bridge/lang-4.x/ast/model/model'; | ||
|
||
|
||
export type FlowrGenerator<P extends Pipeline> = Record<string, (input: FlowrSearchInput<P>) => FlowrSearchElements> | ||
|
||
export const FlowrSearchGenerator = { | ||
all(): FlowrSearchBuilder<NoInfo> { | ||
return new FlowrSearchBuilder({ type: 'generator', name: 'all', args: undefined }); | ||
}, | ||
/** | ||
* TODO TODO TODO | ||
*/ | ||
get(filter: FlowrSearchGetFilters): FlowrSearchBuilder<NoInfo> { | ||
return new FlowrSearchBuilder({ type: 'generator', name: 'get', args: filter }); | ||
}, | ||
/** | ||
* Short form of {@link get} with only the | ||
* {@link FlowrSearchGetFilters#line|line} and {@link FlowrSearchGetFilters#column|column} filters: | ||
* `get({line, column})`. | ||
*/ | ||
loc(line?: number, column?: number) { | ||
return FlowrSearchGenerator.get({ line, column }); | ||
}, | ||
/** | ||
* Short form of {@link get} with only the {@link FlowrSearchGetFilters#name|name} filter: | ||
* `get({name})`. | ||
*/ | ||
var(name: string) { | ||
return FlowrSearchGenerator.get({ name }); | ||
}, | ||
/** | ||
* Short form of {@link get} with only the {@link FlowrSearchGetFilters#id|id} filter: | ||
* `get({id})`. | ||
*/ | ||
id(id: NodeId) { | ||
return FlowrSearchGenerator.get({ id }); | ||
} | ||
} as const; | ||
|
||
export type FlowrSearchBuilderType<Info = NoInfo, ElementType = FlowrSearchElements<Info, FlowrSearchElement<Info>[]>> = FlowrSearchBuilder<Info, ElementType>; | ||
|
||
class FlowrSearchBuilder<Info, ElementType = FlowrSearchElements<Info, FlowrSearchElement<Info>[]>> { | ||
private generator: FlowrSearchGeneratorNode; | ||
private search: FlowrSearchTransformerNode[] = []; | ||
|
||
constructor(generator: FlowrSearchGeneratorNode) { | ||
this.generator = generator; | ||
} | ||
|
||
/** | ||
* TODO | ||
* | ||
* As filter does not change the type of any contained elements, we can return the same type for type safety checks. | ||
*/ | ||
filter(filter: FlowrFilterExpression): this { | ||
this.search.push({ type: 'transformer', name: 'filter', args: { filter: filter } }); | ||
return this; | ||
} | ||
|
||
/** | ||
* first either returns the first element of the search or nothing, if no elements are present. | ||
*/ | ||
first(): FlowrSearchBuilder<Info, [FlowrSearchElement<Info>] | []> { | ||
this.search.push({ type: 'transformer', name: 'first', args: undefined }); | ||
return this as unknown as FlowrSearchBuilder<Info, [FlowrSearchElement<Info>] | []>; | ||
} | ||
|
||
/** | ||
* last either returns the last element of the search or nothing, if no elements are present. | ||
*/ | ||
last(): FlowrSearchBuilder<Info, [FlowrSearchElement<Info>] | []> { | ||
this.search.push({ type: 'transformer', name: 'last', args: undefined }); | ||
return this as unknown as FlowrSearchBuilder<Info, [FlowrSearchElement<Info>] | []>; | ||
} | ||
/** | ||
* index returns the element at the given index if it exists | ||
*/ | ||
index(index: number): FlowrSearchBuilder<Info, [FlowrSearchElement<Info>] | []> { | ||
this.search.push({ type: 'transformer', name: 'index', args: { index } }); | ||
return this as unknown as FlowrSearchBuilder<Info, [FlowrSearchElement<Info>] | []>; | ||
} | ||
/** | ||
* tail returns all elements of the search except the first one. | ||
*/ | ||
tail(): this { | ||
this.search.push({ type: 'transformer', name: 'tail', args: undefined }); | ||
return this; | ||
} | ||
|
||
/** | ||
* take returns the first `count` elements of the search. | ||
*/ | ||
take(count: number): this { | ||
this.search.push({ type: 'transformer', name: 'take', args: { count } }); | ||
return this; | ||
} | ||
|
||
/** | ||
* skip returns all elements of the search except the first `count` ones. | ||
*/ | ||
skip(count: number): this { | ||
this.search.push({ type: 'transformer', name: 'skip', args: { count } }); | ||
return this; | ||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
|
||
|
||
import type { RType } from '../r-bridge/lang-4.x/ast/model/type'; | ||
import type { VertexType } from '../dataflow/graph/vertex'; | ||
|
||
export type FlowrFilterName = keyof typeof FlowrFilters; | ||
|
||
export enum FlowrFilter { | ||
|
||
} | ||
|
||
export const FlowrFilters = { | ||
|
||
} as const; | ||
|
||
|
||
type ValidFilterTypes = FlowrFilterName | RType | VertexType; | ||
/** | ||
* By default, we provide filter for every {@link RType} and {@link VertexType}. | ||
*/ | ||
export type FlowrFilterExpression = FlowrFilterCombinator | ValidFilterTypes; | ||
|
||
interface BooleanBinaryNode<Composite> { | ||
readonly type: 'and' | 'or' | 'xor'; | ||
readonly left: Composite; | ||
readonly right: Composite; | ||
} | ||
interface BooleanUnaryNode<Composite> { | ||
readonly type: 'not'; | ||
readonly operand: Composite; | ||
} | ||
|
||
type Leaf = ValidFilterTypes; | ||
|
||
type BooleanNode = BooleanBinaryNode<BooleanNode> | ||
| BooleanUnaryNode<BooleanNode> | ||
| Leaf; | ||
|
||
|
||
type BooleanNodeOrCombinator = BooleanNode | FlowrFilterCombinator | ||
|
||
export class FlowrFilterCombinator { | ||
private tree: BooleanNode; | ||
|
||
protected constructor(init: BooleanNodeOrCombinator) { | ||
this.tree = this.unpack(init); | ||
} | ||
|
||
public static is(value: BooleanNodeOrCombinator): FlowrFilterCombinator { | ||
return new this(value); | ||
} | ||
|
||
public and(right: BooleanNodeOrCombinator): this { | ||
this.tree = { | ||
type: 'and', | ||
left: this.tree, | ||
right: this.unpack(right) | ||
}; | ||
return this; | ||
} | ||
|
||
public or(right: BooleanNodeOrCombinator): this { | ||
this.tree = { | ||
type: 'or', | ||
left: this.tree, | ||
right: this.unpack(right) | ||
}; | ||
return this; | ||
} | ||
|
||
public xor(right: BooleanNodeOrCombinator): this { | ||
this.tree = { | ||
type: 'xor', | ||
left: this.tree, | ||
right: this.unpack(right) | ||
}; | ||
return this; | ||
} | ||
|
||
public not(): this { | ||
this.tree = { | ||
type: 'not', | ||
operand: this.tree | ||
}; | ||
return this; | ||
} | ||
|
||
private unpack(val: BooleanNodeOrCombinator): BooleanNode { | ||
return val instanceof FlowrFilterCombinator ? val.tree : val; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import type { NoInfo, RNode } from '../r-bridge/lang-4.x/ast/model/model'; | ||
import type { Pipeline, PipelineOutput, PipelineStepOutputWithName } from '../core/steps/pipeline/pipeline'; | ||
import type { NormalizedAst } from '../r-bridge/lang-4.x/ast/model/processing/decorate'; | ||
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id'; | ||
import type { FlowrFilterExpression } from './flowr-search-filters'; | ||
import type { DataflowGraph } from '../dataflow/graph/graph'; | ||
|
||
export interface FlowrSearchElement<Info> { | ||
readonly node: RNode<Info>; | ||
} | ||
|
||
export interface FlowrSearchNodeBase<Type extends string, Name extends string, Args extends Record<string, unknown> | undefined> { | ||
readonly type: Type; | ||
readonly name: Name; | ||
readonly args: Args; | ||
} | ||
|
||
/* Input extends FlowrSearchElements<Info>, Output extends FlowrSearchElements<Info> = Input */ | ||
export type FlowrSearchGeneratorNodeBase<Name extends string, Args extends Record<string, unknown> | undefined> = FlowrSearchNodeBase<'generator', Name, Args>; | ||
export type FlowrSearchTransformerNodeBase<Name extends string, Args extends Record<string, unknown> | undefined> = FlowrSearchNodeBase<'transformer', Name, Args>; | ||
|
||
export interface FlowrSearchGetFilters extends Record<string, unknown> { | ||
readonly line?: number; | ||
readonly column?: number; | ||
readonly name?: string; | ||
readonly id?: NodeId; | ||
} | ||
|
||
export type FlowrSearchGeneratorNode = FlowrSearchGeneratorNodeBase<'all', undefined> | ||
| FlowrSearchGeneratorNodeBase<'get', FlowrSearchGetFilters> | ||
|
||
export type FlowrSearchTransformerNode = FlowrSearchTransformerNodeBase<'first', undefined> | ||
| FlowrSearchTransformerNodeBase<'last', undefined> | ||
| FlowrSearchTransformerNodeBase<'index', { index: number }> | ||
| FlowrSearchTransformerNodeBase<'tail', undefined> | ||
| FlowrSearchTransformerNodeBase<'take', { count: number }> | ||
| FlowrSearchTransformerNodeBase<'skip', { count: number }> | ||
| FlowrSearchTransformerNodeBase<'filter', { | ||
filter: FlowrFilterExpression; | ||
}> | ||
|
||
type MinimumInputForFlowrSearch<P extends Pipeline> = | ||
PipelineStepOutputWithName<P, 'normalize'> extends NormalizedAst ? ( | ||
PipelineStepOutputWithName<P, 'dataflow'> extends DataflowGraph ? PipelineOutput<P> | ||
: never | ||
): never | ||
|
||
/** we allow any pipeline, which provides us with a 'normalize' and 'dataflow' step */ | ||
export type FlowrSearchInput< | ||
P extends Pipeline | ||
> = MinimumInputForFlowrSearch<P> | ||
|
||
/** Intentionally, we abstract away from an array to avoid the use of conventional typescript operations */ | ||
export class FlowrSearchElements<Info = NoInfo, Elements extends FlowrSearchElement<Info>[] = FlowrSearchElement<Info>[]> { | ||
private readonly elements: Elements = [] as unknown as Elements; | ||
|
||
public add(this: FlowrSearchElements<Info, Elements>, element: FlowrSearchElement<Info>): FlowrSearchElements<Info, FlowrSearchElement<Info>[]> { | ||
this.elements.push(element); | ||
return this; | ||
} | ||
|
||
public getElements(): readonly FlowrSearchElement<Info>[] { | ||
return this.elements; | ||
} | ||
/* TODO: conventional operations */ | ||
} | ||
|
||
/* TODO: differentiate generators, transformer, and terminators */ | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { describe, test } from 'vitest'; | ||
import type { FlowrSearchBuilderType } from '../../../src/search/flowr-search-builder'; | ||
import { FlowrSearchGenerator as Q } from '../../../src/search/flowr-search-builder'; | ||
import { RType } from '../../../src/r-bridge/lang-4.x/ast/model/type'; | ||
import { VertexType } from '../../../src/dataflow/graph/vertex'; | ||
import { FlowrFilterCombinator as F } from '../../../src/search/flowr-search-filters'; | ||
|
||
describe('flowR Search (playground)', () => { | ||
function print(search: FlowrSearchBuilderType) { | ||
console.log(JSON.stringify(search, null, 2)); | ||
} | ||
test('poor mans testing', () => { | ||
print(Q.all().filter(RType.Comment)); | ||
print(Q.get({ line: 3, name: 'x' }).filter( | ||
F.is(VertexType.Use).or(RType.Number) | ||
).first()); | ||
}); | ||
}); |