- fixed the buggy implementation of the StepReplacementPoint::GetNextConnectionsToNode method; it does return each node that it connects to exactly once now
- fixed other various bugs in the StepReplacementPoint class due to it's complicated references-layout
- improved the COS language definition by removing redundancy and adding the "operator-specifier" for future operator overloading
@@ -207,7 +207,7 @@ | ||
207 | 207 | { |
208 | 208 | if ( auto *replpt = right.replpt ) |
209 | 209 | { |
210 | - auto *newReplpt = (typename compileForEnvType::StepReplacementPoint*)replpt->Clone(); | |
210 | + auto *newReplpt = env->runtime_env->CloneStep <typename compileForEnvType::StepReplacementPoint> ( replpt ); | |
211 | 211 | |
212 | 212 | this->replpt = newReplpt; |
213 | 213 |
@@ -2368,9 +2368,21 @@ | ||
2368 | 2368 | { |
2369 | 2369 | LexingEnvironment *env = this->env; |
2370 | 2370 | |
2371 | + Step *exec = this->exec; | |
2372 | + | |
2373 | + if ( exec ) | |
2374 | + { | |
2375 | + env->gcReachSched.OnRemoveConnection( this, exec ); | |
2376 | + } | |
2377 | + | |
2371 | 2378 | for ( auto *kvNode : this->replacements ) |
2372 | 2379 | { |
2373 | - env->gcReachSched.OnRemoveConnection( this, kvNode->GetKey() ); | |
2380 | + Step *keyStep = kvNode->GetKey(); | |
2381 | + | |
2382 | + if ( keyStep != exec ) | |
2383 | + { | |
2384 | + env->gcReachSched.OnRemoveConnection( this, keyStep ); | |
2385 | + } | |
2374 | 2386 | } |
2375 | 2387 | |
2376 | 2388 | for ( const valinfo& vinfo : this->valrefs ) |
@@ -2377,7 +2389,7 @@ | ||
2377 | 2389 | { |
2378 | 2390 | Step *valstep = vinfo.step; |
2379 | 2391 | |
2380 | - if ( this->replacements.Find( valstep ) == nullptr ) | |
2392 | + if ( valstep != exec && this->replacements.Find( valstep ) == nullptr ) | |
2381 | 2393 | { |
2382 | 2394 | env->gcReachSched.OnRemoveConnection( this, valstep ); |
2383 | 2395 | } |
@@ -2394,6 +2406,62 @@ | ||
2394 | 2406 | // First we iterate through all keys. |
2395 | 2407 | // Then we iterate through all values which are not - at the same time - keys. |
2396 | 2408 | |
2409 | + auto isInternalNode = [&]( Step *node ) | |
2410 | + { | |
2411 | + if ( this->exec == node ) | |
2412 | + return true; | |
2413 | + | |
2414 | + return false; | |
2415 | + }; | |
2416 | + | |
2417 | + auto isKeyNode = [&]( Step *node ) | |
2418 | + { | |
2419 | + return ( this->replacements.Find( node ) != nullptr ); | |
2420 | + }; | |
2421 | + | |
2422 | + auto isValueNode = [&]( Step *node ) | |
2423 | + { | |
2424 | + return ( this->valrefs.Find( node ) != nullptr ); | |
2425 | + }; | |
2426 | + | |
2427 | + auto findNextInternalNode = [&]( Step *intern_prev ) -> Step* | |
2428 | + { | |
2429 | + Step *exec = this->exec; | |
2430 | + | |
2431 | + if ( intern_prev == nullptr ) | |
2432 | + { | |
2433 | + return exec; | |
2434 | + } | |
2435 | + else | |
2436 | + { | |
2437 | + return nullptr; | |
2438 | + } | |
2439 | + }; | |
2440 | + | |
2441 | + auto findNextKeyNode = [&]( Step *key_prev ) -> Step* | |
2442 | + { | |
2443 | + auto *findNode = this->replacements.FindJustAbove( key_prev ); | |
2444 | + | |
2445 | + if ( findNode == nullptr ) | |
2446 | + return nullptr; | |
2447 | + | |
2448 | + typename decltype(this->replacements)::iterator iter( findNode ); | |
2449 | + | |
2450 | + while ( iter.IsEnd() == false ) | |
2451 | + { | |
2452 | + Step *attempt_return = iter.Resolve()->GetKey(); | |
2453 | + | |
2454 | + if ( this->exec != attempt_return ) | |
2455 | + { | |
2456 | + return attempt_return; | |
2457 | + } | |
2458 | + | |
2459 | + iter.Increment(); | |
2460 | + } | |
2461 | + | |
2462 | + return nullptr; | |
2463 | + }; | |
2464 | + | |
2397 | 2465 | auto findNextValNode = [&]( Step *val_prev ) -> Step* |
2398 | 2466 | { |
2399 | 2467 | auto *findNode = this->valrefs.FindJustAbove( val_prev ); |
@@ -2407,7 +2475,7 @@ | ||
2407 | 2475 | { |
2408 | 2476 | Step *attempt_return = iter.Resolve()->GetValue().step; |
2409 | 2477 | |
2410 | - if ( this->replacements.Find( attempt_return ) == nullptr ) | |
2478 | + if ( this->exec != attempt_return && this->replacements.Find( attempt_return ) == nullptr ) | |
2411 | 2479 | { |
2412 | 2480 | return attempt_return; |
2413 | 2481 | } |
@@ -2418,52 +2486,87 @@ | ||
2418 | 2486 | return nullptr; |
2419 | 2487 | }; |
2420 | 2488 | |
2421 | - Step *first = this->exec; | |
2489 | + enum class eListPresence | |
2490 | + { | |
2491 | + INTERN, | |
2492 | + KEYS, | |
2493 | + VALUES | |
2494 | + }; | |
2422 | 2495 | |
2423 | - if ( prev == nullptr || first != nullptr && prev == first ) | |
2496 | + eListPresence list_presence; | |
2497 | + Step *iter = prev; | |
2498 | + | |
2499 | + // Find the starting iter step. | |
2500 | + if ( prev == nullptr ) | |
2424 | 2501 | { |
2425 | - if ( prev == nullptr && first != nullptr ) | |
2502 | + list_presence = eListPresence::INTERN; | |
2503 | + } | |
2504 | + else | |
2505 | + { | |
2506 | + if ( isInternalNode( prev ) ) | |
2426 | 2507 | { |
2427 | - return first; | |
2508 | + list_presence = eListPresence::INTERN; | |
2428 | 2509 | } |
2429 | - | |
2430 | - auto *keyMinNode = this->replacements.GetMinimumByKey(); | |
2431 | - | |
2432 | - if ( keyMinNode ) | |
2510 | + else if ( isKeyNode( prev ) ) | |
2433 | 2511 | { |
2434 | - return keyMinNode->GetKey(); | |
2512 | + list_presence = eListPresence::KEYS; | |
2435 | 2513 | } |
2514 | + else if ( isValueNode( prev ) ) | |
2515 | + { | |
2516 | + list_presence = eListPresence::VALUES; | |
2517 | + } | |
2518 | + else | |
2519 | + { | |
2520 | + // ??? | |
2521 | + return nullptr; | |
2522 | + } | |
2523 | + } | |
2436 | 2524 | |
2437 | - return findNextValNode( nullptr ); | |
2438 | - } | |
2439 | - | |
2440 | - // If the previous node is inside the keys, then return the next key. | |
2441 | - // If there is no more next key then we return the first value. | |
2442 | - if ( this->replacements.Find( prev ) != nullptr ) | |
2525 | + while ( true ) | |
2443 | 2526 | { |
2444 | - auto *nextByKeys = this->replacements.FindMinimumByCriteria( | |
2445 | - [&]( auto *leftNode ) | |
2446 | - { | |
2447 | - eir::eCompResult cmpRes = eir::DefaultValueCompare( leftNode->GetKey(), prev ); | |
2527 | + // Increment until we find a valid next step. | |
2528 | + if ( list_presence == eListPresence::INTERN ) | |
2529 | + { | |
2530 | + iter = findNextInternalNode( iter ); | |
2531 | + } | |
2532 | + else if ( list_presence == eListPresence::KEYS ) | |
2533 | + { | |
2534 | + iter = findNextKeyNode( iter ); | |
2535 | + } | |
2536 | + else if ( list_presence == eListPresence::VALUES ) | |
2537 | + { | |
2538 | + iter = findNextValNode( iter ); | |
2539 | + } | |
2448 | 2540 | |
2449 | - if ( cmpRes == eir::eCompResult::LEFT_LESS || cmpRes == eir::eCompResult::EQUAL ) | |
2450 | - { | |
2451 | - return eir::eCompResult::LEFT_LESS; | |
2452 | - } | |
2541 | + // Check for validity. | |
2542 | + if ( iter != nullptr ) | |
2543 | + break; | |
2453 | 2544 | |
2454 | - return eir::eCompResult::EQUAL; | |
2455 | - } | |
2456 | - ); | |
2457 | - | |
2458 | - if ( nextByKeys == nullptr ) | |
2545 | + if ( list_presence == eListPresence::INTERN ) | |
2459 | 2546 | { |
2460 | - return findNextValNode( nullptr ); | |
2547 | + list_presence = eListPresence::KEYS; | |
2548 | + iter = nullptr; | |
2461 | 2549 | } |
2462 | - | |
2463 | - return nextByKeys->GetValue(); | |
2550 | + else if ( list_presence == eListPresence::KEYS ) | |
2551 | + { | |
2552 | + list_presence = eListPresence::VALUES; | |
2553 | + iter = nullptr; | |
2554 | + } | |
2555 | + else if ( list_presence == eListPresence::VALUES ) | |
2556 | + { | |
2557 | + break; | |
2558 | + } | |
2559 | + else | |
2560 | + { | |
2561 | + // ??? | |
2562 | +#ifdef _DEBUG | |
2563 | + assert( 0 ); | |
2564 | +#endif //_DEBUG | |
2565 | + return nullptr; | |
2566 | + } | |
2464 | 2567 | } |
2465 | - | |
2466 | - return findNextValNode( prev ); | |
2568 | + | |
2569 | + return iter; | |
2467 | 2570 | } |
2468 | 2571 | |
2469 | 2572 | bool IsUnambiguousCall( void ) const noexcept override |
@@ -2545,18 +2648,23 @@ | ||
2545 | 2648 | if ( old_exec == exec ) |
2546 | 2649 | return; |
2547 | 2650 | |
2548 | - bool prev_is_new_exec_referenced = _is_step_referenced( exec ); | |
2651 | + bool prev_is_new_exec_referenced; | |
2549 | 2652 | |
2653 | + if ( exec != nullptr ) | |
2654 | + { | |
2655 | + prev_is_new_exec_referenced = _is_step_referenced( exec ); | |
2656 | + } | |
2657 | + | |
2550 | 2658 | this->exec = exec; |
2551 | 2659 | |
2552 | 2660 | LexingEnvironment *env = this->env; |
2553 | 2661 | |
2554 | - if ( _is_step_referenced( old_exec ) == false ) | |
2662 | + if ( old_exec != nullptr && _is_step_referenced( old_exec ) == false ) | |
2555 | 2663 | { |
2556 | 2664 | env->gcReachSched.OnRemoveConnection( this, old_exec ); |
2557 | 2665 | } |
2558 | 2666 | |
2559 | - if ( prev_is_new_exec_referenced == false ) | |
2667 | + if ( exec != nullptr && prev_is_new_exec_referenced == false ) | |
2560 | 2668 | { |
2561 | 2669 | env->gcReachSched.OnAddedConnection( this, exec ); |
2562 | 2670 | } |
@@ -2621,6 +2729,16 @@ | ||
2621 | 2729 | this->replacements.RemoveNode( findNode ); |
2622 | 2730 | |
2623 | 2731 | on_value_remove( old_value ); |
2732 | + | |
2733 | + if ( old_value != to_replace ) | |
2734 | + { | |
2735 | + bool is_val_ref = _is_step_referenced( old_value ); | |
2736 | + | |
2737 | + if ( is_val_ref == false ) | |
2738 | + { | |
2739 | + env->gcReachSched.OnRemoveConnection( this, old_value ); | |
2740 | + } | |
2741 | + } | |
2624 | 2742 | } |
2625 | 2743 | } |
2626 | 2744 | else |
@@ -2632,6 +2750,16 @@ | ||
2632 | 2750 | if ( old_step && old_step != replace_with ) |
2633 | 2751 | { |
2634 | 2752 | on_value_remove( old_step ); |
2753 | + | |
2754 | + if ( old_step != to_replace ) | |
2755 | + { | |
2756 | + bool is_val_ref = _is_step_referenced( old_step ); | |
2757 | + | |
2758 | + if ( is_val_ref == false ) | |
2759 | + { | |
2760 | + env->gcReachSched.OnRemoveConnection( this, old_step ); | |
2761 | + } | |
2762 | + } | |
2635 | 2763 | } |
2636 | 2764 | |
2637 | 2765 | this->valrefs[ replace_with ].refcnt++; |
@@ -2678,7 +2806,7 @@ | ||
2678 | 2806 | return ( find_node ? find_node->GetValue() : nullptr ); |
2679 | 2807 | } |
2680 | 2808 | |
2681 | - void ClearReplacements( void ) | |
2809 | + inline void ClearReplacements( void ) | |
2682 | 2810 | { |
2683 | 2811 | LexingEnvironment *env = this->env; |
2684 | 2812 |
@@ -4304,9 +4432,9 @@ | ||
4304 | 4432 | |
4305 | 4433 | if ( altsNode == nullptr ) |
4306 | 4434 | { |
4307 | - // Optimization: an empty alternatives results in a failure. | |
4435 | + // Optimization: an empty alternatives results in a success. | |
4308 | 4436 | has_op_finished = true; |
4309 | - is_op_successful = false; | |
4437 | + is_op_successful = true; | |
4310 | 4438 | } |
4311 | 4439 | else |
4312 | 4440 | { |
@@ -4371,10 +4499,12 @@ | ||
4371 | 4499 | { |
4372 | 4500 | auto& alts = altsteps->alts; |
4373 | 4501 | |
4374 | - if ( alts.GetCount() == entry.process_idx ) | |
4502 | + size_t alts_count = ( alts.GetCount() ); | |
4503 | + | |
4504 | + if ( alts_count == entry.process_idx ) | |
4375 | 4505 | { |
4376 | 4506 | has_op_finished = true; |
4377 | - is_op_successful = false; | |
4507 | + is_op_successful = ( alts_count == 0 ); | |
4378 | 4508 | } |
4379 | 4509 | else |
4380 | 4510 | { |
@@ -4447,6 +4577,7 @@ | ||
4447 | 4577 | |
4448 | 4578 | if ( idx == 2 ) |
4449 | 4579 | { |
4580 | + // We assume that the extend-step is never structurally empty. | |
4450 | 4581 | has_op_finished = true; |
4451 | 4582 | is_op_successful = false; |
4452 | 4583 | } |
@@ -4510,10 +4641,12 @@ | ||
4510 | 4641 | // The crux is in what process_idx it starts from. |
4511 | 4642 | auto& alts = procaltstep->alts; |
4512 | 4643 | |
4513 | - if ( alts.GetCount() == entry.process_idx ) | |
4644 | + size_t alts_count = alts.GetCount(); | |
4645 | + | |
4646 | + if ( alts_count == entry.process_idx ) | |
4514 | 4647 | { |
4515 | 4648 | has_op_finished = true; |
4516 | - is_op_successful = false; | |
4649 | + is_op_successful = ( alts_count == 0 ); | |
4517 | 4650 | } |
4518 | 4651 | else |
4519 | 4652 | { |
@@ -88,6 +88,10 @@ | ||
88 | 88 | { |
89 | 89 | using UnaryOperation::UnaryOperation; |
90 | 90 | }; |
91 | +struct AddressOfOperation : public UnaryOperation | |
92 | +{ | |
93 | + using UnaryOperation::UnaryOperation; | |
94 | +}; | |
91 | 95 | |
92 | 96 | struct BinaryOperation : public Operation |
93 | 97 | { |
@@ -134,6 +138,14 @@ | ||
134 | 138 | { |
135 | 139 | using BinaryOperation::BinaryOperation; |
136 | 140 | }; |
141 | +struct BitshiftLeftOperation : public BinaryOperation | |
142 | +{ | |
143 | + using BinaryOperation::BinaryOperation; | |
144 | +}; | |
145 | +struct BitshiftRightOperation : public BinaryOperation | |
146 | +{ | |
147 | + using BinaryOperation::BinaryOperation; | |
148 | +}; | |
137 | 149 | struct CompareEqualityOperation : public BinaryOperation |
138 | 150 | { |
139 | 151 | using BinaryOperation::BinaryOperation; |
@@ -198,7 +210,24 @@ | ||
198 | 210 | COSNode *what; |
199 | 211 | depVector <COSNode*> params; |
200 | 212 | }; |
213 | +struct ArrayInitOperation : public Operation | |
214 | +{ | |
215 | + inline ArrayInitOperation( COSNode *what = nullptr, depVector <COSNode*> items = {} ) noexcept : what( what ), items( std::move( items ) ) | |
216 | + { | |
217 | + return; | |
218 | + } | |
219 | + inline ArrayInitOperation( const ArrayInitOperation& ) = default; | |
220 | + inline ArrayInitOperation( ArrayInitOperation&& right ) noexcept : items( std::move( right.items ) ) | |
221 | + { | |
222 | + this->what = right.what; | |
223 | + | |
224 | + right.what = nullptr; | |
225 | + } | |
201 | 226 | |
227 | + COSNode *what; | |
228 | + depVector <COSNode*> items; | |
229 | +}; | |
230 | + | |
202 | 231 | struct NewOperation : public Operation |
203 | 232 | { |
204 | 233 | inline NewOperation( COSNode *type = nullptr, depVector <COSNode*> params = {} ) noexcept : type( type ), params( std::move( params ) ) |
@@ -569,7 +598,58 @@ | ||
569 | 598 | |
570 | 599 | depMultiString numeric_string; |
571 | 600 | }; |
601 | +struct SpecifierOperator : public COSNode | |
602 | +{ | |
603 | + enum class eOpType | |
604 | + { | |
605 | + UNDEFINED, | |
572 | 606 | |
607 | + ADD, | |
608 | + SUBTRACT, | |
609 | + MULTIPLY, | |
610 | + DIVIDE, | |
611 | + MODULUS, | |
612 | + BIT_XOR, | |
613 | + BIT_AND, | |
614 | + BIT_OR, | |
615 | + LOGICAL_NEGATE, | |
616 | + DOT, | |
617 | + ASSIGN, | |
618 | + BIT_NEGATE, | |
619 | + | |
620 | + ASSIGN_ADD, | |
621 | + ASSIGN_SUBTRACT, | |
622 | + ASSIGN_MULTIPLY, | |
623 | + ASSIGN_DIVIDE, | |
624 | + ASSIGN_MODULUS, | |
625 | + ASSIGN_BIT_XOR, | |
626 | + ASSIGN_BIT_AND, | |
627 | + ASSIGN_BIT_OR, | |
628 | + ASSIGN_DOT, | |
629 | + | |
630 | + COMPARE_EQUALITY, | |
631 | + COMPARE_GREATER_THAN, | |
632 | + COMPARE_LESS_THAN, | |
633 | + COMPARE_GREATER_THAN_EQUAL, | |
634 | + COMPARE_LESS_THAN_EQUAL, | |
635 | + COMPARE_INEQUALITY, | |
636 | + | |
637 | + LOGICAL_AND, | |
638 | + LOGICAL_OR, | |
639 | + BITSHIFT_LEFT, | |
640 | + BITSHIFT_RIGHT | |
641 | + }; | |
642 | + | |
643 | + inline SpecifierOperator( eOpType op_type = eOpType::UNDEFINED ) noexcept : op_type( op_type ) | |
644 | + { | |
645 | + return; | |
646 | + } | |
647 | + inline SpecifierOperator( const SpecifierOperator& ) = default; | |
648 | + inline SpecifierOperator( SpecifierOperator&& ) = default; | |
649 | + | |
650 | + eOpType op_type = eOpType::UNDEFINED; | |
651 | +}; | |
652 | + | |
573 | 653 | struct PointerTypeSpecifier : public COSNode |
574 | 654 | { |
575 | 655 | inline PointerTypeSpecifier( COSNode *spec = nullptr ) noexcept : spec( spec ) |
@@ -805,6 +885,148 @@ | ||
805 | 885 | }; |
806 | 886 | lexer.GetNamedProduction( "spec" ).GetLastStep()->setSelector <direct_obj_build_selector <char, ResolveSpecifierOperation, COSNode, dynspec_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); |
807 | 887 | } |
888 | + assert( lexer.CompileProduction( compiler, "optoksingle_epostfix", "'+-*/%^&|!.=<>'" ) == true ); | |
889 | + assert( lexer.CompileProduction( compiler, "optoksingle", "'~' | optoksingle_epostfix" ) == true ); | |
890 | + assert( lexer.CompileProduction( compiler, "optoks", "\"&&\" | \"||\" | \"<<\" | \">>\" | optoksingle_epostfix '=' | optoksingle" ) == true ); | |
891 | + assert( lexer.CompileProduction( compiler, "spec", "\"operator\" spaces optok:optoks" ) == true ); | |
892 | + { | |
893 | + struct specifier_op_dispatcher | |
894 | + { | |
895 | + static inline void AssignAttributeTo( SpecifierOperator *assign_to, const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) | |
896 | + { | |
897 | + if ( attrib != "optok" ) | |
898 | + return; | |
899 | + | |
900 | + typedef SpecifierOperator::eOpType eOpType; | |
901 | + | |
902 | + if ( value == "+" ) | |
903 | + { | |
904 | + assign_to->op_type = eOpType::ADD; | |
905 | + } | |
906 | + else if ( value == "+=" ) | |
907 | + { | |
908 | + assign_to->op_type = eOpType::ASSIGN_ADD; | |
909 | + } | |
910 | + else if ( value == "-" ) | |
911 | + { | |
912 | + assign_to->op_type = eOpType::SUBTRACT; | |
913 | + } | |
914 | + else if ( value == "-=" ) | |
915 | + { | |
916 | + assign_to->op_type = eOpType::ASSIGN_SUBTRACT; | |
917 | + } | |
918 | + else if ( value == "*" ) | |
919 | + { | |
920 | + assign_to->op_type = eOpType::MULTIPLY; | |
921 | + } | |
922 | + else if ( value == "*=" ) | |
923 | + { | |
924 | + assign_to->op_type = eOpType::ASSIGN_MULTIPLY; | |
925 | + } | |
926 | + else if ( value == "/" ) | |
927 | + { | |
928 | + assign_to->op_type = eOpType::DIVIDE; | |
929 | + } | |
930 | + else if ( value == "/=" ) | |
931 | + { | |
932 | + assign_to->op_type = eOpType::ASSIGN_DIVIDE; | |
933 | + } | |
934 | + else if ( value == "%" ) | |
935 | + { | |
936 | + assign_to->op_type = eOpType::MODULUS; | |
937 | + } | |
938 | + else if ( value == "%=" ) | |
939 | + { | |
940 | + assign_to->op_type = eOpType::ASSIGN_MODULUS; | |
941 | + } | |
942 | + else if ( value == "^" ) | |
943 | + { | |
944 | + assign_to->op_type = eOpType::BIT_XOR; | |
945 | + } | |
946 | + else if ( value == "^=" ) | |
947 | + { | |
948 | + assign_to->op_type = eOpType::ASSIGN_BIT_XOR; | |
949 | + } | |
950 | + else if ( value == "&" ) | |
951 | + { | |
952 | + assign_to->op_type = eOpType::BIT_AND; | |
953 | + } | |
954 | + else if ( value == "&=" ) | |
955 | + { | |
956 | + assign_to->op_type = eOpType::ASSIGN_BIT_AND; | |
957 | + } | |
958 | + else if ( value == "|" ) | |
959 | + { | |
960 | + assign_to->op_type = eOpType::BIT_OR; | |
961 | + } | |
962 | + else if ( value == "|=" ) | |
963 | + { | |
964 | + assign_to->op_type = eOpType::ASSIGN_BIT_OR; | |
965 | + } | |
966 | + else if ( value == "!" ) | |
967 | + { | |
968 | + assign_to->op_type = eOpType::LOGICAL_NEGATE; | |
969 | + } | |
970 | + else if ( value == "!=" ) | |
971 | + { | |
972 | + assign_to->op_type = eOpType::COMPARE_INEQUALITY; | |
973 | + } | |
974 | + else if ( value == "." ) | |
975 | + { | |
976 | + assign_to->op_type = eOpType::DOT; | |
977 | + } | |
978 | + else if ( value == ".=" ) | |
979 | + { | |
980 | + assign_to->op_type = eOpType::ASSIGN_DOT; | |
981 | + } | |
982 | + else if ( value == "=" ) | |
983 | + { | |
984 | + assign_to->op_type = eOpType::ASSIGN; | |
985 | + } | |
986 | + else if ( value == "==" ) | |
987 | + { | |
988 | + assign_to->op_type = eOpType::COMPARE_EQUALITY; | |
989 | + } | |
990 | + else if ( value == "~" ) | |
991 | + { | |
992 | + assign_to->op_type = eOpType::BIT_NEGATE; | |
993 | + } | |
994 | + else if ( value == "<" ) | |
995 | + { | |
996 | + assign_to->op_type = eOpType::COMPARE_LESS_THAN; | |
997 | + } | |
998 | + else if ( value == "<=" ) | |
999 | + { | |
1000 | + assign_to->op_type = eOpType::COMPARE_LESS_THAN_EQUAL; | |
1001 | + } | |
1002 | + else if ( value == ">" ) | |
1003 | + { | |
1004 | + assign_to->op_type = eOpType::COMPARE_GREATER_THAN; | |
1005 | + } | |
1006 | + else if ( value == ">=" ) | |
1007 | + { | |
1008 | + assign_to->op_type = eOpType::COMPARE_GREATER_THAN_EQUAL; | |
1009 | + } | |
1010 | + else if ( value == "&&" ) | |
1011 | + { | |
1012 | + assign_to->op_type = eOpType::BIT_AND; | |
1013 | + } | |
1014 | + else if ( value == "||" ) | |
1015 | + { | |
1016 | + assign_to->op_type = eOpType::BIT_OR; | |
1017 | + } | |
1018 | + else if ( value == "<<" ) | |
1019 | + { | |
1020 | + assign_to->op_type = eOpType::BITSHIFT_LEFT; | |
1021 | + } | |
1022 | + else if ( value == ">>" ) | |
1023 | + { | |
1024 | + assign_to->op_type = eOpType::BITSHIFT_RIGHT; | |
1025 | + } | |
1026 | + } | |
1027 | + }; | |
1028 | + lexer.GetNamedProduction( "spec" ).GetLastStep()->setSelector <direct_obj_build_selector <char, SpecifierOperator, COSNode, specifier_op_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); | |
1029 | + } | |
808 | 1030 | assert( lexer.CompileProduction( compiler, "dtypedef", "\"typedef\" spaces tmultdecl spaces ';'" ) == true ); |
809 | 1031 | assert( lexer.CompileProduction( compiler, "block", "'{' spaces [<0>statement:extended statement, spaces] spaces '}'" ) == true ); |
810 | 1032 | { |
@@ -843,6 +1065,54 @@ | ||
843 | 1065 | }; |
844 | 1066 | operation.GetLastStep()->setSelector <right_associative_selector <char, COSNode, assignment_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); |
845 | 1067 | } |
1068 | + assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:'|' spaces]" ) != nullptr ); | |
1069 | + { | |
1070 | + struct bor_dispatcher | |
1071 | + { | |
1072 | + inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) | |
1073 | + { | |
1074 | + return; | |
1075 | + } | |
1076 | + | |
1077 | + inline COSNode* CreateOperation( COSNode *left, COSNode *right ) | |
1078 | + { | |
1079 | + return new BitwiseOrOperation( left, right ); | |
1080 | + } | |
1081 | + }; | |
1082 | + operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, bor_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); | |
1083 | + } | |
1084 | + assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:'^' spaces]" ) != nullptr ); | |
1085 | + { | |
1086 | + struct bxor_dispatcher | |
1087 | + { | |
1088 | + inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) | |
1089 | + { | |
1090 | + return; | |
1091 | + } | |
1092 | + | |
1093 | + inline COSNode* CreateOperation( COSNode *left, COSNode *right ) | |
1094 | + { | |
1095 | + return new BitwiseXorOperation( left, right ); | |
1096 | + } | |
1097 | + }; | |
1098 | + operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, bxor_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); | |
1099 | + } | |
1100 | + assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:'&' spaces]" ) != nullptr ); | |
1101 | + { | |
1102 | + struct band_dispatcher | |
1103 | + { | |
1104 | + inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) | |
1105 | + { | |
1106 | + return; | |
1107 | + } | |
1108 | + | |
1109 | + inline COSNode* CreateOperation( COSNode *left, COSNode *right ) | |
1110 | + { | |
1111 | + return new BitwiseAndOperation( left, right ); | |
1112 | + } | |
1113 | + }; | |
1114 | + operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, band_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); | |
1115 | + } | |
846 | 1116 | assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:\"||\" spaces]" ) != nullptr ); |
847 | 1117 | { |
848 | 1118 | struct logical_or_dispatcher |
@@ -959,53 +1229,51 @@ | ||
959 | 1229 | }; |
960 | 1230 | operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, logical_comparison_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); |
961 | 1231 | } |
962 | - assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:'|' spaces]" ) != nullptr ); | |
1232 | + assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:(\"<<\"|\">>\") spaces]" ) != nullptr ); | |
963 | 1233 | { |
964 | - struct bor_dispatcher | |
1234 | + struct bitwise_shift_dispatcher | |
965 | 1235 | { |
966 | - inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) | |
1236 | + enum class eOpType | |
967 | 1237 | { |
968 | - return; | |
969 | - } | |
1238 | + UNDEFINED, | |
1239 | + LEFT_SHIFT, | |
1240 | + RIGHT_SHIFT | |
1241 | + }; | |
970 | 1242 | |
971 | - inline COSNode* CreateOperation( COSNode *left, COSNode *right ) | |
972 | - { | |
973 | - return new BitwiseOrOperation( left, right ); | |
974 | - } | |
975 | - }; | |
976 | - operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, bor_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); | |
977 | - } | |
978 | - assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:'^' spaces]" ) != nullptr ); | |
979 | - { | |
980 | - struct bxor_dispatcher | |
981 | - { | |
982 | 1243 | inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) |
983 | 1244 | { |
984 | - return; | |
1245 | + if ( attrib == "optype" ) | |
1246 | + { | |
1247 | + if ( value == "<<" ) | |
1248 | + { | |
1249 | + this->op_type = eOpType::LEFT_SHIFT; | |
1250 | + } | |
1251 | + else if ( value == ">>" ) | |
1252 | + { | |
1253 | + this->op_type = eOpType::RIGHT_SHIFT; | |
1254 | + } | |
1255 | + } | |
985 | 1256 | } |
986 | 1257 | |
987 | 1258 | inline COSNode* CreateOperation( COSNode *left, COSNode *right ) |
988 | 1259 | { |
989 | - return new BitwiseXorOperation( left, right ); | |
1260 | + eOpType op_type = this->op_type; | |
1261 | + | |
1262 | + if ( op_type == eOpType::LEFT_SHIFT ) | |
1263 | + { | |
1264 | + return new BitshiftLeftOperation( left, right ); | |
1265 | + } | |
1266 | + else if ( op_type == eOpType::RIGHT_SHIFT ) | |
1267 | + { | |
1268 | + return new BitshiftRightOperation( left, right ); | |
1269 | + } | |
1270 | + | |
1271 | + throw lexing_invalid_parameter_exception(); | |
990 | 1272 | } |
991 | - }; | |
992 | - operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, bxor_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); | |
993 | - } | |
994 | - assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:'&' spaces]" ) != nullptr ); | |
995 | - { | |
996 | - struct band_dispatcher | |
997 | - { | |
998 | - inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) | |
999 | - { | |
1000 | - return; | |
1001 | - } | |
1002 | 1273 | |
1003 | - inline COSNode* CreateOperation( COSNode *left, COSNode *right ) | |
1004 | - { | |
1005 | - return new BitwiseAndOperation( left, right ); | |
1006 | - } | |
1274 | + eOpType op_type = eOpType::UNDEFINED; | |
1007 | 1275 | }; |
1008 | - operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, band_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); | |
1276 | + operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, bitwise_shift_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); | |
1009 | 1277 | } |
1010 | 1278 | assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:('-'|'+') spaces]" ) != nullptr ); |
1011 | 1279 | { |
@@ -1175,7 +1443,7 @@ | ||
1175 | 1443 | }; |
1176 | 1444 | operation.GetLastStep()->setSelector <unary_operation_selector <char, COSNode, quickunamod_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); |
1177 | 1445 | } |
1178 | - assert( lexer.CompileInto( compiler, operation, "[<0,e>optype:'-~!*', spaces] opitem:operation" ) != nullptr ); | |
1446 | + assert( lexer.CompileInto( compiler, operation, "[<0,e>optype:'-~!*&', spaces] opitem:operation" ) != nullptr ); | |
1179 | 1447 | { |
1180 | 1448 | struct unary_negation_dispatcher |
1181 | 1449 | { |
@@ -1185,7 +1453,8 @@ | ||
1185 | 1453 | NUMERIC_NEGATION, |
1186 | 1454 | BITWISE_NEGATION, |
1187 | 1455 | LOGICAL_NEGATION, |
1188 | - PTR_RESOLVE | |
1456 | + PTR_RESOLVE, | |
1457 | + ADDRESS_OF | |
1189 | 1458 | }; |
1190 | 1459 | |
1191 | 1460 | inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) |
@@ -1208,6 +1477,10 @@ | ||
1208 | 1477 | { |
1209 | 1478 | this->op_type = eOpType::PTR_RESOLVE; |
1210 | 1479 | } |
1480 | + else if ( value == "&" ) | |
1481 | + { | |
1482 | + this->op_type = eOpType::ADDRESS_OF; | |
1483 | + } | |
1211 | 1484 | } |
1212 | 1485 | } |
1213 | 1486 |
@@ -1231,6 +1504,10 @@ | ||
1231 | 1504 | { |
1232 | 1505 | return new PointerResolveOperation( op ); |
1233 | 1506 | } |
1507 | + else if ( op_type == eOpType::ADDRESS_OF ) | |
1508 | + { | |
1509 | + return new AddressOfOperation( op ); | |
1510 | + } | |
1234 | 1511 | |
1235 | 1512 | throw lexing_invalid_parameter_exception(); |
1236 | 1513 | } |
@@ -1368,31 +1645,113 @@ | ||
1368 | 1645 | }; |
1369 | 1646 | operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, key_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); |
1370 | 1647 | } |
1371 | - assert( lexer.CompileInto( compiler, operation, "[istempl_inst:\"template\" spaces op:operation spaces '<' spaces [<0> procgate type, spaces ',' spaces] spaces '>' | op:operation, spaces '.' spaces]" ) != nullptr ); | |
1648 | + assert( lexer.CompileInto( compiler, operation, "op:operation (spaces '{' spaces [<0> item:procgate operation, spaces ',' spaces] spaces endarrtok:'}')^0:1" ) != nullptr ); | |
1372 | 1649 | { |
1373 | - struct dot_with_templ_dispatcher | |
1650 | + struct arrayinit_selector | |
1374 | 1651 | { |
1652 | + inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) | |
1653 | + { | |
1654 | + if ( attrib == "endarrtok" ) | |
1655 | + { | |
1656 | + this->root = new ArrayInitOperation( this->root, std::move( this->items ) ); | |
1657 | + } | |
1658 | + } | |
1375 | 1659 | |
1660 | + inline bool AssignNode( const eir::FixedString <char>& attrib, COSNode *node ) | |
1661 | + { | |
1662 | + if ( attrib == "op" ) | |
1663 | + { | |
1664 | + this->root = node; | |
1665 | + return true; | |
1666 | + } | |
1667 | + if ( attrib == "item" ) | |
1668 | + { | |
1669 | + this->items.AddToBack( node ); | |
1670 | + return true; | |
1671 | + } | |
1672 | + | |
1673 | + return false; | |
1674 | + } | |
1675 | + | |
1676 | + inline COSNode* DetachFinishedNode( void ) | |
1677 | + { | |
1678 | + COSNode *result = this->root; | |
1679 | + | |
1680 | + this->root = nullptr; | |
1681 | + | |
1682 | + return result; | |
1683 | + } | |
1684 | + | |
1685 | + COSNode *root = nullptr; | |
1686 | + depVector <COSNode*> items; | |
1376 | 1687 | }; |
1688 | + operation.GetLastStep()->setSelector <arrayinit_selector> (); | |
1377 | 1689 | } |
1378 | -#if 0 | |
1379 | - assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces '.' spaces]" ) != nullptr ); | |
1690 | + assert( lexer.CompileInto( compiler, operation, "[\"template\" spaces templop:operation spaces '<' spaces [<0> templarg:procgate type, spaces ',' spaces] spaces endtempl:'>' | dotitem:operation, spaces '.' spaces]" ) != nullptr ); | |
1380 | 1691 | { |
1381 | - struct dot_dispatcher | |
1692 | + struct dot_with_templ_selector | |
1382 | 1693 | { |
1694 | + inline void AddNodeAsRootDot( COSNode *node ) | |
1695 | + { | |
1696 | + COSNode *prev_root = this->root; | |
1697 | + | |
1698 | + if ( prev_root == nullptr ) | |
1699 | + { | |
1700 | + this->root = node; | |
1701 | + return; | |
1702 | + } | |
1703 | + | |
1704 | + this->root = new DotOperation( prev_root, node ); | |
1705 | + } | |
1706 | + | |
1383 | 1707 | inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) |
1384 | 1708 | { |
1385 | - return; | |
1709 | + if ( attrib == "endtempl" ) | |
1710 | + { | |
1711 | + this->AddNodeAsRootDot( templop ); | |
1712 | + this->root = new TemplateInstantiationOperation( this->root, std::move( this->templargs ) ); | |
1713 | + | |
1714 | + this->templop = nullptr; | |
1715 | + return; | |
1716 | + } | |
1386 | 1717 | } |
1387 | 1718 | |
1388 | - inline COSNode* CreateOperation( COSNode *left, COSNode *right ) | |
1719 | + inline bool AssignNode( const eir::FixedString <char>& attrib, COSNode *node ) | |
1389 | 1720 | { |
1390 | - return new DotOperation( left, right ); | |
1721 | + if ( attrib == "dotitem" ) | |
1722 | + { | |
1723 | + this->AddNodeAsRootDot( node ); | |
1724 | + return true; | |
1725 | + } | |
1726 | + else if ( attrib == "templop" ) | |
1727 | + { | |
1728 | + this->templop = node; | |
1729 | + return true; | |
1730 | + } | |
1731 | + else if ( attrib == "templarg" ) | |
1732 | + { | |
1733 | + this->templargs.AddToBack( node ); | |
1734 | + return true; | |
1735 | + } | |
1736 | + | |
1737 | + return false; | |
1391 | 1738 | } |
1739 | + | |
1740 | + inline COSNode* DetachFinishedNode( void ) noexcept | |
1741 | + { | |
1742 | + COSNode *result = this->root; | |
1743 | + | |
1744 | + this->root = nullptr; | |
1745 | + | |
1746 | + return result; | |
1747 | + } | |
1748 | + | |
1749 | + COSNode *root = nullptr; | |
1750 | + COSNode *templop = nullptr; | |
1751 | + depVector <COSNode*> templargs; | |
1392 | 1752 | }; |
1393 | - operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, dot_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); | |
1753 | + operation.GetLastStep()->setSelector <dot_with_templ_selector> (); | |
1394 | 1754 | } |
1395 | -#endif //0 | |
1396 | 1755 | |
1397 | 1756 | auto tailop = lexer.MakeStep <decltype(lexer)::RuntimeEnv::StepAlternatives> (); |
1398 | 1757 |
@@ -1418,6 +1777,28 @@ | ||
1418 | 1777 | }; |
1419 | 1778 | tailop.GetLastStep()->setSelector <direct_obj_build_selector <char, NewOperation, COSNode, new_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); |
1420 | 1779 | } |
1780 | + assert( lexer.CompileInto( compiler, tailop, "\"cast\" spaces '<' spaces totype:type spaces '>' spaces '(' spaces castobj:procgate operation spaces ')'" ) != nullptr ); | |
1781 | + { | |
1782 | + struct cast_dispatcher | |
1783 | + { | |
1784 | + static inline bool AssignNodeTo( CastOperation *assign_to, const eir::FixedString <char>& attrib, COSNode *node ) | |
1785 | + { | |
1786 | + if ( attrib == "totype" ) | |
1787 | + { | |
1788 | + assign_to->totype = node; | |
1789 | + return true; | |
1790 | + } | |
1791 | + if ( attrib == "castobj" ) | |
1792 | + { | |
1793 | + assign_to->castobj = node; | |
1794 | + return true; | |
1795 | + } | |
1796 | + | |
1797 | + return false; | |
1798 | + } | |
1799 | + }; | |
1800 | + tailop.GetLastStep()->setSelector <direct_obj_build_selector <char, CastOperation, COSNode, cast_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); | |
1801 | + } | |
1421 | 1802 | assert( lexer.CompileInto( compiler, tailop, "name" ) != nullptr ); |
1422 | 1803 | assert( lexer.CompileInto( compiler, tailop, "number" ) != nullptr ); |
1423 | 1804 | assert( lexer.CompileInto( compiler, tailop, "'{' spaces [item:procgate operation, spaces ',' spaces] spaces '}'" ) != nullptr ); |
@@ -2055,8 +2436,8 @@ | ||
2055 | 2436 | }; |
2056 | 2437 | lexer.GetNamedProduction( "tmultdecl" ).setSelector <tmultdecl_selector> (); |
2057 | 2438 | } |
2058 | - assert( lexer.CompileProduction( compiler, "funcsigdecl", "functag spaces ( '(' spaces locator spaces (subfunc:funcsigdecl|locatedname) spaces ')' | name:spec ) spaces '(' spaces paramlist_opt spaces ')'" ) == true ); | |
2059 | - assert( lexer.CompileProduction( compiler, "funcsigdecl_opt", "functag spaces ('(' spaces locator spaces (subfunc:funcsigdecl_opt|locatedname_opt) spaces ')' | (name:spec)^0:1) spaces '(' spaces paramlist_opt spaces ')'" ) == true ); | |
2439 | + assert( lexer.CompileProduction( compiler, "funcsigtempl", "functag spaces ( '(' spaces locator spaces (subfunc:funcsigtempl|locnametempl) spaces ')' | name:replaceable nameplacehold ) spaces '(' spaces paramlist_opt spaces ')'" ) == true ); // helper | |
2440 | + assert( lexer.CompileProduction( compiler, "funcsigdecl", "&(funcsigtempl, nameplacehold=spec)" ) == true ); | |
2060 | 2441 | { |
2061 | 2442 | struct funcsig_selector |
2062 | 2443 | { |
@@ -2115,15 +2496,15 @@ | ||
2115 | 2496 | FuncsigDefinition *subfunc = nullptr; |
2116 | 2497 | }; |
2117 | 2498 | lexer.GetNamedProduction( "funcsigdecl" ).setSelector <funcsig_selector> (); |
2118 | - lexer.GetNamedProduction( "funcsigdecl_opt" ).setSelector <funcsig_selector> (); | |
2119 | 2499 | } |
2120 | - assert( lexer.CompileProduction( compiler, "locatedname", "name:spec (spaces [arrspec:arrayspec, spaces])^0:1" ) == true ); // helper | |
2121 | - assert( lexer.CompileProduction( compiler, "locatedname_opt", "(name:spec)^0:1 (spaces [arrspec:arrayspec, spaces])^0:1" ) == true ); // helper. | |
2500 | + assert( lexer.CompileProduction( compiler, "locnametempl", "name:replaceable nameplacehold (spaces [arrspec:arrayspec, spaces])^0:1" ) == true ); // helper | |
2501 | + assert( lexer.CompileProduction( compiler, "locatedname", "&(locnametempl, nameplacehold=spec)" ) == true ); | |
2122 | 2502 | assert( lexer.CompileProduction( compiler, "arrayspec", "'[' spaces (idx:operation spaces)^0:1 endtok:']'" ) == true ); // helper |
2123 | 2503 | // Set-up both of the following productions in one block. |
2124 | - assert( lexer.CompileProduction( compiler, "declaration", "utype:spec spaces locator spaces (func:funcsigdecl|locatedname) declinit" ) == true ); | |
2125 | - assert( lexer.CompileProduction( compiler, "decl_optnoinit", "utype:spec spaces locator spaces (func:funcsigdecl_opt|locatedname_opt)" ) == true ); | |
2126 | - assert( lexer.CompileProduction( compiler, "decl_opt", "inline decl_optnoinit declinit" ) == true ); | |
2504 | + assert( lexer.CompileProduction( compiler, "decltemplate", "utype:spec spaces locator spaces (func:funcsigtempl|locnametempl) replaceable initplacehold" ) == true ); // helper | |
2505 | + assert( lexer.CompileProduction( compiler, "declaration", "&(decltemplate, nameplacehold=spec, initplacehold=declinit)" ) == true ); | |
2506 | + assert( lexer.CompileProduction( compiler, "decl_optnoinit", "&(decltemplate, nameplacehold=(spec)^0:1, initplacehold=empty)" ) == true ); | |
2507 | + assert( lexer.CompileProduction( compiler, "decl_opt", "&(decltemplate, nameplacehold=(spec)^0:1, initplacehold=declinit)" ) == true ); | |
2127 | 2508 | assert( lexer.CompileProduction( compiler, "multdecl", "utype:spec spaces [locator spaces (func:funcsigdecl|locatedname) declinit, spaces nextdecl:',' spaces]" ) == true ); |
2128 | 2509 | { |
2129 | 2510 | struct declaration_selector |
@@ -2383,64 +2764,8 @@ | ||
2383 | 2764 | lexer.AddStep( "initexpr", std::move( special_declinit ) ); |
2384 | 2765 | } |
2385 | 2766 | assert( lexer.CompileProduction( compiler, "declinit", "( spaces init:initexpr | spaces '=' spaces init:operation | spaces init:curlypack )^0:1" ) == true ); |
2386 | - assert( lexer.CompileProduction( compiler, "typelocator", "[<0>arrspec:arrayspec, spaces]" ) == true ); // helper | |
2387 | - assert( lexer.CompileProduction( compiler, "typefuncsig", "functag spaces ( '(' spaces locator spaces (subfunc:typefuncsig|typelocator) spaces ')' spaces )^0:1 '(' spaces paramlist_opt spaces ')'" ) == true ); | |
2388 | - { | |
2389 | - struct typefuncsig_selector | |
2390 | - { | |
2391 | - inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) | |
2392 | - { | |
2393 | - locbuild.AssignAttribute( attrib, value ); | |
2394 | - } | |
2395 | - | |
2396 | - inline bool AssignNode( const eir::FixedString <char>& attrib, COSNode *node ) | |
2397 | - { | |
2398 | - if ( attrib == "param" ) | |
2399 | - { | |
2400 | - this->funcsig.params.AddToBack( node ); | |
2401 | - return true; | |
2402 | - } | |
2403 | - else if ( attrib == "subfunc" ) | |
2404 | - { | |
2405 | - this->subfunc = dynamic_cast <FuncsigDefinition*> ( node ); | |
2406 | - return true; | |
2407 | - } | |
2408 | - else | |
2409 | - { | |
2410 | - return locbuild.AssignNode( attrib, node ); | |
2411 | - } | |
2412 | - } | |
2413 | - | |
2414 | - inline COSNode* DetachFinishedNode( void ) | |
2415 | - { | |
2416 | - COSNode *type; | |
2417 | - | |
2418 | - COSNode *detached_func = this->locbuild.EncapsulateByTypeLocators( new FuncsigDefinition( std::move( this->funcsig ) ) ); | |
2419 | - | |
2420 | - if ( FuncsigDefinition *subfunc = this->subfunc ) | |
2421 | - { | |
2422 | - FuncsigDefinition *left_most_func = subfunc->GetDeepestReturnValueFunctionSignatureType(); | |
2423 | - | |
2424 | - left_most_func->return_type = detached_func; | |
2425 | - | |
2426 | - type = subfunc; | |
2427 | - } | |
2428 | - else | |
2429 | - { | |
2430 | - type = detached_func; | |
2431 | - } | |
2432 | - | |
2433 | - return type; | |
2434 | - } | |
2435 | - | |
2436 | - declaratory_locator_builder locbuild; | |
2437 | - FuncsigDefinition *subfunc = nullptr; | |
2438 | - FuncsigDefinition funcsig; | |
2439 | - }; | |
2440 | - lexer.GetNamedProduction( "typefuncsig" ).setSelector <typefuncsig_selector> (); | |
2441 | - } | |
2442 | 2767 | assert( lexer.CompileProduction( compiler, "functag", "\"func\" | \"operator\" | \"proc\"" ) == true ); |
2443 | - assert( lexer.CompileProduction( compiler, "type", "utype:spec spaces locator spaces (func:typefuncsig|typelocator)" ) == true ); | |
2768 | + assert( lexer.CompileProduction( compiler, "type", "&(decltemplate, nameplacehold=spec, initplacehold=empty)" ) == true ); | |
2444 | 2769 | { |
2445 | 2770 | struct type_selector |
2446 | 2771 | { |
@@ -4722,7 +5047,35 @@ | ||
4722 | 5047 | |
4723 | 5048 | printf( "testing COS functions..." ); |
4724 | 5049 | { |
4725 | - // TODO. | |
5050 | + // 1) | |
5051 | + { | |
5052 | + | |
5053 | + } | |
5054 | + | |
5055 | + // 2) | |
5056 | + { | |
5057 | + | |
5058 | + } | |
5059 | + | |
5060 | + // 3) | |
5061 | + { | |
5062 | + | |
5063 | + } | |
5064 | + | |
5065 | + // 4) | |
5066 | + { | |
5067 | + | |
5068 | + } | |
5069 | + | |
5070 | + // 5) | |
5071 | + { | |
5072 | + | |
5073 | + } | |
5074 | + | |
5075 | + // 6) | |
5076 | + { | |
5077 | + | |
5078 | + } | |
4726 | 5079 | } |
4727 | 5080 | printf( "ok.\n" ); |
4728 | 5081 |