char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
9e40df63b
char/aliceai-t5-moe
1#pragma once 2 3#include "lexer.h" 4#include "value.h" 5 6#include <cassert> 7#include <ctime> 8#include <memory> 9#include <sstream> 10#include <string> 11#include <vector> 12 13#define JJ_DEBUG (msg , ...) do { if (g_jinja_debug) printf("%s:%-3d : " msg "\n", FILENAME, __LINE__, __VA_ARGS__); } while (0) 14 15extern bool g_jinja_debug ; 16 17namespace jinja { 18 19struct statement ; 20using statement_ptr = std ::unique_ptr < statement > ; 21using statements = std ::vector < statement_ptr > ; 22 23// Helpers for dynamic casting and type checking 24template < typename T > 25struct extract_pointee_unique { 26using type = T ; 27}; 28template < typename U > 29struct extract_pointee_unique < std ::unique_ptr < U >> { 30using type = U ; 31}; 32template < typename T > 33bool is_stmt (const statement_ptr & ptr ) { 34return dynamic_cast < const T *> (ptr .get ())!= nullptr ; 35} 36template < typename T > 37T * cast_stmt (statement_ptr & ptr ) { 38return dynamic_cast < T *> (ptr .get ()); 39} 40template < typename T > 41const T * cast_stmt (const statement_ptr & ptr ) { 42return dynamic_cast < const T *> (ptr .get ()); 43} 44// End Helpers 45 46 47// not thread-safe 48void enable_debug (bool enable ); 49 50// for visiting AST nodes 51// function signature: void(bool is_leaf, statement * node, pair of <label, children>) 52using visitor_pair = std ::pair < std ::string ,std ::vector < statement * >>; 53using visitor_fn = std ::function < void (bool ,statement * ,std ::vector < visitor_pair > )> ; 54 55struct context { 56std ::shared_ptr < std ::string > src ;// for debugging; use shared_ptr to avoid copying on scope creation 57std ::time_t current_time ;// for functions that need current time 58 59bool is_get_stats = false;// whether to collect stats 60 61visitor_fn visitor ; 62 63// src is optional, used for error reporting 64context (std ::string src = "") : src(std::make_shared<std::string>(std::move(src))) { 65env = mk_val < value_object > (); 66env -> has_builtins = false; // context object has no builtins 67env -> insert ( "true" , mk_val < value_bool > (true)); 68env -> insert ( "True" , mk_val < value_bool > (true)); 69env -> insert ( "false" , mk_val < value_bool > (false)); 70env -> insert ( "False" , mk_val < value_bool > (false)); 71env -> insert ( "none" , mk_val < value_none > ()); 72env -> insert ( "None" , mk_val < value_none > ()); 73current_time = std:: time ( nullptr ); 74} 75~ context () = default; 76 77context( const context & parent) : context () { 78// inherit variables (for example, when entering a new scope) 79auto & pvar = parent. env -> as_ordered_object (); 80for ( const auto & pair : pvar) { 81set_val ( pair .first, pair .second); 82} 83current_time = parent. current_time ; 84is_get_stats = parent. is_get_stats ; 85src = parent. src ; 86} 87 88value get_val (const std::string & name) { 89value default_val = mk_val < value_undefined > (name); 90return env -> at (name, default_val); 91} 92 93void set_val (const std::string & name, const value & val) { 94env -> insert (name, val); 95} 96 97void set_val (const value & name, const value & val) { 98env -> insert (name, val); 99} 100 101void print_vars () const { 102printf ( "Context Variables:\n%s\n" , value_to_json (env, 2 ). c_str ()); 103} 104 105private: 106value_object env; 107}; 108 109// utils for visiting AST nodes 110static std::vector < statement *> stmts_to_ptr (const statements & stmts) { 111std::vector < statement *> children; 112for (const auto & stmt : stmts) { 113children. push_back (stmt. get ()); 114} 115return children; 116} 117 118/** 119* Base class for all nodes in the AST. 120*/ 121struct statement { 122size_t pos; // position in source, for debugging 123virtual ~ statement () = default; 124virtual std::string type () const { return "Statement" ; } 125virtual void visit (context & ctx) { ctx. visitor (true, this, {}); } 126 127// execute_impl must be overridden by derived classes 128virtual value execute_impl (context & ) { throw_exec_error (); } 129// execute is the public method to execute a statement with error handling 130value execute (context & ); 131 132private: 133[[noreturn]] void throw_exec_error () const { 134throw std::runtime_error( "cannot exec " + type ()); 135} 136}; 137 138// Type Checking Utilities 139 140template < typename T > 141static void chk_type (const statement_ptr & ptr) { 142if (!ptr) return ; // Allow null for optional fields 143assert (dynamic_cast < T *> (ptr. get ()) != nullptr ); 144} 145 146template < typename T , typename U > 147static void chk_type (const statement_ptr & ptr) { 148if (!ptr) return ; 149assert (dynamic_cast < T *> (ptr. get ()) != nullptr || dynamic_cast < U *> (ptr. get ()) != nullptr ); 150} 151 152// Base Types 153 154/** 155* Expressions will result in a value at runtime (unlike statements). 156*/ 157struct expression : public statement { 158std::string type() const override { return "Expression"; } 159}; 160 161// Statements 162 163struct program : public statement { 164statements body; 165 166program () = default; 167explicit program ( statements && body) : body (std:: move (body)) {} 168std :: string type () const override { return "Program" ; } 169[[noreturn]] value execute_impl ( context & ) override { 170throw std::runtime_error( "Cannot execute program directly, use jinja::runtime instead" ); 171} 172}; 173 174struct if_statement : public statement { 175statement_ptr test; 176statements body; 177statements alternate; 178 179if_statement (statement_ptr && test, statements && body, statements && alternate) 180: test( std :: move ( test )), body ( std :: move ( body )), alternate ( std :: move ( alternate )) { 181chk_type < expression > (this -> test ); 182} 183 184std :: string type () const override { return "If" ; } 185value execute_impl ( context & ctx) override; 186void visit ( context & ctx) override { 187ctx. visitor (false, this, { 188{ "test" , {test. get ()}}, 189{ "body" , stmts_to_ptr (body)}, 190{ "alternate" , stmts_to_ptr (alternate)} 191}); 192} 193}; 194 195struct identifier; 196struct tuple_literal; 197 198/** 199* Loop over each item in a sequence 200* https://jinja.palletsprojects.com/en/3.0.x/templates/#for 201*/ 202struct for_statement : public statement { 203statement_ptr loopvar; // Identifier | TupleLiteral 204statement_ptr iterable; 205statements body; 206statements default_block; // if no iteration took place 207 208for_statement (statement_ptr && loopvar, statement_ptr && iterable, statements && body, statements && default_block) 209: loopvar( std :: move ( loopvar )), iterable ( std :: move ( iterable )), 210body ( std :: move ( body )), default_block ( std :: move ( default_block )) { 211chk_type < identifier, tuple_literal > (this -> loopvar ); 212chk_type < expression > (this -> iterable ); 213} 214 215std :: string type () const override { return "For" ; } 216value execute_impl ( context & ctx) override; 217void visit ( context & ctx) override { 218ctx. visitor (false, this, { 219{ "loopvar" , {loopvar. get ()}}, 220{ "iterable" , {iterable. get ()}}, 221{ "body" , stmts_to_ptr (body)}, 222{ "default_block" , stmts_to_ptr (default_block)} 223}); 224} 225}; 226 227struct break_statement : public statement { 228std::string type() const override { return "Break"; } 229 230struct signal : public std::exception { 231const char * what () const noexcept override { 232return "Break statement executed" ; 233} 234}; 235 236[[noreturn]] value execute_impl(context & ) override { 237throw break_statement:: signal (); 238} 239}; 240 241struct continue_statement : public statement { 242std :: string type () const override { return "Continue" ; } 243 244struct signal : public std ::exception { 245const char * what () const noexcept override { 246return "Continue statement executed" ; 247} 248}; 249 250[[noreturn]] value execute_impl ( context & ) override { 251throw continue_statement:: signal (); 252} 253}; 254 255// do nothing 256struct noop_statement : public statement { 257std :: string type () const override { return "Noop" ; } 258value execute_impl ( context & ) override { 259return mk_val < value_undefined > (); 260} 261}; 262 263struct set_statement : public statement { 264statement_ptr assignee; 265statement_ptr val; 266statements body; 267 268set_statement (statement_ptr && assignee, statement_ptr && value, statements && body) 269: assignee( std :: move ( assignee )), val ( std :: move ( value )), body ( std :: move ( body )) { 270chk_type < expression > (this -> assignee ); 271chk_type < expression > (this -> val ); 272} 273 274std :: string type () const override { return "Set" ; } 275value execute_impl ( context & ctx) override; 276void visit ( context & ctx) override { 277ctx. visitor (false, this, { 278{ "assignee" , {assignee. get ()}}, 279{ "value" , {val. get ()}}, 280{ "body" , stmts_to_ptr (body)} 281}); 282} 283}; 284 285struct macro_statement : public statement { 286statement_ptr name; 287statements args; 288statements body; 289 290macro_statement (statement_ptr && name, statements && args, statements && body) 291: name( std :: move ( name )), args ( std :: move ( args )), body ( std :: move ( body )) { 292chk_type < identifier > (this -> name ); 293for ( const auto & arg : this -> args) chk_type < expression > (arg); 294} 295 296std :: string type () const override { return "Macro" ; } 297value execute_impl ( context & ctx) override; 298void visit ( context & ctx) override { 299ctx. visitor (false, this, { 300{ "name" , {name. get ()}}, 301{ "args" , stmts_to_ptr (args)}, 302{ "body" , stmts_to_ptr (body)} 303}); 304} 305}; 306 307struct comment_statement : public statement { 308std :: string val; 309explicit comment_statement ( const std ::string & v) : val (v) {} 310std :: string type () const override { return "Comment" ; } 311value execute_impl ( context & ) override { 312return mk_val < value_undefined > (); 313} 314}; 315 316// Expressions 317 318// Represents an omitted expression in a computed member, e.g. `a[]`. 319struct blank_expression : public expression { 320std :: string type () const override { return "BlankExpression" ; } 321value execute_impl ( context & ) override { 322return mk_val < value_undefined > (); 323} 324}; 325 326struct member_expression : public expression { 327statement_ptr object; 328statement_ptr property; 329bool computed; // true if obj[expr] and false if obj.prop 330 331member_expression (statement_ptr && object, statement_ptr && property, bool computed) 332: object( std :: move ( object )), property ( std :: move ( property )), computed ( computed ) { 333chk_type < expression > (this -> object ); 334chk_type < expression > (this -> property ); 335} 336std :: string type () const override { return "MemberExpression" ; } 337value execute_impl ( context & ctx) override; 338void visit ( context & ctx) override { 339ctx. visitor (false, this, { 340{ "object" , {object. get ()}}, 341{ "property" , {property. get ()}} 342}); 343} 344}; 345 346struct call_expression : public expression { 347statement_ptr callee; 348statements args; 349 350call_expression (statement_ptr && callee, statements && args) 351: callee( std :: move ( callee )), args ( std :: move ( args )) { 352chk_type < expression > (this -> callee ); 353for ( const auto & arg : this -> args) chk_type < expression > (arg); 354} 355std :: string type () const override { return "CallExpression" ; } 356value execute_impl ( context & ctx) override; 357void visit ( context & ctx) override { 358ctx. visitor (false, this, { 359{ "callee" , {callee. get ()}}, 360{ "args" , stmts_to_ptr (args)} 361}); 362} 363}; 364 365/** 366* Represents a user-defined variable or symbol in the template. 367*/ 368struct identifier : public expression { 369std :: string val; 370explicit identifier ( const std ::string & val) : val (val) {} 371std :: string type () const override { return "Identifier" ; } 372value execute_impl ( context & ctx) override; 373}; 374 375// Literals 376 377struct integer_literal : public expression { 378int64_t val; 379explicit integer_literal ( int64_t val) : val (val) {} 380std :: string type () const override { return "IntegerLiteral" ; } 381value execute_impl ( context & ) override { 382return mk_val < value_int > (val); 383} 384}; 385 386struct float_literal : public expression { 387double val; 388explicit float_literal ( double val) : val (val) {} 389std :: string type () const override { return "FloatLiteral" ; } 390value execute_impl ( context & ) override { 391return mk_val < value_float > (val); 392} 393}; 394 395struct string_literal : public expression { 396std :: string val; 397explicit string_literal ( const std ::string & val) : val (val) {} 398std :: string type () const override { return "StringLiteral" ; } 399value execute_impl ( context & ) override { 400return mk_val < value_string > (val); 401} 402}; 403 404struct array_literal : public expression { 405statements val; 406explicit array_literal ( statements && val) : val (std:: move (val)) { 407for ( const auto & item : this -> val) chk_type < expression > (item); 408} 409std :: string type () const override { return "ArrayLiteral" ; } 410value execute_impl ( context & ctx) override { 411auto arr = mk_val < value_array > (); 412for ( const auto & item_stmt : val) { 413arr -> push_back ( item_stmt -> execute ( ctx )); 414} 415return arr; 416} 417}; 418 419struct tuple_literal : public expression { 420statements val; 421explicit tuple_literal ( statements && val) : val (std:: move (val)) { 422for ( const auto & item : this -> val) chk_type < expression > (item); 423} 424std :: string type () const override { return "TupleLiteral" ; } 425value execute_impl ( context & ctx) override { 426auto arr = mk_val < value_array > (); 427for ( const auto & item_stmt : val) { 428arr -> push_back ( item_stmt -> execute ( ctx )); 429} 430return mk_val < value_tuple > (std:: move (arr -> as_array ())); 431} 432}; 433 434struct object_literal : public expression { 435std::vector < std::pair < statement_ptr, statement_ptr>> val; 436explicit object_literal(std::vector < std::pair < statement_ptr, statement_ptr>> && val) 437: val (std:: move (val)) { 438for ( const auto & pair : this -> val) { 439chk_type < expression > (pair.first); 440chk_type < expression > (pair. second ); 441} 442} 443std::string type () const override { return "ObjectLiteral" ; } 444value execute_impl (context & ctx) override; 445}; 446 447// Complex Expressions 448 449/** 450* An operation with two sides, separated by an operator. 451* Note: Either side can be a Complex Expression, with order 452* of operations being determined by the operator. 453*/ 454struct binary_expression : public expression { 455token op; 456statement_ptr left; 457statement_ptr right; 458 459binary_expression (token op, statement_ptr && left, statement_ptr && right) 460: op (std:: move (op)), left (std:: move (left)), right (std:: move (right)) { 461chk_type < expression > (this -> left ); 462chk_type < expression > (this -> right); 463} 464std :: string type () const override { return "BinaryExpression" ; } 465value execute_impl ( context & ctx) override; 466void visit ( context & ctx) override { 467ctx. visitor (false, this, { 468{ "left" , {left. get ()}}, 469{ "right" , {right. get ()}} 470}); 471} 472}; 473 474/** 475* An operation with two sides, separated by the | operator. 476* Operator precedence: https://github.com/pallets/jinja/issues/379#issuecomment-168076202 477*/ 478struct filter_expression : public expression { 479// either an expression or a value is allowed 480statement_ptr operand; 481value_string val; // will be set by filter_statement 482 483statement_ptr filter; 484 485filter_expression (statement_ptr && operand, statement_ptr && filter) 486: operand( std :: move ( operand )), filter ( std :: move ( filter )) { 487chk_type < expression > (this -> operand ); 488chk_type < identifier, call_expression > (this -> filter ); 489} 490 491filter_expression (value_string && val, statement_ptr && filter) 492: val( std :: move ( val )), filter ( std :: move ( filter )) { 493chk_type < identifier, call_expression > (this -> filter ); 494} 495 496std :: string type () const override { return "FilterExpression" ; } 497value execute_impl ( context & ctx) override; 498void visit ( context & ctx) override { 499ctx. visitor (false, this, { 500{ "operand" , {operand. get ()}}, 501{ "filter" , {filter. get ()}} 502}); 503} 504}; 505 506struct filter_statement : public statement { 507statement_ptr filter; 508statements body; 509 510filter_statement (statement_ptr && filter, statements && body) 511: filter( std :: move ( filter )), body ( std :: move ( body )) { 512chk_type < identifier, call_expression > (this -> filter ); 513} 514std :: string type () const override { return "FilterStatement" ; } 515value execute_impl ( context & ctx) override; 516void visit ( context & ctx) override { 517ctx. visitor (false, this, { 518{ "filter" , {filter. get ()}}, 519{ "body" , stmts_to_ptr (body)} 520}); 521} 522}; 523 524/** 525* An operation which filters a sequence of objects by applying a test to each object, 526* and only selecting the objects with the test succeeding. 527* 528* It may also be used as a shortcut for a ternary operator. 529*/ 530struct select_expression : public expression { 531statement_ptr lhs; 532statement_ptr test; 533 534select_expression (statement_ptr && lhs, statement_ptr && test) 535: lhs( std :: move ( lhs )), test ( std :: move ( test )) { 536chk_type < expression > (this -> lhs ); 537chk_type < expression > (this -> test ); 538} 539std :: string type () const override { return "SelectExpression" ; } 540value execute_impl ( context & ctx) override { 541auto predicate = test -> execute_impl (ctx); 542if (!predicate -> as_bool ()) { 543return mk_val < value_undefined > (); 544} 545return lhs -> execute_impl (ctx); 546} 547void visit ( context & ctx) override { 548ctx. visitor (false, this, { 549{ "lhs" , {lhs. get ()}}, 550{ "test" , {test. get ()}} 551}); 552} 553}; 554 555/** 556* An operation with two sides, separated by the "is" operator. 557* NOTE: "value is something" translates to function call "test_is_something(value)" 558*/ 559struct test_expression : public expression { 560statement_ptr operand; 561bool negate; 562statement_ptr test; 563 564test_expression (statement_ptr && operand, bool negate, statement_ptr && test) 565: operand( std :: move ( operand )), negate ( negate ), test ( std :: move ( test )) { 566chk_type < expression > (this -> operand ); 567chk_type < identifier, call_expression > (this -> test ); 568} 569std :: string type () const override { return "TestExpression" ; } 570value execute_impl ( context & ctx) override; 571void visit ( context & ctx) override { 572ctx. visitor (false, this, { 573{ "operand" , {operand. get ()}}, 574{ "test" , {test. get ()}} 575}); 576} 577}; 578 579/** 580* An operation with one side (operator on the left). 581*/ 582struct unary_expression : public expression { 583token op; 584statement_ptr argument; 585 586unary_expression( token op, statement_ptr && argument) 587: op ( std :: move ( op )), argument ( std :: move ( argument )) { 588chk_type < expression > (this -> argument); 589} 590std :: string type () const override { return "UnaryExpression" ; } 591value execute_impl ( context & ctx) override; 592void visit ( context & ctx) override { 593ctx. visitor (false, this, { 594{ "argument" , {argument. get ()}} 595}); 596} 597}; 598 599struct slice_expression : public expression { 600statement_ptr start_expr; 601statement_ptr stop_expr; 602statement_ptr step_expr; 603 604slice_expression (statement_ptr && start_expr, statement_ptr && stop_expr, statement_ptr && step_expr) 605: start_expr( std :: move ( start_expr )), stop_expr ( std :: move ( stop_expr )), step_expr ( std :: move ( step_expr )) { 606chk_type < expression > (this -> start_expr ); 607chk_type < expression > (this -> stop_expr ); 608chk_type < expression > (this -> step_expr ); 609} 610std :: string type () const override { return "SliceExpression" ; } 611[[noreturn]] value execute_impl ( context & ) override { 612throw std::runtime_error( "must be handled by MemberExpression" ); 613} 614void visit ( context & ctx) override { 615ctx. visitor (false, this, { 616{ "start_expr" , {start_expr. get ()}}, 617{ "stop_expr" , {stop_expr. get ()}}, 618{ "step_expr" , {step_expr. get ()}} 619}); 620} 621}; 622 623struct keyword_argument_expression : public expression { 624statement_ptr key; 625statement_ptr val; 626 627keyword_argument_expression (statement_ptr && key, statement_ptr && val) 628: key( std :: move ( key )), val ( std :: move ( val )) { 629chk_type < identifier > (this -> key ); 630chk_type < expression > (this -> val ); 631} 632std :: string type () const override { return "KeywordArgumentExpression" ; } 633value execute_impl ( context & ctx) override; 634void visit ( context & ctx) override { 635ctx. visitor (false, this, { 636{ "key" , {key. get ()}}, 637{ "val" , {val. get ()}} 638}); 639} 640}; 641 642struct spread_expression : public expression { 643statement_ptr argument; 644explicit spread_expression ( statement_ptr && argument) : argument (std:: move (argument)) { 645chk_type < expression > (this -> argument ); 646} 647std :: string type () const override { return "SpreadExpression" ; } 648void visit ( context & ctx) override { 649ctx. visitor (false, this, { 650{ "argument" , {argument. get ()}} 651}); 652} 653}; 654 655struct call_statement : public statement { 656statement_ptr call; 657statements caller_args; 658statements body; 659 660call_statement (statement_ptr && call, statements && caller_args, statements && body) 661: call( std :: move ( call )), caller_args ( std :: move ( caller_args )), body ( std :: move ( body )) { 662chk_type < call_expression > (this -> call ); 663for ( const auto & arg : this -> caller_args) chk_type < expression > (arg); 664} 665std :: string type () const override { return "CallStatement" ; } 666value execute_impl ( context & ctx) override; 667void visit ( context & ctx) override { 668ctx. visitor (false, this, { 669{ "call" , {call. get ()}}, 670{ "caller_args" , stmts_to_ptr (caller_args)}, 671{ "body" , stmts_to_ptr (body)} 672}); 673} 674}; 675 676struct ternary_expression : public expression { 677statement_ptr condition; 678statement_ptr true_expr; 679statement_ptr false_expr; 680 681ternary_expression (statement_ptr && condition, statement_ptr && true_expr, statement_ptr && false_expr) 682: condition( std :: move ( condition )), true_expr ( std :: move ( true_expr )), false_expr ( std :: move ( false_expr )) { 683chk_type < expression > (this -> condition ); 684chk_type < expression > (this -> true_expr ); 685chk_type < expression > (this -> false_expr ); 686} 687std :: string type () const override { return "Ternary" ; } 688value execute_impl ( context & ctx) override { 689value cond_val = condition -> execute (ctx); 690if (cond_val -> as_bool ()) { 691return true_expr -> execute (ctx); 692} else { 693return false_expr -> execute (ctx); 694} 695} 696void visit ( context & ctx) override { 697ctx. visitor (false, this, { 698{ "condition" , {condition. get ()}}, 699{ "true_expr" , {true_expr. get ()}}, 700{ "false_expr" , {false_expr. get ()}} 701}); 702} 703}; 704 705struct raised_exception : public std ::exception { 706std :: string message; 707raised_exception ( const std ::string & msg) : message( msg ) {} 708const char * what () const noexcept override { 709return message. c_str (); 710} 711}; 712 713// Used to rethrow exceptions with modified messages 714struct rethrown_exception : public std ::exception { 715std :: string message; 716rethrown_exception ( const std ::string & msg) : message( msg ) {} 717const char * what () const noexcept override { 718return message. c_str (); 719} 720}; 721 722////////////////////// 723 724static void gather_string_parts_recursive ( const value & val, value_string & parts) { 725// TODO: probably allow print value_none as "None" string? currently this breaks some templates 726if (is_val < value_string > (val)) { 727const auto & str_val = cast_val < value_string > (val) -> val_str ; 728parts -> val_str . append (str_val); 729} else if (is_val < value_int > (val) || is_val < value_float > (val) || is_val < value_bool > (val)) { 730std :: string str_val = val -> as_string (). str (); 731parts -> val_str . append (str_val); 732} else if (is_val < value_array > (val)) { 733auto items = cast_val < value_array > (val) -> as_array (); 734for ( const auto & item : items) { 735gather_string_parts_recursive ( item , parts ); 736} 737} 738} 739 740static std ::string render_string_parts ( const value_string & parts) { 741std :: ostringstream oss; 742for ( const auto & part : parts -> val_str.parts) { 743oss << part.val; 744} 745return oss. str (); 746} 747 748struct runtime { 749context & ctx; 750explicit runtime (context & ctx) : ctx (ctx) {} 751 752value_array execute (const program & prog) { 753value_array results = mk_val < value_array > (); 754for ( const auto & stmt : prog.body) { 755value res = stmt -> execute (ctx); 756results -> push_back (std:: move (res)); 757} 758return results; 759} 760 761static value_string gather_string_parts (const value & val) { 762value_string parts = mk_val < value_string > (); 763gather_string_parts_recursive (val, parts); 764// join consecutive parts with the same type 765auto & p = parts -> val_str . parts ; 766if (p. empty ()) { 767return parts; 768} 769size_t w = 0 ; 770for ( size_t r = 1 ; r < p. size (); r ++ ) { 771if (p[w]. is_input == p[r]. is_input ) { 772p[w]. val += p[r]. val ; 773} else { 774w ++ ; 775if (w != r) { 776// the guard is needed, self-move leaves the string in an unspecified state 777p[w] = std:: move (p[r]); 778} 779} 780} 781p. resize (w + 1 ); 782return parts; 783} 784 785static std ::string debug_dump_program ( const program & prog, const std ::string & src); 786}; 787 788} // namespace jinja