diff --git a/examples/map-reduce/python-reduce.pdl b/examples/map-reduce/python-reduce.pdl new file mode 100644 index 000000000..3efbdc531 --- /dev/null +++ b/examples/map-reduce/python-reduce.pdl @@ -0,0 +1,13 @@ +defs: + plus: + lang: python + code: | + import operator + result = operator.add +for: + i: [1,2,3,4] +map: + ${i} +join: + as: reduce + reduce: ${ plus } diff --git a/examples/map-reduce/reduce.pdl b/examples/map-reduce/reduce.pdl new file mode 100644 index 000000000..2bbaaab6d --- /dev/null +++ b/examples/map-reduce/reduce.pdl @@ -0,0 +1,13 @@ +defs: + plus: + function: + x: number + y: number + return: + ${ x + y } +for: + i: [1,2,3,4] +map: + ${i} +join: + reduce: ${ plus } diff --git a/pdl-live-react/src/pdl_ast.d.ts b/pdl-live-react/src/pdl_ast.d.ts index f15502b41..4fb0710ee 100644 --- a/pdl-live-react/src/pdl_ast.d.ts +++ b/pdl-live-react/src/pdl_ast.d.ts @@ -24,6 +24,7 @@ export type Program = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -167,6 +168,11 @@ export type Description19 = string | null * */ export type Description20 = string | null +/** + * Documentation associated to the block. + * + */ +export type Description21 = string | null /** * Name of the variable used to store the result of the execution of the block. * @@ -197,7 +203,7 @@ export type Parser = | PdlParser | RegexParser | null -export type Description21 = string | null +export type Description22 = string | null export type Pdl = | boolean | number @@ -213,6 +219,7 @@ export type Pdl = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -224,7 +231,7 @@ export type Pdl = | ErrorBlock | EmptyBlock | null -export type Description22 = string | null +export type Description23 = string | null export type Regex = string export type Mode = "search" | "match" | "fullmatch" | "split" | "findall" /** @@ -246,6 +253,7 @@ export type Fallback = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -335,6 +343,7 @@ export type Fallback1 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -402,6 +411,7 @@ export type Program1 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -455,6 +465,7 @@ export type Fallback2 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -518,6 +529,7 @@ export type PdlTrace = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -571,6 +583,7 @@ export type Fallback3 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -635,6 +648,7 @@ export type PdlTrace1 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -688,6 +702,7 @@ export type Fallback4 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -788,6 +803,7 @@ export type Fallback5 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -849,6 +865,7 @@ export type Content = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -910,6 +927,7 @@ export type Fallback6 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -971,6 +989,7 @@ export type Object1 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -998,6 +1017,7 @@ export type Object1 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1052,6 +1072,7 @@ export type Fallback7 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1114,6 +1135,7 @@ export type Array = ( | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1168,6 +1190,7 @@ export type Fallback8 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1230,6 +1253,7 @@ export type Lastof = ( | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1284,6 +1308,7 @@ export type Fallback9 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1347,6 +1372,7 @@ export type Text = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1372,6 +1398,7 @@ export type Text = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1427,6 +1454,7 @@ export type Fallback10 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1470,7 +1498,7 @@ export type PdlContext10 = export type PdlId10 = string | null export type PdlIsLeaf10 = false export type IndependentEnum5 = "independent" | "dependent" -export type Kind10 = "repeat" +export type Kind10 = "map" /** * Arrays to iterate over. * @@ -1484,15 +1512,10 @@ export type For = { */ export type Index = string | null /** - * Condition to stay at the beginning of the loop. - * - */ -export type While = LocalizedExpression | boolean | string -/** - * Body of the loop. + * Body of the iterator. * */ -export type Repeat = +export type Map = | boolean | number | string @@ -1507,6 +1530,7 @@ export type Repeat = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1518,11 +1542,6 @@ export type Repeat = | ErrorBlock | EmptyBlock | null -/** - * Condition to exit at the end of the loop. - * - */ -export type Until = LocalizedExpression | boolean | string /** * Maximal number of iterations to perform. * @@ -1532,7 +1551,7 @@ export type Maxiterations = LocalizedExpression | number | string | null * Define how to combine the result of each iteration. * */ -export type Join = JoinText | JoinArray | JoinObject | JoinLastOf +export type Join = JoinText | JoinArray | JoinObject | JoinLastOf | JoinReduce /** * String concatenation of the result of each iteration. * @@ -1558,6 +1577,11 @@ export type As2 = "object" * */ export type As3 = "lastOf" +export type As4 = "reduce" +/** + * Function used to combine the results. + */ +export type Reduce = LocalizedExpression | string export type PdlTrace2 = | ( | boolean @@ -1574,6 +1598,7 @@ export type PdlTrace2 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1629,6 +1654,7 @@ export type Fallback11 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1672,7 +1698,187 @@ export type PdlContext11 = export type PdlId11 = string | null export type PdlIsLeaf11 = false export type IndependentEnum6 = "independent" | "dependent" -export type Kind11 = "match" +export type Kind11 = "repeat" +/** + * Arrays to iterate over. + * + */ +export type For1 = { + [k: string]: LocalizedExpression | unknown[] | string +} | null +/** + * Name of the variable containing the loop iteration. + * + */ +export type Index1 = string | null +/** + * Condition to stay at the beginning of the loop. + * + */ +export type While = LocalizedExpression | boolean | string +/** + * Body of the loop. + * + */ +export type Repeat = + | boolean + | number + | string + | FunctionBlock + | CallBlock + | LitellmModelBlock + | GraniteioModelBlock + | CodeBlock + | ArgsBlock + | GetBlock + | DataBlock + | IfBlock + | MatchBlock + | RepeatBlock + | MapBlock + | TextBlock + | LastOfBlock + | ArrayBlock + | ObjectBlock + | MessageBlock + | ReadBlock + | IncludeBlock + | ImportBlock + | ErrorBlock + | EmptyBlock + | null +/** + * Condition to exit at the end of the loop. + * + */ +export type Until = LocalizedExpression | boolean | string +/** + * Maximal number of iterations to perform. + * + */ +export type Maxiterations1 = LocalizedExpression | number | string | null +/** + * Define how to combine the result of each iteration. + * + */ +export type Join1 = JoinText | JoinArray | JoinObject | JoinLastOf | JoinReduce +export type PdlTrace3 = + | ( + | boolean + | number + | string + | FunctionBlock + | CallBlock + | LitellmModelBlock + | GraniteioModelBlock + | CodeBlock + | ArgsBlock + | GetBlock + | DataBlock + | IfBlock + | MatchBlock + | RepeatBlock + | MapBlock + | TextBlock + | LastOfBlock + | ArrayBlock + | ObjectBlock + | MessageBlock + | ReadBlock + | IncludeBlock + | ImportBlock + | ErrorBlock + | EmptyBlock + | null + )[] + | null +/** + * Name of the variable used to store the result of the execution of the block. + * + */ +export type Def12 = string | null +/** + * Indicate if the block contributes to the result and background context. + * + */ +export type Contribute12 = ( + | ContributeTarget + | { + [k: string]: ContributeValue + } +)[] +/** + * Parser to use to construct a value out of a string result. + */ +export type Parser12 = + | ("json" | "jsonl" | "yaml") + | PdlParser + | RegexParser + | null +/** + * Block to execute in case of error. + * + */ +export type Fallback12 = + | boolean + | number + | string + | FunctionBlock + | CallBlock + | LitellmModelBlock + | GraniteioModelBlock + | CodeBlock + | ArgsBlock + | GetBlock + | DataBlock + | IfBlock + | MatchBlock + | RepeatBlock + | MapBlock + | TextBlock + | LastOfBlock + | ArrayBlock + | ObjectBlock + | MessageBlock + | ReadBlock + | IncludeBlock + | ImportBlock + | ErrorBlock + | EmptyBlock + | null +/** + * The maximum number of times to retry when an error occurs within a block. + * + */ +export type Retry12 = number | null +/** + * Whether to add the errors while retrying to the trace. Set this to true to use retry feature for multiple LLM trials. + * + */ +export type TraceErrorOnRetry12 = boolean | string | null +/** + * Role associated to the block and sub-blocks. + * Typical roles are `system`, `user`, and `assistant`, + * but there may be other roles such as `available_tools`. + */ +export type Role12 = string | null +/** + * Current context + * + */ +export type PdlContext12 = + | { + [k: string]: unknown + }[] + | null +/** + * Unique identifier for this block + * + */ +export type PdlId12 = string | null +export type PdlIsLeaf12 = false +export type IndependentEnum7 = "independent" | "dependent" +export type Kind12 = "match" export type Case = | boolean | number @@ -1682,10 +1888,10 @@ export type Case = | ObjectPattern | AnyPattern | null -export type Def12 = string | null export type Def13 = string | null export type Def14 = string | null export type Def15 = string | null +export type Def16 = string | null export type Any = null export type Array1 = ( | boolean @@ -1723,6 +1929,7 @@ export type Then = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1746,12 +1953,12 @@ export type With1 = MatchCase[] * Name of the variable used to store the result of the execution of the block. * */ -export type Def16 = string | null +export type Def17 = string | null /** * Indicate if the block contributes to the result and background context. * */ -export type Contribute12 = ( +export type Contribute13 = ( | ContributeTarget | { [k: string]: ContributeValue @@ -1760,7 +1967,7 @@ export type Contribute12 = ( /** * Parser to use to construct a value out of a string result. */ -export type Parser12 = +export type Parser13 = | ("json" | "jsonl" | "yaml") | PdlParser | RegexParser @@ -1769,7 +1976,7 @@ export type Parser12 = * Block to execute in case of error. * */ -export type Fallback12 = +export type Fallback13 = | boolean | number | string @@ -1784,6 +1991,7 @@ export type Fallback12 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1799,23 +2007,23 @@ export type Fallback12 = * The maximum number of times to retry when an error occurs within a block. * */ -export type Retry12 = number | null +export type Retry13 = number | null /** * Whether to add the errors while retrying to the trace. Set this to true to use retry feature for multiple LLM trials. * */ -export type TraceErrorOnRetry12 = boolean | string | null +export type TraceErrorOnRetry13 = boolean | string | null /** * Role associated to the block and sub-blocks. * Typical roles are `system`, `user`, and `assistant`, * but there may be other roles such as `available_tools`. */ -export type Role12 = string | null +export type Role13 = string | null /** * Current context * */ -export type PdlContext12 = +export type PdlContext13 = | { [k: string]: unknown }[] @@ -1824,10 +2032,10 @@ export type PdlContext12 = * Unique identifier for this block * */ -export type PdlId12 = string | null -export type PdlIsLeaf12 = false -export type IndependentEnum7 = "independent" | "dependent" -export type Kind12 = "if" +export type PdlId13 = string | null +export type PdlIsLeaf13 = false +export type IndependentEnum8 = "independent" | "dependent" +export type Kind13 = "if" /** * Condition. * @@ -1852,6 +2060,7 @@ export type Then1 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1882,6 +2091,7 @@ export type Else = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1897,12 +2107,12 @@ export type Else = * Name of the variable used to store the result of the execution of the block. * */ -export type Def17 = string | null +export type Def18 = string | null /** * Indicate if the block contributes to the result and background context. * */ -export type Contribute13 = ( +export type Contribute14 = ( | ContributeTarget | { [k: string]: ContributeValue @@ -1911,7 +2121,7 @@ export type Contribute13 = ( /** * Parser to use to construct a value out of a string result. */ -export type Parser13 = +export type Parser14 = | ("json" | "jsonl" | "yaml") | PdlParser | RegexParser @@ -1920,7 +2130,7 @@ export type Parser13 = * Block to execute in case of error. * */ -export type Fallback13 = +export type Fallback14 = | boolean | number | string @@ -1935,6 +2145,7 @@ export type Fallback13 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -1950,23 +2161,23 @@ export type Fallback13 = * The maximum number of times to retry when an error occurs within a block. * */ -export type Retry13 = number | null +export type Retry14 = number | null /** * Whether to add the errors while retrying to the trace. Set this to true to use retry feature for multiple LLM trials. * */ -export type TraceErrorOnRetry13 = boolean | string | null +export type TraceErrorOnRetry14 = boolean | string | null /** * Role associated to the block and sub-blocks. * Typical roles are `system`, `user`, and `assistant`, * but there may be other roles such as `available_tools`. */ -export type Role13 = string | null +export type Role14 = string | null /** * Current context * */ -export type PdlContext13 = +export type PdlContext14 = | { [k: string]: unknown }[] @@ -1975,9 +2186,9 @@ export type PdlContext13 = * Unique identifier for this block * */ -export type PdlId13 = string | null -export type PdlIsLeaf13 = true -export type Kind13 = "data" +export type PdlId14 = string | null +export type PdlIsLeaf14 = true +export type Kind14 = "data" /** * Do not evaluate expressions inside strings. */ @@ -1986,12 +2197,12 @@ export type Raw = boolean * Name of the variable used to store the result of the execution of the block. * */ -export type Def18 = string | null +export type Def19 = string | null /** * Indicate if the block contributes to the result and background context. * */ -export type Contribute14 = ( +export type Contribute15 = ( | ContributeTarget | { [k: string]: ContributeValue @@ -2000,7 +2211,7 @@ export type Contribute14 = ( /** * Parser to use to construct a value out of a string result. */ -export type Parser14 = +export type Parser15 = | ("json" | "jsonl" | "yaml") | PdlParser | RegexParser @@ -2009,7 +2220,7 @@ export type Parser14 = * Block to execute in case of error. * */ -export type Fallback14 = +export type Fallback15 = | boolean | number | string @@ -2024,6 +2235,7 @@ export type Fallback14 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2039,23 +2251,23 @@ export type Fallback14 = * The maximum number of times to retry when an error occurs within a block. * */ -export type Retry14 = number | null +export type Retry15 = number | null /** * Whether to add the errors while retrying to the trace. Set this to true to use retry feature for multiple LLM trials. * */ -export type TraceErrorOnRetry14 = boolean | string | null +export type TraceErrorOnRetry15 = boolean | string | null /** * Role associated to the block and sub-blocks. * Typical roles are `system`, `user`, and `assistant`, * but there may be other roles such as `available_tools`. */ -export type Role14 = string | null +export type Role15 = string | null /** * Current context * */ -export type PdlContext14 = +export type PdlContext15 = | { [k: string]: unknown }[] @@ -2064,9 +2276,9 @@ export type PdlContext14 = * Unique identifier for this block * */ -export type PdlId14 = string | null -export type PdlIsLeaf14 = true -export type Kind14 = "get" +export type PdlId15 = string | null +export type PdlIsLeaf15 = true +export type Kind15 = "get" /** * Name of the variable to access. */ @@ -2075,12 +2287,12 @@ export type Get = string * Name of the variable used to store the result of the execution of the block. * */ -export type Def19 = string | null +export type Def20 = string | null /** * Indicate if the block contributes to the result and background context. * */ -export type Contribute15 = ( +export type Contribute16 = ( | ContributeTarget | { [k: string]: ContributeValue @@ -2089,7 +2301,7 @@ export type Contribute15 = ( /** * Parser to use to construct a value out of a string result. */ -export type Parser15 = +export type Parser16 = | ("json" | "jsonl" | "yaml") | PdlParser | RegexParser @@ -2098,7 +2310,7 @@ export type Parser15 = * Block to execute in case of error. * */ -export type Fallback15 = +export type Fallback16 = | boolean | number | string @@ -2113,6 +2325,7 @@ export type Fallback15 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2128,23 +2341,23 @@ export type Fallback15 = * The maximum number of times to retry when an error occurs within a block. * */ -export type Retry15 = number | null +export type Retry16 = number | null /** * Whether to add the errors while retrying to the trace. Set this to true to use retry feature for multiple LLM trials. * */ -export type TraceErrorOnRetry15 = boolean | string | null +export type TraceErrorOnRetry16 = boolean | string | null /** * Role associated to the block and sub-blocks. * Typical roles are `system`, `user`, and `assistant`, * but there may be other roles such as `available_tools`. */ -export type Role15 = string | null +export type Role16 = string | null /** * Current context * */ -export type PdlContext15 = +export type PdlContext16 = | { [k: string]: unknown }[] @@ -2153,9 +2366,9 @@ export type PdlContext15 = * Unique identifier for this block * */ -export type PdlId15 = string | null -export type PdlIsLeaf15 = true -export type Kind15 = "code" +export type PdlId16 = string | null +export type PdlIsLeaf16 = true +export type Kind16 = "code" export type Lang = "command" /** * The argument vector to spawn. @@ -2166,12 +2379,12 @@ export type Args = (LocalizedExpression | string)[] * Name of the variable used to store the result of the execution of the block. * */ -export type Def20 = string | null +export type Def21 = string | null /** * Indicate if the block contributes to the result and background context. * */ -export type Contribute16 = ( +export type Contribute17 = ( | ContributeTarget | { [k: string]: ContributeValue @@ -2180,7 +2393,7 @@ export type Contribute16 = ( /** * Parser to use to construct a value out of a string result. */ -export type Parser16 = +export type Parser17 = | ("json" | "jsonl" | "yaml") | PdlParser | RegexParser @@ -2189,7 +2402,7 @@ export type Parser16 = * Block to execute in case of error. * */ -export type Fallback16 = +export type Fallback17 = | boolean | number | string @@ -2204,6 +2417,7 @@ export type Fallback16 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2219,23 +2433,23 @@ export type Fallback16 = * The maximum number of times to retry when an error occurs within a block. * */ -export type Retry16 = number | null +export type Retry17 = number | null /** * Whether to add the errors while retrying to the trace. Set this to true to use retry feature for multiple LLM trials. * */ -export type TraceErrorOnRetry16 = boolean | string | null +export type TraceErrorOnRetry17 = boolean | string | null /** * Role associated to the block and sub-blocks. * Typical roles are `system`, `user`, and `assistant`, * but there may be other roles such as `available_tools`. */ -export type Role16 = string | null +export type Role17 = string | null /** * Current context * */ -export type PdlContext16 = +export type PdlContext17 = | { [k: string]: unknown }[] @@ -2244,9 +2458,9 @@ export type PdlContext16 = * Unique identifier for this block * */ -export type PdlId16 = string | null -export type PdlIsLeaf16 = true -export type Kind16 = "code" +export type PdlId17 = string | null +export type PdlIsLeaf17 = true +export type Kind17 = "code" /** * Programming language of the code. * @@ -2271,6 +2485,7 @@ export type Code = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2286,12 +2501,12 @@ export type Code = * Name of the variable used to store the result of the execution of the block. * */ -export type Def21 = string | null +export type Def22 = string | null /** * Indicate if the block contributes to the result and background context. * */ -export type Contribute17 = ( +export type Contribute18 = ( | ContributeTarget | { [k: string]: ContributeValue @@ -2300,7 +2515,7 @@ export type Contribute17 = ( /** * Parser to use to construct a value out of a string result. */ -export type Parser17 = +export type Parser18 = | ("json" | "jsonl" | "yaml") | PdlParser | RegexParser @@ -2309,7 +2524,7 @@ export type Parser17 = * Block to execute in case of error. * */ -export type Fallback17 = +export type Fallback18 = | boolean | number | string @@ -2324,6 +2539,7 @@ export type Fallback17 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2339,23 +2555,23 @@ export type Fallback17 = * The maximum number of times to retry when an error occurs within a block. * */ -export type Retry17 = number | null +export type Retry18 = number | null /** * Whether to add the errors while retrying to the trace. Set this to true to use retry feature for multiple LLM trials. * */ -export type TraceErrorOnRetry17 = boolean | string | null +export type TraceErrorOnRetry18 = boolean | string | null /** * Role associated to the block and sub-blocks. * Typical roles are `system`, `user`, and `assistant`, * but there may be other roles such as `available_tools`. */ -export type Role17 = string | null +export type Role18 = string | null /** * Current context * */ -export type PdlContext17 = +export type PdlContext18 = | { [k: string]: unknown }[] @@ -2364,9 +2580,9 @@ export type PdlContext17 = * Unique identifier for this block * */ -export type PdlId17 = string | null -export type PdlIsLeaf17 = true -export type Kind17 = "model" +export type PdlId18 = string | null +export type PdlIsLeaf18 = true +export type Kind18 = "model" /** * Messages to send to the model. * @@ -2386,6 +2602,7 @@ export type Input = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2429,12 +2646,12 @@ export type Parameters = * Name of the variable used to store the result of the execution of the block. * */ -export type Def22 = string | null +export type Def23 = string | null /** * Indicate if the block contributes to the result and background context. * */ -export type Contribute18 = ( +export type Contribute19 = ( | ContributeTarget | { [k: string]: ContributeValue @@ -2443,7 +2660,7 @@ export type Contribute18 = ( /** * Parser to use to construct a value out of a string result. */ -export type Parser18 = +export type Parser19 = | ("json" | "jsonl" | "yaml") | PdlParser | RegexParser @@ -2452,7 +2669,7 @@ export type Parser18 = * Block to execute in case of error. * */ -export type Fallback18 = +export type Fallback19 = | boolean | number | string @@ -2467,6 +2684,7 @@ export type Fallback18 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2482,23 +2700,23 @@ export type Fallback18 = * The maximum number of times to retry when an error occurs within a block. * */ -export type Retry18 = number | null +export type Retry19 = number | null /** * Whether to add the errors while retrying to the trace. Set this to true to use retry feature for multiple LLM trials. * */ -export type TraceErrorOnRetry18 = boolean | string | null +export type TraceErrorOnRetry19 = boolean | string | null /** * Role associated to the block and sub-blocks. * Typical roles are `system`, `user`, and `assistant`, * but there may be other roles such as `available_tools`. */ -export type Role18 = string | null +export type Role19 = string | null /** * Current context * */ -export type PdlContext18 = +export type PdlContext19 = | { [k: string]: unknown }[] @@ -2507,9 +2725,9 @@ export type PdlContext18 = * Unique identifier for this block * */ -export type PdlId18 = string | null -export type PdlIsLeaf18 = true -export type Kind18 = "model" +export type PdlId19 = string | null +export type PdlIsLeaf19 = true +export type Kind19 = "model" /** * Messages to send to the model. * @@ -2529,6 +2747,7 @@ export type Input1 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2623,12 +2842,12 @@ export type MaxRetries = number | string | null * Name of the variable used to store the result of the execution of the block. * */ -export type Def23 = string | null +export type Def24 = string | null /** * Indicate if the block contributes to the result and background context. * */ -export type Contribute19 = ( +export type Contribute20 = ( | ContributeTarget | { [k: string]: ContributeValue @@ -2637,7 +2856,7 @@ export type Contribute19 = ( /** * Parser to use to construct a value out of a string result. */ -export type Parser19 = +export type Parser20 = | ("json" | "jsonl" | "yaml") | PdlParser | RegexParser @@ -2646,7 +2865,7 @@ export type Parser19 = * Block to execute in case of error. * */ -export type Fallback19 = +export type Fallback20 = | boolean | number | string @@ -2661,6 +2880,7 @@ export type Fallback19 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2676,23 +2896,23 @@ export type Fallback19 = * The maximum number of times to retry when an error occurs within a block. * */ -export type Retry19 = number | null +export type Retry20 = number | null /** * Whether to add the errors while retrying to the trace. Set this to true to use retry feature for multiple LLM trials. * */ -export type TraceErrorOnRetry19 = boolean | string | null +export type TraceErrorOnRetry20 = boolean | string | null /** * Role associated to the block and sub-blocks. * Typical roles are `system`, `user`, and `assistant`, * but there may be other roles such as `available_tools`. */ -export type Role19 = string | null +export type Role20 = string | null /** * Current context * */ -export type PdlContext19 = +export type PdlContext20 = | { [k: string]: unknown }[] @@ -2701,15 +2921,15 @@ export type PdlContext19 = * Unique identifier for this block * */ -export type PdlId19 = string | null -export type PdlIsLeaf19 = true -export type Kind19 = "call" +export type PdlId20 = string | null +export type PdlIsLeaf20 = true +export type Kind20 = "call" /** * Function to call. * */ export type Call = LocalizedExpression | FunctionBlock | string -export type PdlTrace3 = +export type PdlTrace4 = | boolean | number | string @@ -2724,6 +2944,7 @@ export type PdlTrace3 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2739,12 +2960,12 @@ export type PdlTrace3 = * Name of the variable used to store the result of the execution of the block. * */ -export type Def24 = string | null +export type Def25 = string | null /** * Indicate if the block contributes to the result and background context. * */ -export type Contribute20 = ( +export type Contribute21 = ( | ContributeTarget | { [k: string]: ContributeValue @@ -2753,7 +2974,7 @@ export type Contribute20 = ( /** * Parser to use to construct a value out of a string result. */ -export type Parser20 = +export type Parser21 = | ("json" | "jsonl" | "yaml") | PdlParser | RegexParser @@ -2762,7 +2983,7 @@ export type Parser20 = * Block to execute in case of error. * */ -export type Fallback20 = +export type Fallback21 = | boolean | number | string @@ -2777,6 +2998,7 @@ export type Fallback20 = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2792,23 +3014,23 @@ export type Fallback20 = * The maximum number of times to retry when an error occurs within a block. * */ -export type Retry20 = number | null +export type Retry21 = number | null /** * Whether to add the errors while retrying to the trace. Set this to true to use retry feature for multiple LLM trials. * */ -export type TraceErrorOnRetry20 = boolean | string | null +export type TraceErrorOnRetry21 = boolean | string | null /** * Role associated to the block and sub-blocks. * Typical roles are `system`, `user`, and `assistant`, * but there may be other roles such as `available_tools`. */ -export type Role20 = string | null +export type Role21 = string | null /** * Current context * */ -export type PdlContext20 = +export type PdlContext21 = | { [k: string]: unknown }[] @@ -2817,9 +3039,9 @@ export type PdlContext20 = * Unique identifier for this block * */ -export type PdlId20 = string | null -export type PdlIsLeaf20 = true -export type Kind20 = "function" +export type PdlId21 = string | null +export type PdlIsLeaf21 = true +export type Kind21 = "function" /** * Functions parameters with their types. * @@ -2846,6 +3068,7 @@ export type Return = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2877,6 +3100,7 @@ export type PdlBlock = | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -2924,20 +3148,20 @@ export interface FunctionBlock { } | null defs?: Defs - def?: Def24 - contribute?: Contribute20 - parser?: Parser20 - fallback?: Fallback20 - retry?: Retry20 - trace_error_on_retry?: TraceErrorOnRetry20 - role?: Role20 - pdl__context?: PdlContext20 - pdl__id?: PdlId20 + def?: Def25 + contribute?: Contribute21 + parser?: Parser21 + fallback?: Fallback21 + retry?: Retry21 + trace_error_on_retry?: TraceErrorOnRetry21 + role?: Role21 + pdl__context?: PdlContext21 + pdl__id?: PdlId21 pdl__result?: unknown pdl__location?: PdlLocationType | null pdl__timing?: PdlTiming | null - pdl__is_leaf?: PdlIsLeaf20 - kind?: Kind20 + pdl__is_leaf?: PdlIsLeaf21 + kind?: Kind21 function: Function return: Return signature?: Signature @@ -2991,6 +3215,7 @@ export interface Defs { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -3038,23 +3263,23 @@ export interface CallBlock { } | null defs?: Defs1 - def?: Def23 - contribute?: Contribute19 - parser?: Parser19 - fallback?: Fallback19 - retry?: Retry19 - trace_error_on_retry?: TraceErrorOnRetry19 - role?: Role19 - pdl__context?: PdlContext19 - pdl__id?: PdlId19 + def?: Def24 + contribute?: Contribute20 + parser?: Parser20 + fallback?: Fallback20 + retry?: Retry20 + trace_error_on_retry?: TraceErrorOnRetry20 + role?: Role20 + pdl__context?: PdlContext20 + pdl__id?: PdlId20 pdl__result?: unknown pdl__location?: PdlLocationType | null pdl__timing?: PdlTiming | null - pdl__is_leaf?: PdlIsLeaf19 - kind?: Kind19 + pdl__is_leaf?: PdlIsLeaf20 + kind?: Kind20 call: Call args?: unknown - pdl__trace?: PdlTrace3 + pdl__trace?: PdlTrace4 } /** * Set of definitions executed before the execution of the block. @@ -3076,6 +3301,7 @@ export interface Defs1 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -3130,20 +3356,20 @@ export interface LitellmModelBlock { } | null defs?: Defs2 - def?: Def22 - contribute?: Contribute18 - parser?: Parser18 - fallback?: Fallback18 - retry?: Retry18 - trace_error_on_retry?: TraceErrorOnRetry18 - role?: Role18 - pdl__context?: PdlContext18 - pdl__id?: PdlId18 + def?: Def23 + contribute?: Contribute19 + parser?: Parser19 + fallback?: Fallback19 + retry?: Retry19 + trace_error_on_retry?: TraceErrorOnRetry19 + role?: Role19 + pdl__context?: PdlContext19 + pdl__id?: PdlId19 pdl__result?: unknown pdl__location?: PdlLocationType | null pdl__timing?: PdlTiming | null - pdl__is_leaf?: PdlIsLeaf18 - kind?: Kind18 + pdl__is_leaf?: PdlIsLeaf19 + kind?: Kind19 input?: Input1 modelResponse?: Modelresponse1 /** @@ -3176,6 +3402,7 @@ export interface Defs2 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -3223,20 +3450,20 @@ export interface GraniteioModelBlock { } | null defs?: Defs3 - def?: Def21 - contribute?: Contribute17 - parser?: Parser17 - fallback?: Fallback17 - retry?: Retry17 - trace_error_on_retry?: TraceErrorOnRetry17 - role?: Role17 - pdl__context?: PdlContext17 - pdl__id?: PdlId17 + def?: Def22 + contribute?: Contribute18 + parser?: Parser18 + fallback?: Fallback18 + retry?: Retry18 + trace_error_on_retry?: TraceErrorOnRetry18 + role?: Role18 + pdl__context?: PdlContext18 + pdl__id?: PdlId18 pdl__result?: unknown pdl__location?: PdlLocationType | null pdl__timing?: PdlTiming | null - pdl__is_leaf?: PdlIsLeaf17 - kind?: Kind17 + pdl__is_leaf?: PdlIsLeaf18 + kind?: Kind18 input?: Input modelResponse?: Modelresponse /** @@ -3269,6 +3496,7 @@ export interface Defs3 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -3325,20 +3553,20 @@ export interface CodeBlock { } | null defs?: Defs4 - def?: Def20 - contribute?: Contribute16 - parser?: Parser16 - fallback?: Fallback16 - retry?: Retry16 - trace_error_on_retry?: TraceErrorOnRetry16 - role?: Role16 - pdl__context?: PdlContext16 - pdl__id?: PdlId16 + def?: Def21 + contribute?: Contribute17 + parser?: Parser17 + fallback?: Fallback17 + retry?: Retry17 + trace_error_on_retry?: TraceErrorOnRetry17 + role?: Role17 + pdl__context?: PdlContext17 + pdl__id?: PdlId17 pdl__result?: unknown pdl__location?: PdlLocationType | null pdl__timing?: PdlTiming | null - pdl__is_leaf?: PdlIsLeaf16 - kind?: Kind16 + pdl__is_leaf?: PdlIsLeaf17 + kind?: Kind17 lang: Lang1 code: Code } @@ -3362,6 +3590,7 @@ export interface Defs4 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -3417,20 +3646,20 @@ export interface ArgsBlock { } | null defs?: Defs5 - def?: Def19 - contribute?: Contribute15 - parser?: Parser15 - fallback?: Fallback15 - retry?: Retry15 - trace_error_on_retry?: TraceErrorOnRetry15 - role?: Role15 - pdl__context?: PdlContext15 - pdl__id?: PdlId15 + def?: Def20 + contribute?: Contribute16 + parser?: Parser16 + fallback?: Fallback16 + retry?: Retry16 + trace_error_on_retry?: TraceErrorOnRetry16 + role?: Role16 + pdl__context?: PdlContext16 + pdl__id?: PdlId16 pdl__result?: unknown pdl__location?: PdlLocationType | null pdl__timing?: PdlTiming | null - pdl__is_leaf?: PdlIsLeaf15 - kind?: Kind15 + pdl__is_leaf?: PdlIsLeaf16 + kind?: Kind16 lang?: Lang args: Args } @@ -3454,6 +3683,7 @@ export interface Defs5 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -3503,20 +3733,20 @@ export interface GetBlock { } | null defs?: Defs6 - def?: Def18 - contribute?: Contribute14 - parser?: Parser14 - fallback?: Fallback14 - retry?: Retry14 - trace_error_on_retry?: TraceErrorOnRetry14 - role?: Role14 - pdl__context?: PdlContext14 - pdl__id?: PdlId14 + def?: Def19 + contribute?: Contribute15 + parser?: Parser15 + fallback?: Fallback15 + retry?: Retry15 + trace_error_on_retry?: TraceErrorOnRetry15 + role?: Role15 + pdl__context?: PdlContext15 + pdl__id?: PdlId15 pdl__result?: unknown pdl__location?: PdlLocationType | null pdl__timing?: PdlTiming | null - pdl__is_leaf?: PdlIsLeaf14 - kind?: Kind14 + pdl__is_leaf?: PdlIsLeaf15 + kind?: Kind15 get: Get } /** @@ -3539,6 +3769,7 @@ export interface Defs6 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -3607,20 +3838,20 @@ export interface DataBlock { } | null defs?: Defs7 - def?: Def17 - contribute?: Contribute13 - parser?: Parser13 - fallback?: Fallback13 - retry?: Retry13 - trace_error_on_retry?: TraceErrorOnRetry13 - role?: Role13 - pdl__context?: PdlContext13 - pdl__id?: PdlId13 + def?: Def18 + contribute?: Contribute14 + parser?: Parser14 + fallback?: Fallback14 + retry?: Retry14 + trace_error_on_retry?: TraceErrorOnRetry14 + role?: Role14 + pdl__context?: PdlContext14 + pdl__id?: PdlId14 pdl__result?: unknown pdl__location?: PdlLocationType | null pdl__timing?: PdlTiming | null - pdl__is_leaf?: PdlIsLeaf13 - kind?: Kind13 + pdl__is_leaf?: PdlIsLeaf14 + kind?: Kind14 data: unknown raw?: Raw } @@ -3644,6 +3875,7 @@ export interface Defs7 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -3701,21 +3933,21 @@ export interface IfBlock { } | null defs?: Defs8 - def?: Def16 - contribute?: Contribute12 - parser?: Parser12 - fallback?: Fallback12 - retry?: Retry12 - trace_error_on_retry?: TraceErrorOnRetry12 - role?: Role12 - pdl__context?: PdlContext12 - pdl__id?: PdlId12 + def?: Def17 + contribute?: Contribute13 + parser?: Parser13 + fallback?: Fallback13 + retry?: Retry13 + trace_error_on_retry?: TraceErrorOnRetry13 + role?: Role13 + pdl__context?: PdlContext13 + pdl__id?: PdlId13 pdl__result?: unknown pdl__location?: PdlLocationType | null pdl__timing?: PdlTiming | null - pdl__is_leaf?: PdlIsLeaf12 - context?: IndependentEnum7 - kind?: Kind12 + pdl__is_leaf?: PdlIsLeaf13 + context?: IndependentEnum8 + kind?: Kind13 if: If1 then: Then1 else?: Else @@ -3740,6 +3972,7 @@ export interface Defs8 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -3804,6 +4037,115 @@ export interface MatchBlock { } | null defs?: Defs9 + def?: Def12 + contribute?: Contribute12 + parser?: Parser12 + fallback?: Fallback12 + retry?: Retry12 + trace_error_on_retry?: TraceErrorOnRetry12 + role?: Role12 + pdl__context?: PdlContext12 + pdl__id?: PdlId12 + pdl__result?: unknown + pdl__location?: PdlLocationType | null + pdl__timing?: PdlTiming | null + pdl__is_leaf?: PdlIsLeaf12 + context?: IndependentEnum7 + kind?: Kind12 + match: unknown + with: With1 +} +/** + * Set of definitions executed before the execution of the block. + * + */ +export interface Defs9 { + [k: string]: + | boolean + | number + | string + | FunctionBlock + | CallBlock + | LitellmModelBlock + | GraniteioModelBlock + | CodeBlock + | ArgsBlock + | GetBlock + | DataBlock + | IfBlock + | MatchBlock + | RepeatBlock + | MapBlock + | TextBlock + | LastOfBlock + | ArrayBlock + | ObjectBlock + | MessageBlock + | ReadBlock + | IncludeBlock + | ImportBlock + | ErrorBlock + | EmptyBlock + | null +} +/** + * Repeat the execution of a block sequentially. + * The scope and `pdl_context` are accumulated in between iterations. + * + * For loop example: + * ```PDL + * for: + * number: [1, 2, 3, 4] + * name: ["Bob", "Carol", "David", "Ernest"] + * repeat: + * "${ name }'s number is ${ number }\n" + * ``` + * + * While loop: + * ```PDL + * defs: + * i: 0 + * while: ${i < 5} + * repeat: + * defs: + * i: ${ i + 1} + * data: ${ i } + * join: + * as: array + * ``` + */ +export interface RepeatBlock { + description?: Description10 + /** + * Type specification of the result of the block. + * + */ + spec?: + | ( + | "null" + | "boolean" + | "string" + | "number" + | "integer" + | "array" + | "object" + | "bool" + | "str" + | "float" + | "int" + | "list" + | "obj" + ) + | EnumPdlType + | PdlTypeType[] + | OptionalPdlType + | JsonSchemaTypePdlType + | ObjectPdlType + | { + [k: string]: PdlTypeType + } + | null + defs?: Defs10 def?: Def11 contribute?: Contribute11 parser?: Parser11 @@ -3819,14 +4161,20 @@ export interface MatchBlock { pdl__is_leaf?: PdlIsLeaf11 context?: IndependentEnum6 kind?: Kind11 - match: unknown - with: With1 + for?: For1 + index?: Index1 + while?: While + repeat: Repeat + until?: Until + maxIterations?: Maxiterations1 + join?: Join1 + pdl__trace?: PdlTrace3 } /** * Set of definitions executed before the execution of the block. * */ -export interface Defs9 { +export interface Defs10 { [k: string]: | boolean | number @@ -3842,6 +4190,7 @@ export interface Defs9 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -3855,14 +4204,16 @@ export interface Defs9 { | null } /** - * Repeat the execution of a block. + * Independent executions of a block. + * Repeat the execution of a block starting from the initial scope + * and `pdl_context`. * * For loop example: * ```PDL * for: * number: [1, 2, 3, 4] * name: ["Bob", "Carol", "David", "Ernest"] - * repeat: + * map: * "${ name }'s number is ${ number }\n" * ``` * @@ -3870,14 +4221,14 @@ export interface Defs9 { * ```PDL * index: i * maxIterations: 5 - * repeat: + * map: * ${ i } * join: * as: array * ``` */ -export interface RepeatBlock { - description?: Description10 +export interface MapBlock { + description?: Description11 /** * Type specification of the result of the block. * @@ -3907,7 +4258,7 @@ export interface RepeatBlock { [k: string]: PdlTypeType } | null - defs?: Defs10 + defs?: Defs11 def?: Def10 contribute?: Contribute10 parser?: Parser10 @@ -3925,9 +4276,7 @@ export interface RepeatBlock { kind?: Kind10 for?: For index?: Index - while?: While - repeat: Repeat - until?: Until + map: Map maxIterations?: Maxiterations join?: Join pdl__trace?: PdlTrace2 @@ -3936,7 +4285,7 @@ export interface RepeatBlock { * Set of definitions executed before the execution of the block. * */ -export interface Defs10 { +export interface Defs11 { [k: string]: | boolean | number @@ -3952,6 +4301,7 @@ export interface Defs10 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -3968,7 +4318,7 @@ export interface Defs10 { * Create the concatenation of the stringify version of the result of each block of the list of blocks. */ export interface TextBlock { - description?: Description11 + description?: Description12 /** * Type specification of the result of the block. * @@ -3998,7 +4348,7 @@ export interface TextBlock { [k: string]: PdlTypeType } | null - defs?: Defs11 + defs?: Defs12 def?: Def9 contribute?: Contribute9 parser?: Parser9 @@ -4020,7 +4370,7 @@ export interface TextBlock { * Set of definitions executed before the execution of the block. * */ -export interface Defs11 { +export interface Defs12 { [k: string]: | boolean | number @@ -4036,6 +4386,7 @@ export interface Defs11 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -4052,7 +4403,7 @@ export interface Defs11 { * Return the value of the last block if the list of blocks. */ export interface LastOfBlock { - description?: Description12 + description?: Description13 /** * Type specification of the result of the block. * @@ -4082,7 +4433,7 @@ export interface LastOfBlock { [k: string]: PdlTypeType } | null - defs?: Defs12 + defs?: Defs13 def?: Def8 contribute?: Contribute8 parser?: Parser8 @@ -4104,7 +4455,7 @@ export interface LastOfBlock { * Set of definitions executed before the execution of the block. * */ -export interface Defs12 { +export interface Defs13 { [k: string]: | boolean | number @@ -4120,6 +4471,7 @@ export interface Defs12 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -4136,7 +4488,7 @@ export interface Defs12 { * Return the array of values computed by each block of the list of blocks. */ export interface ArrayBlock { - description?: Description13 + description?: Description14 /** * Type specification of the result of the block. * @@ -4166,7 +4518,7 @@ export interface ArrayBlock { [k: string]: PdlTypeType } | null - defs?: Defs13 + defs?: Defs14 def?: Def7 contribute?: Contribute7 parser?: Parser7 @@ -4188,7 +4540,7 @@ export interface ArrayBlock { * Set of definitions executed before the execution of the block. * */ -export interface Defs13 { +export interface Defs14 { [k: string]: | boolean | number @@ -4204,6 +4556,7 @@ export interface Defs13 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -4220,7 +4573,7 @@ export interface Defs13 { * Return the object where the value of each field is defined by a block. If the body of the object is an array, the resulting object is the union of the objects computed by each element of the array. */ export interface ObjectBlock { - description?: Description14 + description?: Description15 /** * Type specification of the result of the block. * @@ -4250,7 +4603,7 @@ export interface ObjectBlock { [k: string]: PdlTypeType } | null - defs?: Defs14 + defs?: Defs15 def?: Def6 contribute?: Contribute6 parser?: Parser6 @@ -4272,7 +4625,7 @@ export interface ObjectBlock { * Set of definitions executed before the execution of the block. * */ -export interface Defs14 { +export interface Defs15 { [k: string]: | boolean | number @@ -4288,6 +4641,7 @@ export interface Defs14 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -4304,7 +4658,7 @@ export interface Defs14 { * Create a message. */ export interface MessageBlock { - description?: Description15 + description?: Description16 /** * Type specification of the result of the block. * @@ -4334,7 +4688,7 @@ export interface MessageBlock { [k: string]: PdlTypeType } | null - defs?: Defs15 + defs?: Defs16 def?: Def5 contribute?: Contribute5 parser?: Parser5 @@ -4357,7 +4711,7 @@ export interface MessageBlock { * Set of definitions executed before the execution of the block. * */ -export interface Defs15 { +export interface Defs16 { [k: string]: | boolean | number @@ -4373,6 +4727,7 @@ export interface Defs15 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -4401,7 +4756,7 @@ export interface Defs15 { * ``` */ export interface ReadBlock { - description?: Description16 + description?: Description17 /** * Type specification of the result of the block. * @@ -4431,7 +4786,7 @@ export interface ReadBlock { [k: string]: PdlTypeType } | null - defs?: Defs16 + defs?: Defs17 def?: Def4 contribute?: Contribute4 parser?: Parser4 @@ -4454,7 +4809,7 @@ export interface ReadBlock { * Set of definitions executed before the execution of the block. * */ -export interface Defs16 { +export interface Defs17 { [k: string]: | boolean | number @@ -4470,6 +4825,7 @@ export interface Defs16 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -4486,7 +4842,7 @@ export interface Defs16 { * Include a PDL file. */ export interface IncludeBlock { - description?: Description17 + description?: Description18 /** * Type specification of the result of the block. * @@ -4516,7 +4872,7 @@ export interface IncludeBlock { [k: string]: PdlTypeType } | null - defs?: Defs17 + defs?: Defs18 def?: Def3 contribute?: Contribute3 parser?: Parser3 @@ -4539,7 +4895,7 @@ export interface IncludeBlock { * Set of definitions executed before the execution of the block. * */ -export interface Defs17 { +export interface Defs18 { [k: string]: | boolean | number @@ -4555,6 +4911,7 @@ export interface Defs17 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -4571,7 +4928,7 @@ export interface Defs17 { * Import a PDL file. */ export interface ImportBlock { - description?: Description18 + description?: Description19 /** * Type specification of the result of the block. * @@ -4601,7 +4958,7 @@ export interface ImportBlock { [k: string]: PdlTypeType } | null - defs?: Defs18 + defs?: Defs19 def?: Def2 contribute?: Contribute2 parser?: Parser2 @@ -4623,7 +4980,7 @@ export interface ImportBlock { * Set of definitions executed before the execution of the block. * */ -export interface Defs18 { +export interface Defs19 { [k: string]: | boolean | number @@ -4639,6 +4996,7 @@ export interface Defs18 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -4655,7 +5013,7 @@ export interface Defs18 { * Block representing an error generated at runtime. */ export interface ErrorBlock { - description?: Description19 + description?: Description20 /** * Type specification of the result of the block. * @@ -4685,7 +5043,7 @@ export interface ErrorBlock { [k: string]: PdlTypeType } | null - defs?: Defs19 + defs?: Defs20 def?: Def1 contribute?: Contribute1 parser?: Parser1 @@ -4707,7 +5065,7 @@ export interface ErrorBlock { * Set of definitions executed before the execution of the block. * */ -export interface Defs19 { +export interface Defs20 { [k: string]: | boolean | number @@ -4723,6 +5081,7 @@ export interface Defs19 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -4739,7 +5098,7 @@ export interface Defs19 { * Block without an action. It can contain definitions. */ export interface EmptyBlock { - description?: Description20 + description?: Description21 /** * Type specification of the result of the block. * @@ -4769,7 +5128,7 @@ export interface EmptyBlock { [k: string]: PdlTypeType } | null - defs?: Defs20 + defs?: Defs21 def?: Def contribute?: Contribute parser?: Parser @@ -4789,7 +5148,7 @@ export interface EmptyBlock { * Set of definitions executed before the execution of the block. * */ -export interface Defs20 { +export interface Defs21 { [k: string]: | boolean | number @@ -4805,6 +5164,7 @@ export interface Defs20 { | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock @@ -4846,7 +5206,7 @@ export interface Table { * Use a PDL program as a parser specification (experimental). */ export interface PdlParser { - description?: Description21 + description?: Description22 spec?: | ( | "null" @@ -4878,7 +5238,7 @@ export interface PdlParser { * A regular expression parser. */ export interface RegexParser { - description?: Description22 + description?: Description23 spec?: | ( | "null" @@ -4941,6 +5301,13 @@ export interface JoinObject { export interface JoinLastOf { as: As3 } +/** + * Join loop iterations as the value of the last iteration. + */ +export interface JoinReduce { + as?: As4 + reduce: Reduce +} /** * Case of a match. */ @@ -4956,21 +5323,21 @@ export interface MatchCase { * Match any of the patterns. */ export interface OrPattern { - def?: Def12 + def?: Def13 anyOf: Anyof } /** * Match an array. */ export interface ArrayPattern { - def?: Def13 + def?: Def14 array: Array1 } /** * Match an object. */ export interface ObjectPattern { - def?: Def14 + def?: Def15 object: Object2 } export interface Object2 { @@ -4988,7 +5355,7 @@ export interface Object2 { * Match any value. */ export interface AnyPattern { - def?: Def15 + def?: Def16 any: Any } /** diff --git a/pdl-live-react/src/pdl_ast_utils.ts b/pdl-live-react/src/pdl_ast_utils.ts index 83f4fb739..2fcef845f 100644 --- a/pdl-live-react/src/pdl_ast_utils.ts +++ b/pdl-live-react/src/pdl_ast_utils.ts @@ -178,6 +178,7 @@ export function map_block_children( }) .with({ kind: "repeat" }, (block) => { const for_ = block?.for ? f_expr(block.for) : undefined + const while_ = block?.until ? f_expr(block.while) : undefined const until = block?.until ? f_expr(block.until) : undefined const max_iterations = block?.maxIterations ? f_expr(block.maxIterations) @@ -186,11 +187,25 @@ export function map_block_children( return { ...block, for: for_, + while: while_, repeat, until, maxIterations: max_iterations, } }) + .with({ kind: "map" }, (block) => { + const for_ = block?.for ? f_expr(block.for) : undefined + const max_iterations = block?.maxIterations + ? f_expr(block.maxIterations) + : undefined + const map = f_block(block.map) + return { + ...block, + for: for_, + map, + maxIterations: max_iterations, + } + }) .with({ kind: "error" }, (block) => { const doc = f_block(block.program) return { ...block, program: doc } @@ -289,6 +304,9 @@ export function iter_block_children( .with({ kind: "repeat" }, (block) => { f(block.repeat) }) + .with({ kind: "map" }, (block) => { + f(block.map) + }) .with({ kind: "error" }, (block) => f(block.program)) .with({ kind: "read" }, () => {}) .with({ kind: "include" }, () => {}) diff --git a/pdl-live-react/src/view/detail/find.ts b/pdl-live-react/src/view/detail/find.ts index bd1ed3f4e..0246f58da 100644 --- a/pdl-live-react/src/view/detail/find.ts +++ b/pdl-live-react/src/view/detail/find.ts @@ -3,6 +3,7 @@ import { childrenOf } from "../timeline/model" import { isNonScalarPdlBlock, nonNullable, + PdlBlock, type NonScalarPdlBlock as Block, } from "../../helpers" @@ -21,7 +22,7 @@ export default function find( } else { return ( childrenOf(block) - .map((child: Block) => find(child, id)) + .map((child: PdlBlock) => find(child, id)) .filter(nonNullable)[0] || null ) } diff --git a/pdl-live-react/src/view/timeline/model.ts b/pdl-live-react/src/view/timeline/model.ts index 5879f9eea..1c1481fc9 100644 --- a/pdl-live-react/src/view/timeline/model.ts +++ b/pdl-live-react/src/view/timeline/model.ts @@ -147,11 +147,12 @@ export function childrenOf(block: NonScalarPdlBlock) { .with({ kind: "object" }, (data) => [data.object]) .with({ kind: "message" }, (data) => [data.content]) .with({ kind: "repeat" }, (data) => [data.pdl__trace ?? data.repeat]) + .with({ kind: "map" }, (data) => [data.pdl__trace ?? data.map]) .with({ kind: "empty" }, (data) => data.defs ? Object.values(data.defs) : [], ) .with({ kind: "error" }, () => []) // TODO show errors in trace - .with({ kind: undefined }, () => []) + .with({ kind: P.nullish }, () => []) // @ts-expect-error: TODO .exhaustive() .flat() diff --git a/src/pdl/pdl-schema.json b/src/pdl/pdl-schema.json index 17a6c3f60..3d9575364 100644 --- a/src/pdl/pdl-schema.json +++ b/src/pdl/pdl-schema.json @@ -98,6 +98,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -244,6 +247,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -497,6 +503,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -643,6 +652,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -851,6 +863,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -1024,6 +1039,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -1170,6 +1188,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -1401,6 +1422,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -1515,6 +1539,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -1661,6 +1688,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -1875,6 +1905,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -2025,6 +2058,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -2171,6 +2207,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -2422,6 +2461,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -2568,6 +2610,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -2813,6 +2858,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -2959,6 +3007,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -3166,6 +3217,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -3281,6 +3335,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -3427,6 +3484,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -3644,6 +3704,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -3774,6 +3837,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -3920,6 +3986,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -4157,6 +4226,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -4303,6 +4375,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -4505,6 +4580,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -4759,6 +4837,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -4905,6 +4986,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -5126,6 +5210,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -5210,6 +5297,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -5326,6 +5416,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -5472,6 +5565,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -5679,6 +5775,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -5793,6 +5892,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -5939,6 +6041,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -6150,6 +6255,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -6253,6 +6361,35 @@ "title": "JoinObject", "type": "object" }, + "JoinReduce": { + "additionalProperties": false, + "description": "Join loop iterations as the value of the last iteration.", + "properties": { + "as": { + "const": "reduce", + "default": "reduce", + "title": "As", + "type": "string" + }, + "reduce": { + "anyOf": [ + { + "$ref": "#/$defs/LocalizedExpression_TypeVar_" + }, + { + "type": "string" + } + ], + "description": "Function used to combine the results.", + "title": "Reduce" + } + }, + "required": [ + "reduce" + ], + "title": "JoinReduce", + "type": "object" + }, "JoinText": { "additionalProperties": false, "description": "Join loop iterations as a string.", @@ -6369,6 +6506,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -6515,6 +6655,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -6723,6 +6866,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -6838,6 +6984,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -6984,6 +7133,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -7186,6 +7338,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -7750,9 +7905,9 @@ "title": "LocalizedExpression", "type": "object" }, - "MatchBlock": { + "MapBlock": { "additionalProperties": false, - "description": "Match control structure.\n\nExample:\n```PDL\ndefs:\n answer:\n read:\n message: \"Enter a number? \"\nmatch: ${ (answer | int) }\nwith:\n- case: 42\n then: You won!\n- case:\n any:\n def: x\n if: ${ x > 42 }\n then: Too high\n- then: Too low", + "description": "Independent executions of a block.\nRepeat the execution of a block starting from the initial scope\nand `pdl_context`.\n\nFor loop example:\n```PDL\nfor:\n number: [1, 2, 3, 4]\n name: [\"Bob\", \"Carol\", \"David\", \"Ernest\"]\nmap:\n \"${ name }'s number is ${ number }\\n\"\n```\n\nBounded loop:\n```PDL\nindex: i\nmaxIterations: 5\nmap:\n ${ i }\njoin:\n as: array\n```", "properties": { "description": { "anyOf": [ @@ -7820,6 +7975,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -7966,6 +8124,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -8120,85 +8281,40 @@ "default": "dependent" }, "kind": { - "const": "match", - "default": "match", + "const": "map", + "default": "map", "title": "Kind", "type": "string" }, - "match": { - "anyOf": [ - { - "$ref": "#/$defs/LocalizedExpression_TypeVar_" - }, - {}, - { - "type": "string" - } - ], - "description": "Matched expression.\n ", - "title": "Match" - }, - "with": { - "description": "List of cases to match.\n ", - "items": { - "$ref": "#/$defs/MatchCase" - }, - "title": "With", - "type": "array" - } - }, - "required": [ - "match", - "with" - ], - "title": "MatchBlock", - "type": "object" - }, - "MatchCase": { - "additionalProperties": false, - "description": "Case of a match.", - "properties": { - "case": { + "for": { "anyOf": [ { - "type": "boolean" - }, - { - "type": "integer" - }, - { - "type": "number" - }, - { - "type": "string" - }, - { - "$ref": "#/$defs/OrPattern" - }, - { - "$ref": "#/$defs/ArrayPattern" - }, - { - "$ref": "#/$defs/ObjectPattern" - }, - { - "$ref": "#/$defs/AnyPattern" + "additionalProperties": { + "anyOf": [ + { + "$ref": "#/$defs/LocalizedExpression_TypeVar_" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + } + ] + }, + "type": "object" }, { "type": "null" } ], "default": null, - "title": "Case" + "description": "Arrays to iterate over.\n ", + "title": "For" }, - "if": { + "index": { "anyOf": [ - { - "$ref": "#/$defs/LocalizedExpression_TypeVar_" - }, - { - "type": "boolean" - }, { "type": "string" }, @@ -8207,9 +8323,10 @@ } ], "default": null, - "title": "If" + "description": "Name of the variable containing the loop iteration.\n ", + "title": "Index" }, - "then": { + "map": { "anyOf": [ { "type": "boolean" @@ -8256,6 +8373,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -8290,67 +8410,767 @@ "type": "null" } ], - "title": "Then" + "description": "Body of the iterator.\n ", + "title": "Map" }, - "pdl__case_result": { + "maxIterations": { "anyOf": [ { - "type": "boolean" + "$ref": "#/$defs/LocalizedExpression_TypeVar_" }, { - "type": "null" - } - ], - "default": null, - "title": "Pdl Case Result" - }, - "pdl__if_result": { - "anyOf": [ + "type": "integer" + }, { - "type": "boolean" + "type": "string" }, { "type": "null" } ], "default": null, - "title": "Pdl If Result" + "description": "Maximal number of iterations to perform.\n ", + "title": "Maxiterations" }, - "pdl__matched": { + "join": { "anyOf": [ { - "type": "boolean" + "$ref": "#/$defs/JoinText" }, { - "type": "null" - } - ], - "default": null, - "title": "Pdl Matched" - } - }, - "required": [ - "then" - ], - "title": "MatchCase", - "type": "object" - }, - "MessageBlock": { - "additionalProperties": false, - "description": "Create a message.", - "properties": { - "description": { - "anyOf": [ + "$ref": "#/$defs/JoinArray" + }, { - "type": "string" + "$ref": "#/$defs/JoinObject" }, { - "type": "null" + "$ref": "#/$defs/JoinLastOf" + }, + { + "$ref": "#/$defs/JoinReduce" } ], - "default": null, - "description": "Documentation associated to the block.\n ", - "title": "Description" + "default": { + "as": "text", + "with": "" + }, + "description": "Define how to combine the result of each iteration.\n ", + "title": "Join" + }, + "pdl__trace": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/$defs/FunctionBlock" + }, + { + "$ref": "#/$defs/CallBlock" + }, + { + "$ref": "#/$defs/LitellmModelBlock" + }, + { + "$ref": "#/$defs/GraniteioModelBlock" + }, + { + "$ref": "#/$defs/CodeBlock" + }, + { + "$ref": "#/$defs/ArgsBlock" + }, + { + "$ref": "#/$defs/GetBlock" + }, + { + "$ref": "#/$defs/DataBlock" + }, + { + "$ref": "#/$defs/IfBlock" + }, + { + "$ref": "#/$defs/MatchBlock" + }, + { + "$ref": "#/$defs/RepeatBlock" + }, + { + "$ref": "#/$defs/MapBlock" + }, + { + "$ref": "#/$defs/TextBlock" + }, + { + "$ref": "#/$defs/LastOfBlock" + }, + { + "$ref": "#/$defs/ArrayBlock" + }, + { + "$ref": "#/$defs/ObjectBlock" + }, + { + "$ref": "#/$defs/MessageBlock" + }, + { + "$ref": "#/$defs/ReadBlock" + }, + { + "$ref": "#/$defs/IncludeBlock" + }, + { + "$ref": "#/$defs/ImportBlock" + }, + { + "$ref": "#/$defs/ErrorBlock" + }, + { + "$ref": "#/$defs/EmptyBlock" + }, + { + "type": "null" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pdl Trace" + } + }, + "required": [ + "map" + ], + "title": "MapBlock", + "type": "object" + }, + "MatchBlock": { + "additionalProperties": false, + "description": "Match control structure.\n\nExample:\n```PDL\ndefs:\n answer:\n read:\n message: \"Enter a number? \"\nmatch: ${ (answer | int) }\nwith:\n- case: 42\n then: You won!\n- case:\n any:\n def: x\n if: ${ x > 42 }\n then: Too high\n- then: Too low", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Documentation associated to the block.\n ", + "title": "Description" + }, + "spec": { + "$ref": "#/$defs/PdlTypeType", + "default": null, + "description": "Type specification of the result of the block.\n " + }, + "defs": { + "additionalProperties": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/$defs/FunctionBlock" + }, + { + "$ref": "#/$defs/CallBlock" + }, + { + "$ref": "#/$defs/LitellmModelBlock" + }, + { + "$ref": "#/$defs/GraniteioModelBlock" + }, + { + "$ref": "#/$defs/CodeBlock" + }, + { + "$ref": "#/$defs/ArgsBlock" + }, + { + "$ref": "#/$defs/GetBlock" + }, + { + "$ref": "#/$defs/DataBlock" + }, + { + "$ref": "#/$defs/IfBlock" + }, + { + "$ref": "#/$defs/MatchBlock" + }, + { + "$ref": "#/$defs/RepeatBlock" + }, + { + "$ref": "#/$defs/MapBlock" + }, + { + "$ref": "#/$defs/TextBlock" + }, + { + "$ref": "#/$defs/LastOfBlock" + }, + { + "$ref": "#/$defs/ArrayBlock" + }, + { + "$ref": "#/$defs/ObjectBlock" + }, + { + "$ref": "#/$defs/MessageBlock" + }, + { + "$ref": "#/$defs/ReadBlock" + }, + { + "$ref": "#/$defs/IncludeBlock" + }, + { + "$ref": "#/$defs/ImportBlock" + }, + { + "$ref": "#/$defs/ErrorBlock" + }, + { + "$ref": "#/$defs/EmptyBlock" + }, + { + "type": "null" + } + ] + }, + "default": {}, + "description": "Set of definitions executed before the execution of the block.\n ", + "title": "Defs", + "type": "object" + }, + "def": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Name of the variable used to store the result of the execution of the block.\n ", + "title": "Def" + }, + "contribute": { + "default": [ + "result", + "context" + ], + "description": "Indicate if the block contributes to the result and background context.\n ", + "items": { + "anyOf": [ + { + "$ref": "#/$defs/ContributeTarget" + }, + { + "additionalProperties": { + "$ref": "#/$defs/ContributeValue" + }, + "type": "object" + } + ] + }, + "title": "Contribute", + "type": "array" + }, + "parser": { + "anyOf": [ + { + "enum": [ + "json", + "jsonl", + "yaml" + ], + "type": "string" + }, + { + "$ref": "#/$defs/PdlParser" + }, + { + "$ref": "#/$defs/RegexParser" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Parser to use to construct a value out of a string result.", + "title": "Parser" + }, + "fallback": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/$defs/FunctionBlock" + }, + { + "$ref": "#/$defs/CallBlock" + }, + { + "$ref": "#/$defs/LitellmModelBlock" + }, + { + "$ref": "#/$defs/GraniteioModelBlock" + }, + { + "$ref": "#/$defs/CodeBlock" + }, + { + "$ref": "#/$defs/ArgsBlock" + }, + { + "$ref": "#/$defs/GetBlock" + }, + { + "$ref": "#/$defs/DataBlock" + }, + { + "$ref": "#/$defs/IfBlock" + }, + { + "$ref": "#/$defs/MatchBlock" + }, + { + "$ref": "#/$defs/RepeatBlock" + }, + { + "$ref": "#/$defs/MapBlock" + }, + { + "$ref": "#/$defs/TextBlock" + }, + { + "$ref": "#/$defs/LastOfBlock" + }, + { + "$ref": "#/$defs/ArrayBlock" + }, + { + "$ref": "#/$defs/ObjectBlock" + }, + { + "$ref": "#/$defs/MessageBlock" + }, + { + "$ref": "#/$defs/ReadBlock" + }, + { + "$ref": "#/$defs/IncludeBlock" + }, + { + "$ref": "#/$defs/ImportBlock" + }, + { + "$ref": "#/$defs/ErrorBlock" + }, + { + "$ref": "#/$defs/EmptyBlock" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Block to execute in case of error.\n ", + "title": "Fallback" + }, + "retry": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The maximum number of times to retry when an error occurs within a block.\n ", + "title": "Retry" + }, + "trace_error_on_retry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Whether to add the errors while retrying to the trace. Set this to true to use retry feature for multiple LLM trials.\n ", + "title": "Trace Error On Retry" + }, + "role": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Role associated to the block and sub-blocks.\nTypical roles are `system`, `user`, and `assistant`,\nbut there may be other roles such as `available_tools`.", + "title": "Role" + }, + "pdl__context": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": [], + "description": "Current context\n ", + "title": "Pdl Context" + }, + "pdl__id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "", + "description": "Unique identifier for this block\n ", + "title": "Pdl Id" + }, + "pdl__result": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "description": "Result of the execution of the block", + "title": "Pdl Result" + }, + "pdl__location": { + "anyOf": [ + { + "$ref": "#/$defs/PdlLocationType" + }, + { + "type": "null" + } + ], + "default": null + }, + "pdl__timing": { + "anyOf": [ + { + "$ref": "#/$defs/PdlTiming" + }, + { + "type": "null" + } + ], + "default": null + }, + "pdl__is_leaf": { + "const": false, + "default": false, + "title": "Pdl Is Leaf", + "type": "boolean" + }, + "context": { + "$ref": "#/$defs/IndependentEnum", + "default": "dependent" + }, + "kind": { + "const": "match", + "default": "match", + "title": "Kind", + "type": "string" + }, + "match": { + "anyOf": [ + { + "$ref": "#/$defs/LocalizedExpression_TypeVar_" + }, + {}, + { + "type": "string" + } + ], + "description": "Matched expression.\n ", + "title": "Match" + }, + "with": { + "description": "List of cases to match.\n ", + "items": { + "$ref": "#/$defs/MatchCase" + }, + "title": "With", + "type": "array" + } + }, + "required": [ + "match", + "with" + ], + "title": "MatchBlock", + "type": "object" + }, + "MatchCase": { + "additionalProperties": false, + "description": "Case of a match.", + "properties": { + "case": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/$defs/OrPattern" + }, + { + "$ref": "#/$defs/ArrayPattern" + }, + { + "$ref": "#/$defs/ObjectPattern" + }, + { + "$ref": "#/$defs/AnyPattern" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Case" + }, + "if": { + "anyOf": [ + { + "$ref": "#/$defs/LocalizedExpression_TypeVar_" + }, + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "If" + }, + "then": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/$defs/FunctionBlock" + }, + { + "$ref": "#/$defs/CallBlock" + }, + { + "$ref": "#/$defs/LitellmModelBlock" + }, + { + "$ref": "#/$defs/GraniteioModelBlock" + }, + { + "$ref": "#/$defs/CodeBlock" + }, + { + "$ref": "#/$defs/ArgsBlock" + }, + { + "$ref": "#/$defs/GetBlock" + }, + { + "$ref": "#/$defs/DataBlock" + }, + { + "$ref": "#/$defs/IfBlock" + }, + { + "$ref": "#/$defs/MatchBlock" + }, + { + "$ref": "#/$defs/RepeatBlock" + }, + { + "$ref": "#/$defs/MapBlock" + }, + { + "$ref": "#/$defs/TextBlock" + }, + { + "$ref": "#/$defs/LastOfBlock" + }, + { + "$ref": "#/$defs/ArrayBlock" + }, + { + "$ref": "#/$defs/ObjectBlock" + }, + { + "$ref": "#/$defs/MessageBlock" + }, + { + "$ref": "#/$defs/ReadBlock" + }, + { + "$ref": "#/$defs/IncludeBlock" + }, + { + "$ref": "#/$defs/ImportBlock" + }, + { + "$ref": "#/$defs/ErrorBlock" + }, + { + "$ref": "#/$defs/EmptyBlock" + }, + { + "type": "null" + } + ], + "title": "Then" + }, + "pdl__case_result": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pdl Case Result" + }, + "pdl__if_result": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pdl If Result" + }, + "pdl__matched": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pdl Matched" + } + }, + "required": [ + "then" + ], + "title": "MatchCase", + "type": "object" + }, + "MessageBlock": { + "additionalProperties": false, + "description": "Create a message.", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Documentation associated to the block.\n ", + "title": "Description" }, "spec": { "$ref": "#/$defs/PdlTypeType", @@ -8405,6 +9225,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -8551,6 +9374,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -8753,6 +9579,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -8899,6 +9728,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -9045,6 +9877,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -9254,6 +10089,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -9339,6 +10177,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -9581,6 +10422,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -9715,6 +10559,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -9941,6 +10788,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -10048,6 +10898,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -10194,6 +11047,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -10435,7 +11291,7 @@ }, "RepeatBlock": { "additionalProperties": false, - "description": "Repeat the execution of a block.\n\nFor loop example:\n```PDL\nfor:\n number: [1, 2, 3, 4]\n name: [\"Bob\", \"Carol\", \"David\", \"Ernest\"]\nrepeat:\n \"${ name }'s number is ${ number }\\n\"\n```\n\nBounded loop:\n```PDL\nindex: i\nmaxIterations: 5\nrepeat:\n ${ i }\njoin:\n as: array\n```", + "description": "Repeat the execution of a block sequentially.\nThe scope and `pdl_context` are accumulated in between iterations.\n\nFor loop example:\n```PDL\nfor:\n number: [1, 2, 3, 4]\n name: [\"Bob\", \"Carol\", \"David\", \"Ernest\"]\nrepeat:\n \"${ name }'s number is ${ number }\\n\"\n```\n\nWhile loop:\n```PDL\ndefs:\n i: 0\nwhile: ${i < 5}\nrepeat:\n defs:\n i: ${ i + 1}\n data: ${ i }\njoin:\n as: array\n```", "properties": { "description": { "anyOf": [ @@ -10503,6 +11359,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -10649,6 +11508,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -10911,6 +11773,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -10996,6 +11861,9 @@ }, { "$ref": "#/$defs/JoinLastOf" + }, + { + "$ref": "#/$defs/JoinReduce" } ], "default": { @@ -11055,6 +11923,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -11176,6 +12047,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -11322,6 +12196,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -11528,6 +12405,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, @@ -11606,6 +12486,9 @@ { "$ref": "#/$defs/RepeatBlock" }, + { + "$ref": "#/$defs/MapBlock" + }, { "$ref": "#/$defs/TextBlock" }, diff --git a/src/pdl/pdl_ast.py b/src/pdl/pdl_ast.py index cc6b03a8e..6f0224ca6 100644 --- a/src/pdl/pdl_ast.py +++ b/src/pdl/pdl_ast.py @@ -5,6 +5,7 @@ from typing import ( Annotated, Any, + Callable, Generic, Literal, Mapping, @@ -61,6 +62,7 @@ class BlockKind(StrEnum): IF = "if" MATCH = "match" REPEAT = "repeat" + MAP = "map" READ = "read" INCLUDE = "include" IMPORT = "import" @@ -788,23 +790,18 @@ class MatchBlock(StructuredBlock): """ -class IterationType(StrEnum): - LASTOF = "lastOf" - ARRAY = "array" - OBJECT = "object" - TEXT = "text" - - class JoinConfig(BaseModel): """Configure how loop iterations should be combined.""" - model_config = ConfigDict(extra="forbid", use_attribute_docstrings=True) + model_config = ConfigDict( + extra="forbid", use_attribute_docstrings=True, validate_by_name=True + ) class JoinText(JoinConfig): """Join loop iterations as a string.""" - as_: Literal[IterationType.TEXT] = Field(alias="as", default=IterationType.TEXT) + as_: Literal["text"] = Field(alias="as", default="text") """String concatenation of the result of each iteration. """ @@ -816,7 +813,7 @@ class JoinText(JoinConfig): class JoinArray(JoinConfig): """Join loop iterations as an array.""" - as_: Literal[IterationType.ARRAY] = Field(alias="as") + as_: Literal["array"] = Field(alias="as") """Return the result of each iteration as an array. """ @@ -824,7 +821,7 @@ class JoinArray(JoinConfig): class JoinObject(JoinConfig): """Join loop iterations as an object.""" - as_: Literal[IterationType.OBJECT] = Field(alias="as") + as_: Literal["object"] = Field(alias="as") """Return the union of the objects created at each iteration. """ @@ -832,18 +829,28 @@ class JoinObject(JoinConfig): class JoinLastOf(JoinConfig): """Join loop iterations as the value of the last iteration.""" - as_: Literal[IterationType.LASTOF] = Field(alias="as") + as_: Literal["lastOf"] = Field(alias="as") """Return the result of the last iteration. """ -JoinType: TypeAlias = JoinText | JoinArray | JoinObject | JoinLastOf +class JoinReduce(JoinConfig): + """Join loop iterations as the value of the last iteration.""" + + as_: Literal["reduce"] = Field(alias="as", default="reduce") + + reduce: ExpressionType[Callable] + """Function used to combine the results.""" + + +JoinType: TypeAlias = JoinText | JoinArray | JoinObject | JoinLastOf | JoinReduce """Different ways to join loop iterations.""" class RepeatBlock(StructuredBlock): """ - Repeat the execution of a block. + Repeat the execution of a block sequentially. + The scope and `pdl_context` are accumulated in between iterations. For loop example: ```PDL @@ -854,12 +861,15 @@ class RepeatBlock(StructuredBlock): "${ name }'s number is ${ number }\\n" ``` - Bounded loop: + While loop: ```PDL - index: i - maxIterations: 5 + defs: + i: 0 + while: ${i < 5} repeat: - ${ i } + defs: + i: ${ i + 1} + data: ${ i } join: as: array ``` @@ -891,6 +901,52 @@ class RepeatBlock(StructuredBlock): pdl__trace: Optional[list["BlockType"]] = None +class MapBlock(StructuredBlock): + """ + Independent executions of a block. + Repeat the execution of a block starting from the initial scope + and `pdl_context`. + + For loop example: + ```PDL + for: + number: [1, 2, 3, 4] + name: ["Bob", "Carol", "David", "Ernest"] + map: + "${ name }'s number is ${ number }\\n" + ``` + + Bounded loop: + ```PDL + index: i + maxIterations: 5 + map: + ${ i } + join: + as: array + ``` + """ + + kind: Literal[BlockKind.MAP] = BlockKind.MAP + for_: Optional[dict[str, ExpressionType[list]]] = Field(default=None, alias="for") + """Arrays to iterate over. + """ + index: Optional[str] = None + """Name of the variable containing the loop iteration. + """ + map: "BlockType" + """Body of the iterator. + """ + maxIterations: Optional[ExpressionType[int]] = None + """Maximal number of iterations to perform. + """ + join: JoinType = JoinText() + """Define how to combine the result of each iteration. + """ + # Field for internal use + pdl__trace: Optional[list["BlockType"]] = None + + class ReadBlock(LeafBlock): """Read from a file or standard input. @@ -971,6 +1027,7 @@ class EmptyBlock(LeafBlock): | IfBlock | MatchBlock | RepeatBlock + | MapBlock | TextBlock | LastOfBlock | ArrayBlock diff --git a/src/pdl/pdl_ast_utils.py b/src/pdl/pdl_ast_utils.py index 241662680..dc8b0a650 100644 --- a/src/pdl/pdl_ast_utils.py +++ b/src/pdl/pdl_ast_utils.py @@ -19,6 +19,7 @@ IncludeBlock, LastOfBlock, LitellmModelBlock, + MapBlock, MatchBlock, MatchCase, MessageBlock, @@ -85,6 +86,11 @@ def iter_block_children(f: Callable[[BlockType], None], block: BlockType) -> Non if block.pdl__trace is not None: for trace in block.pdl__trace: f(trace) + case MapBlock(): + f(block.map) + if block.pdl__trace is not None: + for trace in block.pdl__trace: + f(trace) case ErrorBlock(): f(block.program) case ReadBlock(): @@ -191,6 +197,12 @@ def map_block_children(f: MappedFunctions, block: BlockType) -> BlockType: block.until = f.f_expr(block.until) if block.pdl__trace is not None: block.pdl__trace = [f.f_block(trace) for trace in block.pdl__trace] + case MapBlock(): + if block.for_ is not None: + block.for_ = {x: f.f_expr(blocks) for x, blocks in block.for_.items()} + block.map = f.f_block(block.map) + if block.pdl__trace is not None: + block.pdl__trace = [f.f_block(trace) for trace in block.pdl__trace] case ErrorBlock(): block.program = f.f_block(block.program) case ReadBlock(): diff --git a/src/pdl/pdl_compilers/to_regex.py b/src/pdl/pdl_compilers/to_regex.py index 602e81a0c..cbfc246f4 100644 --- a/src/pdl/pdl_compilers/to_regex.py +++ b/src/pdl/pdl_compilers/to_regex.py @@ -18,6 +18,7 @@ LitellmModelBlock, LitellmParameters, LocalizedExpression, + MapBlock, ModelBlock, ReadBlock, RepeatBlock, @@ -312,6 +313,10 @@ def compile_block( body, scope = compile_block(scope, block.repeat) # XXX TODO: join char in text mode XXX regex = ReStar(body) + case MapBlock(): + body, scope = compile_block(scope, block.map) + # XXX TODO: join char in text mode XXX + regex = ReStar(body) case ReadBlock(): regex = ReStar(ReAnyChar()) case IncludeBlock(): diff --git a/src/pdl/pdl_dumper.py b/src/pdl/pdl_dumper.py index bcd3f9379..3e6f2ace5 100644 --- a/src/pdl/pdl_dumper.py +++ b/src/pdl/pdl_dumper.py @@ -29,6 +29,10 @@ IfBlock, ImportBlock, IncludeBlock, + JoinArray, + JoinLastOf, + JoinObject, + JoinReduce, JoinText, JoinType, JsonSchemaTypePdlType, @@ -36,6 +40,7 @@ LitellmModelBlock, LitellmParameters, LocalizedExpression, + MapBlock, MatchBlock, MessageBlock, ObjectBlock, @@ -243,7 +248,20 @@ def block_to_dict( # noqa: C901 d["until"] = expr_to_dict(block.until, json_compatible) if block.maxIterations is not None: d["maxIterations"] = expr_to_dict(block.maxIterations, json_compatible) - d["join"] = join_to_dict(block.join) + d["join"] = join_to_dict(block.join, json_compatible) + if block.pdl__trace is not None: + d["pdl__trace"] = [ + block_to_dict(b, json_compatible) for b in block.pdl__trace + ] + case MapBlock(): + if block.for_ is not None: + d["for"] = expr_to_dict(block.for_, json_compatible) + if block.index is not None: + d["index"] = block.index + d["map"] = block_to_dict(block.map, json_compatible) + if block.maxIterations is not None: + d["maxIterations"] = expr_to_dict(block.maxIterations, json_compatible) + d["join"] = join_to_dict(block.join, json_compatible) if block.pdl__trace is not None: d["pdl__trace"] = [ block_to_dict(b, json_compatible) for b in block.pdl__trace @@ -402,13 +420,17 @@ def pattern_to_dict(pattern: PatternType): return result -def join_to_dict(join: JoinType) -> dict[str, Any]: - d = {} +def join_to_dict(join: JoinType, json_compatible: bool) -> dict[str, Any]: + d: dict[str, Any] = {} match join: case JoinText(): d["with"] = join.with_ - case _: + case JoinArray() | JoinObject() | JoinLastOf(): d["as"] = str(join.as_) + case JoinReduce(): + d["reduce"] = expr_to_dict(join.reduce, json_compatible) + case _: + assert False return d diff --git a/src/pdl/pdl_interpreter.py b/src/pdl/pdl_interpreter.py index 4e332b917..d0fb3aa51 100644 --- a/src/pdl/pdl_interpreter.py +++ b/src/pdl/pdl_interpreter.py @@ -11,13 +11,21 @@ # TODO: temporarily disabling warnings to mute a pydantic warning from liteLLM import warnings from asyncio import AbstractEventLoop -from functools import partial +from functools import partial, reduce from os import getenv warnings.filterwarnings("ignore", "Valid config keys have changed in V2") from pathlib import Path # noqa: E402 -from typing import Any, Generator, Generic, Optional, Sequence, TypeVar # noqa: E402 +from typing import ( # noqa: E402 + Any, + Generator, + Generic, + Optional, + Sequence, + Tuple, + TypeVar, +) import httpx # noqa: E402 import json_repair # noqa: E402 @@ -60,13 +68,19 @@ ImportBlock, IncludeBlock, IndependentEnum, - IterationType, + JoinArray, + JoinLastOf, + JoinObject, + JoinReduce, + JoinText, + JoinType, LastOfBlock, LazyMessage, LazyMessages, LitellmModelBlock, LitellmParameters, LocalizedExpression, + MapBlock, MatchBlock, MessageBlock, ModelBlock, @@ -627,7 +641,7 @@ def process_block_body( result, background, scope, trace = process_blocks_of( block, "text", - IterationType.TEXT, + JoinText(), state, scope, loc, @@ -636,7 +650,7 @@ def process_block_body( result, background, scope, trace = process_blocks_of( block, "lastOf", - IterationType.LASTOF, + JoinLastOf(as_="lastOf"), # pyright: ignore state, scope, loc, @@ -645,7 +659,7 @@ def process_block_body( result, background, scope, trace = process_blocks_of( block, "array", - IterationType.ARRAY, + JoinArray(as_="array"), # pyright: ignore state, scope, loc, @@ -664,7 +678,7 @@ def process_block_body( if isinstance(value_blocks, StructuredBlock): context = value_blocks.context value, value_background, scope, value_trace = process_blocks( - IterationType.LASTOF, + JoinLastOf(as_="lastOf"), # pyright: ignore context, iteration_state, scope, @@ -701,7 +715,7 @@ def process_block_body( result, background, scope, trace = process_blocks_of( block, "object", - IterationType.OBJECT, + JoinObject(as_="object"), # pyright: ignore iteration_state, scope, loc, @@ -827,46 +841,12 @@ def process_block_body( background = DependentContext([]) iter_trace: list[BlockType] = [] pdl_context_init = scope_init.data["pdl_context"] - if block.for_ is None: - items = None - lengths = None - else: - items, block = process_expr_of(block, "for_", scope, loc, "for") - lengths = [] - for idx, lst in items.items(): - if not isinstance(lst, list): - msg = f"Values inside the For block must be lists but got {type(lst)}." - lst_loc = append( - append(block.pdl__location or empty_block_location, "for"), - idx, - ) - raise PDLRuntimeError( - message=msg, - loc=lst_loc, - trace=ErrorBlock( - msg=msg, pdl__location=lst_loc, program=block - ), - fallback=[], - ) - lengths.append(len(lst)) - if len(set(lengths)) != 1: # Not all the lists are of the same length - msg = "Lists inside the For block must be of the same length." - for_loc = append(block.pdl__location or empty_block_location, "for") - raise PDLRuntimeError( - msg, - loc=for_loc, - trace=ErrorBlock(msg=msg, pdl__location=for_loc, program=block), - fallback=[], - ) iteration_state = state.with_yield_result( - state.yield_result and block.join.as_ == IterationType.TEXT + state.yield_result and isinstance(block.join, JoinText) ) - if block.maxIterations is None: - max_iterations = None - else: - max_iterations, block = process_expr_of( - block, "maxIterations", scope, loc - ) + block, items, length = _evaluate_for_field(scope, block, loc) + block, max_iterations = _evaluate_max_iterations_field(scope, block, loc) + block = _evaluate_join_field(scope, block, loc) repeat_loc = append(loc, "repeat") iidx = 0 try: @@ -877,7 +857,7 @@ def process_block_body( scope = scope | {block.index: iidx} if max_iterations is not None and iidx >= max_iterations: break - if lengths is not None and iidx >= lengths[0]: + if length is not None and iidx >= length: break stay, _ = process_condition_of(block, "while_", scope, loc, "while") if not stay: @@ -885,9 +865,8 @@ def process_block_body( iteration_state = iteration_state.with_iter(iidx) if first: first = False - elif block.join.as_ == IterationType.TEXT: + elif isinstance(block.join, JoinText): join_string = block.join.with_ - results.append(PdlConst(join_string)) if iteration_state.yield_result: yield_result(join_string, block.kind) if iteration_state.yield_background: @@ -921,13 +900,11 @@ def process_block_body( saved_background = DependentContext( [saved_background, iteration_background] ) + background = saved_background else: saved_background = IndependentContext( [saved_background, iteration_background] ) - - if block.context is IndependentEnum.DEPENDENT: - background = saved_background results.append(iteration_result) iter_trace.append(body_trace) iteration_state = iteration_state.with_pop() @@ -943,12 +920,67 @@ def process_block_body( loc=exc.loc or repeat_loc, trace=trace, ) from exc - result = combine_results(block.join.as_, results) + result = combine_results(block.join, results) if block.context is IndependentEnum.INDEPENDENT: background = saved_background if state.yield_result and not iteration_state.yield_result: yield_result(result.result(), block.kind) trace = block.model_copy(update={"pdl__trace": iter_trace}) + case MapBlock(): + results = [] + background = DependentContext([]) + iter_trace = [] + iteration_state = state.with_yield_result(False) + block, items, length = _evaluate_for_field(scope, block, loc) + block, max_iterations = _evaluate_max_iterations_field(scope, block, loc) + block = _evaluate_join_field(scope, block, loc) + map_loc = append(loc, "map") + iidx = 0 + try: + saved_background = IndependentContext([]) + while True: + iteration_scope = scope_init + if block.index is not None: + iteration_scope = iteration_scope | {block.index: iidx} + if max_iterations is not None and iidx >= max_iterations: + break + if length is not None and iidx >= length: + break + iteration_state = iteration_state.with_iter(iidx) + if items is not None: + for k in items.keys(): + iteration_scope = iteration_scope | {k: items[k][iidx]} + ( + iteration_result, + iteration_background, + iteration_scope, + body_trace, + ) = process_block( + iteration_state, + iteration_scope, + block.map, + map_loc, + ) + saved_background = IndependentContext( + [saved_background, iteration_background] + ) + results.append(iteration_result) + iter_trace.append(body_trace) + iteration_state = iteration_state.with_pop() + iidx = iidx + 1 + except PDLRuntimeError as exc: + iter_trace.append(exc.pdl__trace) + trace = block.model_copy(update={"pdl__trace": iter_trace}) + raise PDLRuntimeError( + exc.message, + loc=exc.loc or map_loc, + trace=trace, + ) from exc + result = combine_results(block.join, results) + # background = saved_background # commented because the block do not contribute to the background + if state.yield_result and not iteration_state.yield_result: + yield_result(result.result(), block.kind) + trace = block.model_copy(update={"pdl__trace": iter_trace}) case ReadBlock(): result, background, scope, trace = process_input(state, scope, block, loc) if state.yield_result: @@ -1008,6 +1040,75 @@ def process_block_body( return result, background, scope, trace +BlockTVarEvalFor = TypeVar("BlockTVarEvalFor", bound=RepeatBlock | MapBlock) + + +def _evaluate_for_field( + scope: ScopeType, block: BlockTVarEvalFor, loc: PdlLocationType +) -> Tuple[BlockTVarEvalFor, Optional[dict[str, list]], Optional[int]]: + if block.for_ is None: + items = None + length = None + else: + items, block = process_expr_of(block, "for_", scope, loc, "for") + lengths = [] + for idx, lst in items.items(): + if not isinstance(lst, list): + msg = f"Values inside the For block must be lists but got {type(lst)}." + lst_loc = append( + append(block.pdl__location or empty_block_location, "for"), + idx, + ) + raise PDLRuntimeError( + message=msg, + loc=lst_loc, + trace=ErrorBlock(msg=msg, pdl__location=lst_loc, program=block), + fallback=[], + ) + lengths.append(len(lst)) + if len(set(lengths)) != 1: # Not all the lists are of the same length + msg = "Lists inside the For block must be of the same length." + for_loc = append(block.pdl__location or empty_block_location, "for") + raise PDLRuntimeError( + msg, + loc=for_loc, + trace=ErrorBlock(msg=msg, pdl__location=for_loc, program=block), + fallback=[], + ) + length = lengths[0] + return block, items, length + + +BlockTVarEvalMaxIter = TypeVar("BlockTVarEvalMaxIter", bound=RepeatBlock | MapBlock) + + +def _evaluate_max_iterations_field( + scope: ScopeType, block: BlockTVarEvalMaxIter, loc: PdlLocationType +) -> Tuple[BlockTVarEvalMaxIter, Optional[int]]: + if block.maxIterations is None: + max_iterations = None + else: + max_iterations, block = process_expr_of(block, "maxIterations", scope, loc) + return block, max_iterations + + +BlockTVarEvalJoin = TypeVar("BlockTVarEvalJoin", bound=RepeatBlock | MapBlock) + + +def _evaluate_join_field( + scope: ScopeType, block: BlockTVarEvalJoin, loc: PdlLocationType +) -> BlockTVarEvalJoin: + match block.join: + case JoinText() | JoinArray() | JoinObject() | JoinLastOf(): + pass + case JoinReduce(): + loc = append(loc, "reduce") + _, expr = process_expr(scope, block.join.reduce, loc) + join = block.join.model_copy(update={"reduce": expr}) + block = block.model_copy(update={"join": join}) + return block + + def is_matching( # pylint: disable=too-many-return-statements value: Any, pattern: PatternType, scope: ScopeType ) -> Optional[ScopeType]: @@ -1124,7 +1225,7 @@ def process_block_of( # pylint: disable=too-many-arguments, too-many-positional def process_blocks_of( # pylint: disable=too-many-arguments, too-many-positional-arguments block: BlockTypeTVarProcessBlocksOf, field: str, - iteration_type: IterationType, + join_type: JoinType, state: InterpreterState, scope: ScopeType, loc: PdlLocationType, @@ -1135,7 +1236,7 @@ def process_blocks_of( # pylint: disable=too-many-arguments, too-many-positiona if isinstance(block, StructuredBlock): context = block.context result, background, scope, blocks = process_blocks( - iteration_type, + join_type, context, state, scope, @@ -1155,7 +1256,7 @@ def process_blocks_of( # pylint: disable=too-many-arguments, too-many-positiona def process_blocks( # pylint: disable=too-many-arguments,too-many-positional-arguments - iteration_type: IterationType, + join_type: JoinType, context: IndependentEnum, state: InterpreterState, scope: ScopeType, @@ -1170,8 +1271,7 @@ def process_blocks( # pylint: disable=too-many-arguments,too-many-positional-ar if not isinstance(blocks, str) and isinstance(blocks, Sequence): # Is a list of blocks iteration_state = state.with_yield_result( - state.yield_result - and (iteration_type in (IterationType.LASTOF, IterationType.TEXT)) + state.yield_result and isinstance(join_type, (JoinLastOf, JoinText)) ) new_loc = None background = DependentContext([]) @@ -1185,7 +1285,7 @@ def process_blocks( # pylint: disable=too-many-arguments,too-many-positional-ar "pdl_context": DependentContext([pdl_context_init, background]) } new_loc = append(loc, "[" + str(i) + "]") - if iteration_type == IterationType.LASTOF and state.yield_result: + if isinstance(join_type, JoinLastOf) and state.yield_result: iteration_state = state.with_yield_result(i + 1 == len(blocks)) ( iteration_result, @@ -1216,35 +1316,46 @@ def process_blocks( # pylint: disable=too-many-arguments,too-many-positional-ar ) from exc else: iteration_state = state.with_yield_result( - state.yield_result and iteration_type != IterationType.ARRAY + state.yield_result and not isinstance(join_type, JoinArray) ) block_result, background, scope, trace = process_block( iteration_state, scope, blocks, loc ) results.append(block_result) - result = combine_results(iteration_type, results) + result = combine_results(join_type, results) if state.yield_result and not iteration_state.yield_result: yield_result(result, block_kind) return result, background, scope, trace -def combine_results(iteration_type: IterationType, results: list[PdlLazy[Any]]): +def combine_results(join_type: JoinType, results: list[PdlLazy[Any]]): result: Any - match iteration_type: - case IterationType.ARRAY: + match join_type: + case JoinArray(): result = PdlList(results) - case IterationType.OBJECT: + case JoinObject(): result = PdlDict({}) for d in results: result = result | d - case IterationType.LASTOF: + case JoinLastOf(): if len(results) > 0: result = results[-1] else: result = None - case IterationType.TEXT: + case JoinText(): + join_str = join_type.with_ result = lazy_apply( - (lambda _: "".join([stringify(r.result()) for r in results])), + (lambda _: join_str.join([stringify(r.result()) for r in results])), + PdlConst(()), + ) + case JoinReduce(): + result = lazy_apply( + ( + lambda _: reduce( + value_of_expr(join_type.reduce), + [r.result() for r in results], + ) + ), PdlConst(()), ) case _: diff --git a/src/pdl/pdl_parser.py b/src/pdl/pdl_parser.py index 3752b36f3..201e5db79 100644 --- a/src/pdl/pdl_parser.py +++ b/src/pdl/pdl_parser.py @@ -139,6 +139,11 @@ def parse_dict( # if block.pdl__trace is not None: # for trace in block.pdl__trace: # iter_blocks(f, trace) +# case MapBlock(): +# iter_blocks(f, block.map) +# if block.pdl__trace is not None: +# for trace in block.pdl__trace: +# iter_blocks(f, trace) # case ErrorBlock(): # iter_blocks(f, block.program) # case ReadBlock(): diff --git a/src/pdl/pdl_scheduler.py b/src/pdl/pdl_scheduler.py index 5e126ae7f..04e725476 100644 --- a/src/pdl/pdl_scheduler.py +++ b/src/pdl/pdl_scheduler.py @@ -51,6 +51,8 @@ def color_of(kind: BlockKind): color = None case BlockKind.REPEAT: color = None + case BlockKind.MAP: + color = None case BlockKind.READ: color = None case BlockKind.INCLUDE: diff --git a/tests/results/examples/map-reduce/python-reduce.0.result b/tests/results/examples/map-reduce/python-reduce.0.result new file mode 100644 index 000000000..9a037142a --- /dev/null +++ b/tests/results/examples/map-reduce/python-reduce.0.result @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/tests/results/examples/map-reduce/reduce.0.result b/tests/results/examples/map-reduce/reduce.0.result new file mode 100644 index 000000000..9a037142a --- /dev/null +++ b/tests/results/examples/map-reduce/reduce.0.result @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/tests/test_for.py b/tests/test_for.py index b7a4b4b43..88cdaf20f 100644 --- a/tests/test_for.py +++ b/tests/test_for.py @@ -3,160 +3,338 @@ from pdl.pdl import exec_dict, exec_str from pdl.pdl_interpreter import PDLRuntimeError -for_data = { - "description": "For block example", - "text": [ - { - "for": { - "i": [1, 2, 3, 4], - }, - "repeat": "${ i }\n", - } - ], -} + +def for_data(loop_kind): + return { + "description": "For block example", + "text": [ + { + "for": { + "i": [1, 2, 3, 4], + }, + loop_kind: "${ i }\n", + } + ], + } def test_for_data(): - text = exec_dict(for_data) - assert text == "1\n2\n3\n4\n" + for loop_kind in ["repeat", "map"]: + text = exec_dict(for_data(loop_kind)) + assert text == "1\n2\n3\n4\n" -for_data1 = { - "description": "For block example", - "text": [ - { - "for": {"i": [1, 2, 3, 4], "name": ["A", "B", "C", "D"]}, - "repeat": "${ i }: ${ name }\n", - } - ], -} +def for_data1(loop_kind): + return { + "description": "For block example", + "text": [ + { + "for": {"i": [1, 2, 3, 4], "name": ["A", "B", "C", "D"]}, + loop_kind: "${ i }: ${ name }\n", + } + ], + } def test_for_data1(): - text = exec_dict(for_data1) - assert text == "1: A\n2: B\n3: C\n4: D\n" - - -for_data2 = { - "description": "For block example", - "defs": {"ids": {"data": [5, 6, 7, 8]}}, - "text": [ - { - "for": {"i": [1, 2, 3, 4], "name": ["A", "B", "C", "D"], "id": "${ ids }"}, - "repeat": "${ i }: ${ name }: ${ id }\n", - } - ], -} + for loop_kind in ["repeat", "map"]: + text = exec_dict(for_data1(loop_kind)) + assert text == "1: A\n2: B\n3: C\n4: D\n" + + +def for_data2(loop_kind): + return { + "description": "For block example", + "defs": {"ids": {"data": [5, 6, 7, 8]}}, + "text": [ + { + "for": { + "i": [1, 2, 3, 4], + "name": ["A", "B", "C", "D"], + "id": "${ ids }", + }, + loop_kind: "${ i }: ${ name }: ${ id }\n", + } + ], + } def test_for_data2(): - text = exec_dict(for_data2) - assert text == "1: A: 5\n2: B: 6\n3: C: 7\n4: D: 8\n" - - -for_data3 = { - "description": "For block example", - "defs": {"ids": {"data": [5, 6]}}, - "text": [ - { - "for": {"i": [1, 2, 3, 4], "name": ["A", "B", "C", "D"], "id": "${ ids }"}, - "repeat": "${ i }: ${ name }: ${ id }\n", - "join": {"as": "array"}, - } - ], -} + for loop_kind in ["repeat", "map"]: + text = exec_dict(for_data2(loop_kind)) + assert text == "1: A: 5\n2: B: 6\n3: C: 7\n4: D: 8\n" + + +def for_data3(loop_kind): + return { + "description": "For block example", + "defs": {"ids": {"data": [5, 6]}}, + "text": [ + { + "for": { + "i": [1, 2, 3, 4], + "name": ["A", "B", "C", "D"], + "id": "${ ids }", + }, + loop_kind: "${ i }: ${ name }: ${ id }\n", + "join": {"as": "array"}, + } + ], + } def test_for_data3(): with pytest.raises(PDLRuntimeError): - exec_dict(for_data3) + for loop_kind in ["repeat", "map"]: + exec_dict(for_data3(loop_kind)) -for_data4 = { - "description": "For block def", - "text": [ - { - "def": "x", - "for": {"i": [1, 2, 3, 4]}, - "repeat": "${ i + 1 }", - "join": {"as": "array"}, - } - ], -} +def for_data4(loop_kind): + return { + "description": "For block def", + "text": [ + { + "def": "x", + "for": {"i": [1, 2, 3, 4]}, + loop_kind: "${ i + 1 }", + "join": {"as": "array"}, + } + ], + } def test_for_data4(): - result = exec_dict(for_data4, output="all") - assert result["result"] == "[2, 3, 4, 5]" - assert result["scope"]["x"] == [2, 3, 4, 5] - - -for_as_text_data4 = { - "description": "For block def", - "text": [ - { - "def": "x", - "for": {"i": [1, 2, 3, 4]}, - "repeat": "${ i + 1 }", - } - ], -} + for loop_kind in ["repeat", "map"]: + result = exec_dict(for_data4(loop_kind), output="all") + assert result["result"] == "[2, 3, 4, 5]" + assert result["scope"]["x"] == [2, 3, 4, 5] + + +def for_as_text_data4(loop_kind): + return { + "description": "For block def", + "text": [ + { + "def": "x", + "for": {"i": [1, 2, 3, 4]}, + "repeat": "${ i + 1 }", + } + ], + } def test_for_as_text_data4(): - result = exec_dict(for_as_text_data4, output="all") - assert result["result"] == "2345" - assert result["scope"]["x"] == "2345" - - -for_data5 = { - "description": "For block def", - "text": [ - { - "def": "x", - "text": { - "for": {"i": [1, 2, 3, 4]}, - "repeat": "${ i }", - "join": {"as": "array"}, - }, - } - ], -} + for loop_kind in ["repeat", "map"]: + result = exec_dict(for_as_text_data4(loop_kind), output="all") + assert result["result"] == "2345" + assert result["scope"]["x"] == "2345" + + +def for_data5(loop_kind): + return { + "description": "For block def", + "text": [ + { + "def": "x", + "text": { + "for": {"i": [1, 2, 3, 4]}, + loop_kind: "${ i }", + "join": {"as": "array"}, + }, + } + ], + } def test_for_data5(): - result = exec_dict(for_data5, output="all") - assert result["result"] == "[1, 2, 3, 4]" - assert result["scope"]["x"] == "[1, 2, 3, 4]" + for loop_kind in ["repeat", "map"]: + result = exec_dict(for_data5(loop_kind), output="all") + assert result["result"] == "[1, 2, 3, 4]" + assert result["scope"]["x"] == "[1, 2, 3, 4]" def test_for_nested_array(): - prog_str = """ + for loop_kind in ["repeat", "map"]: + prog_str = f""" for: i: [1,2,3] repeat: for: j: [1,2] - repeat: "${i}${j}" + {loop_kind}: "${{i}}${{j}}" join: as: array join: as: array """ - result = exec_str(prog_str) - assert result == [["11", "12"], ["21", "22"], ["31", "32"]] + result = exec_str(prog_str) + assert result == [["11", "12"], ["21", "22"], ["31", "32"]] def test_for_nested_text(): - prog_str = r""" + for loop_kind1 in ["repeat", "map"]: + for loop_kind2 in ["repeat", "map"]: + prog_str = f""" for: i: [1,2,3] -repeat: +{loop_kind1}: for: j: [1,2] - repeat: "${i}${j}" + {loop_kind2}: "${{i}}${{j}}" +join: + with: "\\n" +""" + result = exec_str(prog_str) + assert result == "\n".join(["1112", "2122", "3132"]) + + +def for_scope(loop_kind): + return { + "defs": {"x": 0}, + "text": { + "for": {"i": [1, 2, 3, 4]}, + loop_kind: {"defs": {"x": "${ x + i }"}, "data": "${ i + x }"}, + "join": {"as": "array"}, + }, + } + + +def test_for_scope(): + for loop_kind in ["repeat", "map"]: + result = exec_dict(for_scope(loop_kind), output="all") + match loop_kind: + case "repeat": + assert result["result"] == "[2, 5, 9, 14]" + assert result["scope"]["x"] == 10 + case "map": + assert result["result"] == "[2, 4, 6, 8]" + assert result["scope"]["x"] == 0 + + +def for_index(loop_kind): + return { + "text": { + "index": "idx", + "for": {"i": [1, 2, 3, 4]}, + loop_kind: "${ i + idx }", + "join": {"as": "array"}, + }, + } + + +def test_for_index(): + for loop_kind in ["repeat", "map"]: + result = exec_dict(for_index(loop_kind), output="all") + assert result["result"] == "[1, 3, 5, 7]" + + +def for_context(loop_kind): + return { + "lastOf": [ + "Hello", + { + "for": { + "i": [ + 1, + 2, + 3, + ] + }, + loop_kind: "${ pdl_context.serialize('litellm') }", + "join": {"as": "array"}, + }, + ] + } + + +def test_for_context(): + for loop_kind in ["repeat", "map"]: + result = exec_dict(for_context(loop_kind), output="all") + match loop_kind: + case "repeat": + assert result["result"] == [ + [{"role": "user", "content": "Hello", "pdl__defsite": "lastOf.0"}], + [ + { + "role": "user", + "content": "Hello", + "pdl__defsite": "lastOf.0", + }, + { + "role": "user", + "content": [ + { + "role": "user", + "content": "Hello", + "pdl__defsite": "lastOf.0", + } + ], + "pdl__defsite": "lastOf.1.repeat.0", + }, + ], + [ + { + "role": "user", + "content": "Hello", + "pdl__defsite": "lastOf.0", + }, + { + "role": "user", + "content": [ + { + "role": "user", + "content": "Hello", + "pdl__defsite": "lastOf.0", + } + ], + "pdl__defsite": "lastOf.1.repeat.0", + }, + { + "role": "user", + "content": [ + { + "role": "user", + "content": "Hello", + "pdl__defsite": "lastOf.0", + }, + { + "role": "user", + "content": [ + { + "role": "user", + "content": "Hello", + "pdl__defsite": "lastOf.0", + } + ], + "pdl__defsite": "lastOf.1.repeat.0", + }, + ], + "pdl__defsite": "lastOf.1.repeat.1", + }, + ], + ] + case "map": + assert result["result"] == [ + [{"role": "user", "content": "Hello", "pdl__defsite": "lastOf.0"}], + [{"role": "user", "content": "Hello", "pdl__defsite": "lastOf.0"}], + [{"role": "user", "content": "Hello", "pdl__defsite": "lastOf.0"}], + ] + + +def test_for_reduce(): + for loop_kind1 in ["repeat", "map"]: + prog_str = f""" +defs: + plus: + lang: python + code: | + import operator + result = operator.add +for: + i: [1,2,3,4] +{loop_kind1}: ${{ i }} join: - with: "\n" + reduce: ${{ plus }} """ - result = exec_str(prog_str) - assert result == "\n".join(["1112", "2122", "3132"]) + result = exec_str(prog_str) + assert result == 10