char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
d9f918d2d
char/aliceai-t5-moe
1#pragma once 2 3#include "string.h" 4#include "utils.h" 5 6#include <algorithm> 7#include <cmath> 8#include <cstdint> 9#include <functional> 10#include <map> 11#include <memory> 12#include <set> 13#include <sstream> 14#include <string> 15#include <vector> 16#include <unordered_map> 17 18namespace jinja { 19 20struct value_t ; 21using value = std ::shared_ptr < value_t > ; 22 23 24// Helper to check the type of a value 25template < typename T > 26struct extract_pointee { 27using type = T ; 28}; 29template < typename U > 30struct extract_pointee < std ::shared_ptr < U >> { 31using type = U ; 32}; 33template < typename T > 34bool is_val (const value & ptr ) { 35using PointeeType = typename extract_pointee < T > ::type ; 36return dynamic_cast < const PointeeType *> (ptr .get ())!= nullptr ; 37} 38template < typename T > 39bool is_val (const value_t * ptr ) { 40using PointeeType = typename extract_pointee < T > ::type ; 41return dynamic_cast < const PointeeType *> (ptr )!= nullptr ; 42} 43template < typename T ,typename ...Args > 44std ::shared_ptr < typename extract_pointee < T > ::type > mk_val (Args && ...args ) { 45using PointeeType = typename extract_pointee < T > ::type ; 46return std ::make_shared < PointeeType > (std ::forward < Args > (args )...); 47} 48template < typename T > 49const typename extract_pointee < T > ::type * cast_val (const value & ptr ) { 50using PointeeType = typename extract_pointee < T > ::type ; 51return dynamic_cast < const PointeeType *> (ptr .get ()); 52} 53template < typename T > 54typename extract_pointee < T > ::type * cast_val (value & ptr ) { 55using PointeeType = typename extract_pointee < T > ::type ; 56return dynamic_cast < PointeeType *> (ptr .get ()); 57} 58// End Helper 59 60 61struct context ;// forward declaration 62 63 64// for converting from JSON to jinja values 65// example input JSON: 66// { 67// "messages": [ 68// {"role": "user", "content": "Hello!"}, 69// {"role": "assistant", "content": "Hi there!"} 70// ], 71// "bos_token": "<s>", 72// "eos_token": "</s>", 73// } 74// 75// to mark strings as user input, wrap them in a special object: 76// { 77// "messages": [ 78// { 79// "role": "user", 80// "content": {"__input__": "Hello!"} // this string is user input 81// }, 82// ... 83// ], 84// } 85// 86// marking input can be useful for tracking data provenance 87// and preventing template injection attacks 88// 89// Note: T_JSON can be common_json 90template < typename T_JSON > 91void global_from_json (context & ctx ,const T_JSON & json_obj ,bool mark_input ); 92 93// 94// base value type 95// 96 97struct func_args ;// function argument values 98 99using func_hptr = value (const func_args & ); 100using func_handler = std ::function < func_hptr > ; 101using func_builtins = std ::map < std ::string ,func_handler > ; 102 103enum value_compare_op {eq ,ge ,gt ,lt ,ne }; 104bool value_compare (const value & a ,const value & b ,value_compare_op op ); 105 106struct value_t { 107int64_t val_int ; 108double val_flt ; 109string val_str ; 110 111std ::vector < value > val_arr ; 112std ::vector < std ::pair < value ,value >>val_obj ; 113 114func_handler val_func ; 115 116// only used if ctx.is_get_stats = true 117struct stats_t { 118bool used = false; 119// ops can be builtin calls or operators: "array_access", "object_access" 120std ::set < std ::string > ops ; 121// utility to recursively mark value and its children as used 122static void mark_used (value & val ,bool deep = false); 123 }stats ; 124 125value_t ()= default ; 126value_t (const value_t & )= default ; 127virtual ~value_t ()= default ; 128 129// Note: only for debugging and error reporting purposes 130virtual std ::string type ()const {return "" ; } 131 132virtual int64_t as_int ()const {throw_type_error ("is not an int value" ); } 133virtual double as_float ()const {throw_type_error ("is not a float value" ); } 134virtual string as_string ()const {throw_type_error ("is not a string value" ); } 135virtual bool as_bool ()const {throw_type_error ("is not a bool value" ); } 136virtual const std ::vector < value > & as_array ()const {throw_type_error ("is not an array value" ); } 137virtual const std ::vector < std ::pair < value ,value >>& as_ordered_object ()const {throw_type_error ("is not an object value" ); } 138virtual value invoke (const func_args & )const {throw_type_error ("is not a function value" ); } 139virtual bool is_none ()const {return false; } 140virtual bool is_undefined ()const {return false; } 141virtual const func_builtins & get_builtins ()const {throw_type_error ("has no builtins" ); } 142 143virtual bool has_key (const value & ) {throw_type_error ("is not an object value" ); } 144virtual void insert (const value & /* key */ ,const value & /* val */ ) {throw_type_error ("is not an object value" ); } 145virtual value & at (const value & /* key */ ,value & /* default_val */ ) {throw_type_error ("is not an object value" ); } 146virtual value & at (const value & /* key */ ) {throw_type_error ("is not an object value" ); } 147virtual value & at (const std ::string & /* key */ ,value & /* default_val */ ) {throw_type_error ("is not an object value" ); } 148virtual value & at (const std ::string & /* key */ ) {throw_type_error ("is not an object value" ); } 149virtual value & at (int64_t /* idx */ ,value & /* default_val */ ) {throw_type_error ("is not an array value" ); } 150virtual value & at (int64_t /* idx */ ) {throw_type_error ("is not an array value" ); } 151 152virtual bool is_numeric ()const {return false; } 153virtual bool is_hashable ()const {return false; } 154virtual bool is_immutable ()const {return true; } 155virtual hasher unique_hash ()const noexcept = 0 ; 156// TODO: C++20 <=> operator 157// NOTE: We are treating == as equivalent (for normal comparisons) and != as strict nonequal (for strict (is) comparisons) 158virtual bool operator == (const value_t & other )const {return equivalent (other ); } 159virtual bool operator != (const value_t & other )const {return nonequal (other ); } 160 161// Note: only for debugging purposes 162virtual std ::string as_repr ()const {return as_string ().str (); } 163 164private : 165 [[noreturn ]]void throw_type_error (const char * expected )const { 166throw std ::runtime_error (type ()+ " "+ expected ); 167 } 168 169protected : 170virtual bool equivalent (const value_t & )const = 0 ; 171virtual bool nonequal (const value_t & other )const {return !equivalent (other ); } 172}; 173 174// 175// utils 176// 177 178const func_builtins & global_builtins (); 179 180std ::string value_to_json (const value & val ,int indent = -1 ,const std ::string_view item_sep = ", " ,const std ::string_view key_sep = ": " ); 181 182// Note: only used for debugging purposes 183std ::string value_to_string_repr (const value & val ); 184 185struct not_implemented_exception :public std ::runtime_error { 186not_implemented_exception (const std ::string & msg ) :std ::runtime_error ("NotImplemented: " + msg ) {} 187}; 188 189struct value_hasher { 190size_t operator ()(const value & val )const noexcept { 191return val -> unique_hash ().digest (); 192 } 193}; 194 195struct value_equivalence { 196bool operator ()(const value & lhs ,const value & rhs )const { 197return * lhs == * rhs ; 198 } 199bool operator ()(const std ::pair < value ,value > & lhs ,const std ::pair < value ,value > & rhs )const { 200return * (lhs .first )== * (rhs .first )&& * (lhs .second )== * (rhs .second ); 201 } 202}; 203 204struct value_equality { 205bool operator ()(const value & lhs ,const value & rhs )const { 206return !(* lhs != * rhs ); 207 } 208}; 209 210// 211// primitive value types 212// 213 214struct value_int_t :public value_t { 215value_int_t (int64_t v ) { 216val_int = v ; 217val_flt = static_cast < double > (v ); 218if (static_cast < int64_t > (val_flt )!= v ) { 219val_flt = v < 0 ?- INFINITY :INFINITY ; 220 } 221 } 222virtual std ::string type ()const override {return "Integer" ; } 223virtual int64_t as_int ()const override {return val_int ; } 224virtual double as_float ()const override {return val_flt ; } 225virtual string as_string ()const override {return std ::to_string (val_int ); } 226virtual bool as_bool ()const override { 227return val_int != 0 ; 228 } 229virtual const func_builtins & get_builtins ()const override ; 230virtual bool is_numeric () const override { return true; } 231virtual bool is_hashable () const override { return true; } 232virtual hasher unique_hash () const noexcept override { 233return hasher ( typeid ( * this)) 234. update ( & val_int, sizeof (val_int)) 235. update ( & val_flt, sizeof (val_flt)); 236} 237protected: 238virtual bool equivalent ( const value_t & other) const override { 239return other. is_numeric () && val_int == other.val_int && val_flt == other.val_flt; 240} 241virtual bool nonequal ( const value_t & other) const override { 242return !( typeid ( * this ) == typeid (other) && val_int == other.val_int); 243} 244}; 245using value_int = std::shared_ptr < value_int_t > ; 246 247 248struct value_float_t : public value_t { 249value val; 250value_float_t( double v) { 251val_flt = v; 252val_int = std:: isfinite (v) ? static_cast < int64_t > (v) : 0 ; 253val = mk_val < value_int > (val_int); 254} 255virtual std::string type () const override { return "Float" ; } 256virtual double as_float () const override { return val_flt; } 257virtual int64_t as_int () const override { return val_int; } 258virtual string as_string () const override { 259std :: string out = std:: to_string (val_flt); 260out. erase (out. find_last_not_of ( '0' ) + 1 , std::string::npos); // remove trailing zeros 261if (out. back () == '.' ) out. push_back ( '0' ); // leave one zero if no decimals 262return out; 263} 264virtual bool as_bool () const override { 265return val_flt != 0.0 ; 266} 267virtual const func_builtins & get_builtins () const override ; 268virtual bool is_numeric () const override { return true; } 269virtual bool is_hashable () const override { return true; } 270virtual hasher unique_hash () const noexcept override { 271if ( static_cast < double > (val_int) == val_flt) { 272return val -> unique_hash (); 273} else { 274return hasher ( typeid ( * this)) 275. update ( & val_int, sizeof (val_int)) 276. update ( & val_flt, sizeof (val_flt)); 277} 278} 279protected : 280virtual bool equivalent ( const value_t & other) const override { 281return other. is_numeric () && val_int == other. val_int && val_flt == other. val_flt ; 282} 283virtual bool nonequal ( const value_t & other) const override { 284return !( typeid ( * this) == typeid (other) && val_flt == other. val_flt ); 285} 286}; 287using value_float = std::shared_ptr < value_float_t > ; 288 289 290struct value_string_t : public value_t { 291value_string_t () { val_str = string (); } 292value_string_t ( const std ::string & v) { val_str = string (v); } 293value_string_t( const string & v) { val_str = v; } 294virtual std::string type () const override { return "String" ; } 295virtual string as_string () const override { return val_str; } 296virtual std::string as_repr () const override { 297std :: ostringstream ss; 298for ( const auto & part : val_str.parts) { 299ss << ( part .is_input ? " INPUT : " : " TMPL : ") << part.val << " \n"; 300} 301return ss. str (); 302} 303virtual bool as_bool () const override { 304return val_str. length () > 0 ; 305} 306virtual const func_builtins & get_builtins () const override; 307virtual bool is_hashable () const override { return true; } 308virtual hasher unique_hash () const noexcept override { 309const auto type_hash = typeid ( * this). hash_code (); 310auto hash = hasher (); 311hash. update ( & type_hash, sizeof (type_hash)); 312val_str. hash_update (hash); 313return hash; 314} 315void mark_input () { 316val_str. mark_input (); 317} 318protected: 319virtual bool equivalent (const value_t & other) const override { 320return typeid ( * this) == typeid (other) && val_str. str () == other. val_str . str (); 321} 322}; 323using value_string = std::shared_ptr < value_string_t > ; 324 325 326struct value_bool_t : public value_t { 327value val; 328value_bool_t (bool v) { 329val_int = static_cast < int64_t > (v); 330val_flt = static_cast < double > (v); 331val = mk_val < value_int > (val_int); 332} 333virtual std::string type () const override { return "Boolean" ; } 334virtual int64_t as_int () const override { return val_int; } 335virtual bool as_bool () const override { return val_int; } 336virtual string as_string () const override { return std:: string (val_int ? "True" : "False" ); } 337virtual const func_builtins & get_builtins () const override; 338virtual bool is_numeric () const override { return true; } 339virtual bool is_hashable () const override { return true; } 340virtual hasher unique_hash () const noexcept override { 341return val -> unique_hash (); 342} 343protected: 344virtual bool equivalent (const value_t & other) const override { 345return other. is_numeric () && val_int == other. val_int && val_flt == other. val_flt ; 346} 347virtual bool nonequal (const value_t & other) const override { 348return !( typeid ( * this) == typeid (other) && val_int == other. val_int ); 349} 350}; 351using value_bool = std::shared_ptr < value_bool_t > ; 352 353 354struct value_array_t : public value_t { 355value_array_t () = default; 356value_array_t (value & v) { 357val_arr = v -> val_arr ; 358} 359value_array_t (std::vector < value > && arr) { 360val_arr = arr; 361} 362value_array_t (const std::vector < value > & arr) { 363val_arr = arr; 364} 365void reverse () { 366if ( is_immutable ()) { 367throw std:: runtime_error ( "Attempting to modify immutable type" ); 368} 369std:: reverse (val_arr. begin (), val_arr. end ()); 370} 371void push_back (const value & val) { 372if ( is_immutable ()) { 373throw std:: runtime_error ( "Attempting to modify immutable type" ); 374} 375val_arr. push_back (val); 376} 377void push_back (value && val) { 378if ( is_immutable ()) { 379throw std:: runtime_error ( "Attempting to modify immutable type" ); 380} 381val_arr. push_back (std:: move (val)); 382} 383value pop_at (int64_t index) { 384if ( is_immutable ()) { 385throw std:: runtime_error ( "Attempting to modify immutable type" ); 386} 387if (index < 0 ) { 388index = static_cast < int64_t > (val_arr. size ()) + index; 389} 390if (index < 0 || index >= static_cast < int64_t > (val_arr. size ())) { 391throw std:: runtime_error ( "Index " + std:: to_string (index) + " out of bounds for array of size " + std:: to_string (val_arr. size ())); 392} 393value val = val_arr. at (static_cast < size_t > (index)); 394val_arr. erase (val_arr. begin () + index); 395return val; 396} 397virtual std::string type () const override { return "Array" ; } 398virtual bool is_immutable () const override { return false; } 399virtual const std::vector < value > & as_array () const override { return val_arr; } 400virtual string as_string () const override { 401const bool immutable = is_immutable (); 402std::ostringstream ss; 403ss << (immutable ? "(" : "[" ); 404for (size_t i = 0 ; i < val_arr. size (); i ++ ) { 405if (i > 0 ) ss << ", " ; 406value val = val_arr. at (i); 407ss << value_to_string_repr (val); 408} 409if (immutable && val_arr. size () == 1 ) { 410ss << "," ; 411} 412ss << (immutable ? ")" : "]" ); 413return ss. str (); 414} 415virtual bool as_bool () const override { 416return !val_arr. empty (); 417} 418virtual value & at (int64_t index, value & default_val) override { 419if (index < 0 ) { 420index += val_arr. size (); 421} 422if (index < 0 || static_cast < size_t > (index) >= val_arr. size ()) { 423return default_val; 424} 425return val_arr[index]; 426} 427virtual value & at (int64_t index) override { 428if (index < 0 ) { 429index += val_arr. size (); 430} 431if (index < 0 || static_cast < size_t > (index) >= val_arr. size ()) { 432throw std:: runtime_error ( "Index " + std:: to_string (index) + " out of bounds for array of size " + std:: to_string (val_arr. size ())); 433} 434return val_arr[index]; 435} 436virtual const func_builtins & get_builtins () const override; 437virtual bool is_hashable () const override { 438if (std:: all_of (val_arr. begin (), val_arr. end (), [ & ](auto & val) -> bool { 439return val -> is_immutable () && val -> is_hashable (); 440})) { 441return true; 442} 443return false; 444} 445virtual hasher unique_hash () const noexcept override { 446auto hash = hasher ( typeid ( * this)); 447for ( const auto & val : val_arr) { 448// must use digest to prevent problems from "concatenation" property of hasher 449// for ex. hash of [ "ab", "c" ] should be different from [ "a", "bc" ] 450const size_t val_hash = val -> unique_hash (). digest (); 451hash. update ( & val_hash, sizeof ( size_t )); 452} 453return hash; 454} 455protected: 456virtual bool equivalent ( const value_t & other) const override { 457return typeid ( * this ) == typeid (other) && is_hashable () && other. is_hashable () && std:: equal (val_arr. begin (), val_arr. end (), other. val_arr . begin (), other. val_arr . end (), value_equivalence ()); 458} 459}; 460using value_array = std::shared_ptr < value_array_t > ; 461 462 463struct value_tuple_t : public value_array_t { 464value_tuple_t (value & v) { 465val_arr = v -> val_arr ; 466} 467value_tuple_t ( std ::vector < value > && arr) { 468val_arr = arr; 469} 470value_tuple_t ( const std ::vector < value > & arr) { 471val_arr = arr; 472} 473value_tuple_t ( const std ::pair < value, value > & pair) { 474val_arr. push_back (pair. first ); 475val_arr. push_back (pair. second ); 476} 477virtual std::string type () const override { return "Tuple" ; } 478virtual bool is_immutable () const override { return true; } 479}; 480using value_tuple = std::shared_ptr < value_tuple_t > ; 481 482 483struct value_object_t : public value_t { 484std ::unordered_map < value, value, value_hasher, value_equivalence > unordered; 485bool has_builtins = true; // context and loop objects do not have builtins 486value_object_t () = default; 487value_object_t (value & v) { 488val_obj = v -> val_obj ; 489for ( const auto & pair : val_obj) { 490unordered[pair. first ] = pair. second ; 491} 492} 493value_object_t ( const std ::map < value, value > & obj) { 494for ( const auto & pair : obj) { 495insert ( pair .first, pair .second); 496} 497} 498value_object_t (const std::vector < std::pair < value, value>> & obj) { 499for (const auto & pair : obj) { 500insert (pair. first , pair. second ); 501} 502} 503void insert (const std::string & key, const value & val) { 504insert (mk_val < value_string > (key), val); 505} 506virtual std::string type () const override { return "Object" ; } 507virtual bool is_immutable () const override { return false; } 508virtual const std::vector < std::pair < value, value>> & as_ordered_object () const override { return val_obj; } 509virtual string as_string () const override { 510std::ostringstream ss; 511ss << "{"; 512for ( size_t i = 0 ; i < val_obj.size(); i ++ ) { 513if (i > 0 ) ss << ", " ; 514auto & [ key , val] = val_obj. at (i); 515ss << value_to_string_repr (key) << ": " << value_to_string_repr (val); 516} 517ss << "}" ; 518return ss. str (); 519} 520virtual bool as_bool () const override { 521return !unordered. empty (); 522} 523virtual bool has_key ( const value & key) override { 524if (!key -> is_immutable () || !key -> is_hashable ()) { 525throw std::runtime_error( "Object key of unhashable type: " + key -> type ()); 526} 527return unordered. find (key) != unordered. end (); 528} 529virtual void insert ( const value & key, const value & val) override { 530bool replaced = false; 531if ( is_immutable ()) { 532throw std::runtime_error( "Attempting to modify immutable type" ); 533} 534if ( has_key (key)) { 535// if key exists, replace value in ordered list instead of appending 536for (auto & pair : val_obj) { 537if ( * (pair.first) == * key) { 538pair.second = val; 539replaced = true; 540break; 541} 542} 543} 544unordered[key] = val; 545if (!replaced) { 546val_obj. push_back ({key, val}); 547} 548} 549virtual value & at (const value & key, value & default_val) override { 550if (! has_key (key)) { 551return default_val; 552} 553return unordered. at (key); 554} 555virtual value & at (const value & key) override { 556if (! has_key (key)) { 557throw std:: runtime_error ( "Key '" + key -> as_string (). str () + "' not found in value of type " + type ()); 558} 559return unordered. at (key); 560} 561virtual value & at (const std::string & key, value & default_val) override { 562value key_val = mk_val < value_string > (key); 563return at (key_val, default_val); 564} 565virtual value & at (const std::string & key) override { 566value key_val = mk_val < value_string > (key); 567return at (key_val); 568} 569virtual const func_builtins & get_builtins () const override; 570virtual bool is_hashable () const override { 571if (std:: all_of (val_obj. begin (), val_obj. end (), [ & ](auto & pair) -> bool { 572const auto & val = pair. second ; 573return val -> is_immutable () && val -> is_hashable (); 574})) { 575return true; 576} 577return false; 578} 579virtual hasher unique_hash () const noexcept override { 580auto hash = hasher ( typeid ( * this)); 581for ( const auto & [key, val] : val_obj) { 582// must use digest to prevent problems from "concatenation" property of hasher 583// for ex. hash of key="ab", value="c" should be different from key="a", value="bc" 584const size_t key_hash = key -> unique_hash (). digest (); 585const size_t val_hash = val -> unique_hash (). digest (); 586hash. update ( & key_hash, sizeof (key_hash)); 587hash. update ( & val_hash, sizeof (val_hash)); 588} 589return hash; 590} 591protected: 592virtual bool equivalent ( const value_t & other) const override { 593return typeid ( * this ) == typeid (other) && is_hashable () && other. is_hashable () && std:: equal (val_obj. begin (), val_obj. end (), other. val_obj . begin (), other. val_obj . end (), value_equivalence ()); 594} 595}; 596using value_object = std::shared_ptr < value_object_t > ; 597 598// 599// none and undefined types 600// 601 602struct value_none_t : public value_t { 603virtual std::string type () const override { return "None" ; } 604virtual bool is_none () const override { return true; } 605virtual bool as_bool () const override { return false; } 606virtual string as_string () const override { return string ( type ()); } 607virtual std::string as_repr () const override { return type (); } 608virtual const func_builtins & get_builtins () const override ; 609virtual bool is_hashable () const override { return true; } 610virtual hasher unique_hash () const noexcept override { 611return hasher ( typeid ( * this)); 612} 613protected : 614virtual bool equivalent ( const value_t & other) const override { 615return typeid ( * this ) == typeid (other); 616} 617}; 618using value_none = std::shared_ptr < value_none_t > ; 619 620struct value_undefined_t : public value_t { 621std :: string hint; // for debugging, to indicate where undefined came from 622value_undefined_t ( const std ::string & h = "" ) : hint( h ) {} 623virtual std::string type () const override { return hint. empty () ? "Undefined" : "Undefined (hint: '" + hint + "')" ; } 624virtual bool is_undefined () const override { return true; } 625virtual bool as_bool () const override { return false; } 626virtual std::string as_repr () const override { return type (); } 627virtual const func_builtins & get_builtins () const override; 628virtual hasher unique_hash () const noexcept override { 629return hasher ( typeid ( * this)); 630} 631protected: 632virtual bool equivalent ( const value_t & other) const override { 633return is_undefined () == other. is_undefined (); 634} 635}; 636using value_undefined = std::shared_ptr < value_undefined_t > ; 637 638// 639// function type 640// 641 642struct func_args { 643public : 644std ::string func_name; // for error messages 645context & ctx ; 646func_args( context & ctx) : ctx ( ctx ) {} 647value get_kwarg ( const std ::string & key, value default_val) const ; 648value get_kwarg_or_pos ( const std ::string & key, size_t pos) const ; 649value get_pos ( size_t pos) const; 650value get_pos ( size_t pos, value default_val) const; 651const std :: vector < value > & get_args () const ; 652size_t count () const { return args. size (); } 653void push_back ( const value & val); 654void push_front ( const value & val); 655void ensure_count ( size_t min, size_t max = 999 ) const { 656size_t n = args. size (); 657if (n < min || n > max) { 658throw std::runtime_error( "Function '" + func_name + "' expected between " + std:: to_string (min) + " and " + std:: to_string (max) + " arguments, got " + std:: to_string (n)); 659} 660} 661template < typename T > void ensure_val (const value & ptr) const { 662if (!is_val < T > (ptr)) { 663throw std::runtime_error( "Function '" + func_name + "' expected value of type " + std:: string ( typeid ( T ). name ()) + ", got " + ptr -> type ()); 664} 665} 666void ensure_count ( bool require0, bool require1, bool require2, bool require3) const { 667static auto bool_to_int = []( bool b) { return b ? 1 : 0 ; }; 668size_t required = bool_to_int (require0) + bool_to_int (require1) + bool_to_int (require2) + bool_to_int (require3); 669ensure_count (required); 670} 671template < typename T0 > void ensure_vals (bool required0 = true) const { 672ensure_count (required0, false, false, false) ; 673if ( required0 && args . size () > 0 ) ensure_val < T0 >( args [ 0 ]); 674} 675template < typename T0 , typename T1 > void ensure_vals ( bool required0 = true, bool required1 = true) const { 676ensure_count ( required0 , required1 , false, false); 677if ( required0 && args . size () > 0 ) ensure_val < T0 >( args [ 0 ]); 678if ( required1 && args . size () > 1 ) ensure_val < T1 >( args [ 1 ]); 679} 680template < typename T0 , typename T1 , typename T2 > void ensure_vals ( bool required0 = true, bool required1 = true, bool required2 = true) const { 681ensure_count ( required0 , required1 , required2 , false); 682if ( required0 && args . size () > 0 ) ensure_val < T0 >( args [ 0 ]); 683if ( required1 && args . size () > 1 ) ensure_val < T1 >( args [ 1 ]); 684if ( required2 && args . size () > 2 ) ensure_val < T2 >( args [ 2 ]); 685} 686template < typename T0 , typename T1 , typename T2 , typename T3 > void ensure_vals ( bool required0 = true, bool required1 = true, bool required2 = true, bool required3 = true) const { 687ensure_count ( required0 , required1 , required2 , required3 ); 688if ( required0 && args . size () > 0 ) ensure_val < T0 >( args [ 0 ]); 689if ( required1 && args . size () > 1 ) ensure_val < T1 >( args [ 1 ]); 690if ( required2 && args . size () > 2 ) ensure_val < T2 >( args [ 2 ]); 691if ( required3 && args . size () > 3 ) ensure_val < T3 >( args [ 3 ]); 692} 693private : 694std :: vector < value > args ; 695}; 696 697struct value_func_t : public value_t { 698std :: string name ; 699value arg0 ; // bound "this" argument, if any 700value_func_t ( const std :: string & name , const func_handler & func ) : name ( name ) { 701val_func = func ; 702} 703value_func_t ( const std :: string & name , const func_handler & func , const value & arg_this ) : name ( name ), arg0 ( arg_this ) { 704val_func = func ; 705} 706virtual value invoke ( const func_args & args ) const override { 707func_args new_args ( args ); // copy 708new_args . func_name = name ; 709if ( arg0 ) { 710new_args . push_front ( arg0 ); 711} 712return val_func ( new_args ); 713} 714virtual std :: string type () const override { return "Function" ; } 715virtual std :: string as_repr () const override { return type () + "<" + name + ">(" + ( arg0 ? arg0 -> as_repr () : "" ) + ")" ; } 716virtual bool is_hashable () const override { return false; } 717virtual hasher unique_hash () const noexcept override { 718// Note: this is unused for now, we don't support function as object keys 719// use function pointer as unique identifier 720const auto target = val_func. target < func_hptr > (); 721return hasher ( typeid ( * this)). update ( & target, sizeof (target)); 722} 723protected: 724virtual bool equivalent ( const value_t & other) const override { 725// Note: this is unused for now, we don't support function as object keys 726// compare function pointers 727// (val_func == other.val_func does not work as std::function::operator== is only used for nullptr check) 728const auto target_this = this -> val_func . target < func_hptr > (); 729const auto target_other = other. val_func . target < func_hptr > (); 730return typeid ( * this) == typeid (other) && target_this == target_other; 731} 732}; 733using value_func = std::shared_ptr < value_func_t > ; 734 735// special value for kwarg 736struct value_kwarg_t : public value_t { 737std :: string key; 738value val; 739value_kwarg_t ( const std ::string & k, const value & v) : key (k), val (v) {} 740virtual std::string type () const override { return "KwArg" ; } 741virtual std::string as_repr () const override { return type (); } 742virtual bool is_hashable () const override { return true; } 743virtual hasher unique_hash () const noexcept override { 744const auto type_hash = typeid ( * this). hash_code (); 745auto hash = val -> unique_hash (); 746hash . update ( & type_hash , sizeof ( type_hash )) 747. update (key. data (), key. size ()); 748return hash; 749} 750protected : 751virtual bool equivalent ( const value_t & other) const override { 752const value_kwarg_t & other_val = static_cast < const value_kwarg_t &> (other); 753return typeid ( * this) == typeid (other) && key == other_val. key && val == other_val. val ; 754} 755}; 756using value_kwarg = std::shared_ptr < value_kwarg_t > ; 757 758 759} // namespace jinja