• R/O
  • SSH
  • HTTPS

eircompile: Commit


Commit MetaInfo

Revision55 (tree)
Time2021-11-19 17:07:41
Authorquiret

Log Message

- finished up the COS syntax tree generation; need to add unit tests to stabilize the expectations now (they are already prepared on paper)

Change Summary

Incremental Difference

--- eircompile/include/eircompile/lexing_compile.h (revision 54)
+++ eircompile/include/eircompile/lexing_compile.h (revision 55)
@@ -221,7 +221,7 @@
221221 sepaltsstep.SetItemStep( &producible );
222222 sepaltsstep.SetSeparationStep( &sepalts );
223223 sepaltsstep.min_item_cnt = 1;
224- sepaltsstep.setSelector <mintwo_specialized_selector <charType, ExecStep, alts_dispatcher, decltype(cenv)>> ( &cenv, this );
224+ sepaltsstep.setSelector <mintwo_specialized_selector <charType, CompiledAlternatives, ExecStep, alts_dispatcher, decltype(cenv)>> ( &cenv, this );
225225
226226 // Add the altenatives to the producibles.
227227 // They deserve to be weak-binding because they enclose operations.
@@ -281,7 +281,7 @@
281281 step_prodchain.is_alternation = true;
282282
283283 seqstep.SetConnections( { &seqstep_optattrib, &step_prodchain } );
284- seqstep.setSelector <mintwo_specialized_selector <charType, ExecStep, seqs_dispatcher, decltype(cenv)>> ( &cenv, this );
284+ seqstep.setSelector <mintwo_specialized_selector <charType, CompiledSequence, ExecStep, seqs_dispatcher, decltype(cenv)>> ( &cenv, this );
285285
286286 // After the alternatives have generated we can produce the sequence.
287287 // Thus the sequence is stronger-binding than the alternatives, allowing the alternatives
--- eircompile/include/eircompile/lexing_selectors.h (revision 54)
+++ eircompile/include/eircompile/lexing_selectors.h (revision 55)
@@ -404,20 +404,44 @@
404404 depOptimizedVector <unaOpDisp> postfix_operands_in_order;
405405 };
406406
407-template <typename structType, typename charType, typename nodeType>
407+namespace selector_utils
408+{
409+
410+template <typename methodType, typename charType, typename cNodeType>
411+concept IsAssignAttributeToMethod =
412+ std::is_invocable_r <void, methodType, cNodeType* /* assign_to */, const eir::FixedString <charType>& /* attrib */, const eir::FixedString <charType>& /* value */>::value;
413+
414+template <typename methodType, typename charType, typename cNodeType, typename baseNodeType>
415+concept IsAssignNodeToMethod =
416+ std::is_invocable_r <bool, methodType, cNodeType* /* assign_to */, const eir::FixedString <char>& /* attrib */, baseNodeType* /* node */>::value;
417+
418+} // namespace hidden_selector_utils
419+
420+template <typename structType, typename charType, typename cNodeType>
421+concept LexerStructHasAssignAttributeToMethod =
422+ selector_utils::IsAssignAttributeToMethod <decltype(structType::AssignAttributeTo), charType, cNodeType>;
423+
424+template <typename structType, typename charType, typename cNodeType, typename baseNodeType>
425+concept LexerStructHasAssignNodeToMethod =
426+ selector_utils::IsAssignNodeToMethod <decltype(structType::AssignNodeTo), charType, cNodeType, baseNodeType>;
427+
428+template <typename structType, typename charType, typename nodeType, typename subNodeType = nodeType>
408429 concept MintwoSelectorDispatcher =
409430 eir::constructible_from <structType, const structType&> &&
410431 eir::nothrow_constructible_from <structType, structType&&> &&
411432 std::is_nothrow_destructible <structType>::value &&
412433 LexerCompatibleNode <nodeType, charType> &&
413- std::is_invocable_r <nodeType*, decltype(&structType::CreateNode), structType&, nodeType* /* first_node */>::value;
434+ std::derived_from <subNodeType, nodeType> &&
435+ std::is_invocable_r <nodeType*, decltype(&structType::CreateNode), structType&, nodeType* /* first_node */>::value &&
436+ ( LexerStructHasAssignNode <nodeType, charType, nodeType> || LexerStructHasAssignNodeToMethod <structType, charType, subNodeType, nodeType> );
414437
415438 // Specialized selector that returns a node-concatenation only if at least two
416439 // nodes have been lexed.
417440 template <
418441 typename charType,
442+ typename subNodeType,
419443 LexerCompatibleNode <charType> nodeType,
420- MintwoSelectorDispatcher <charType, nodeType> nodeDisp,
444+ MintwoSelectorDispatcher <charType, nodeType, subNodeType> nodeDisp,
421445 typename lexingEnvType
422446 >
423447 struct mintwo_specialized_selector
@@ -540,7 +564,16 @@
540564 this->has_created_specialization = true;
541565 }
542566
543- return result_node->AssignNode( attrib, node );
567+ if constexpr ( LexerStructHasAssignNode <nodeType, charType, nodeType> )
568+ {
569+ return result_node->AssignNode( attrib, node );
570+ }
571+ else
572+ {
573+ subNodeType *specialized_result_node = (subNodeType*)result_node;
574+
575+ return dispatcher.AssignNodeTo( specialized_result_node, attrib, node );
576+ }
544577 }
545578 }
546579
@@ -556,31 +589,10 @@
556589 // a static dispatcher struct which can then be tailored to specific character encodings.
557590 // Keep the base node types clean, if possible and feasible!
558591
559-namespace selector_utils
560-{
561-
562-template <typename methodType, typename charType, typename cNodeType>
563-concept ObjectBuildingIsAssignAttributeToMethod =
564- std::is_invocable_r <void, methodType, cNodeType* /* assign_to */, const eir::FixedString <charType>& /* attrib */, const eir::FixedString <charType>& /* value */>::value;
565-
566-template <typename methodType, typename charType, typename cNodeType, typename baseNodeType>
567-concept ObjectBuildingIsAssignNodeToMethod =
568- std::is_invocable_r <bool, methodType, cNodeType* /* assign_to */, const eir::FixedString <char>& /* attrib */, baseNodeType* /* node */>::value;
569-
570-} // namespace hidden_selector_utils
571-
572-template <typename structType, typename charType, typename cNodeType>
573-concept LexerStructHasObjectBuildingAssignAttributeToMethod =
574- selector_utils::ObjectBuildingIsAssignAttributeToMethod <decltype(structType::AssignAttributeTo), charType, cNodeType>;
575-
576592 template <typename structType, typename charType, typename cNodeType, typename baseNodeType>
577-concept LexerStructHasObjectBuildingAssignNodeToMethod =
578- selector_utils::ObjectBuildingIsAssignNodeToMethod <decltype(structType::AssignNodeTo), charType, cNodeType, baseNodeType>;
579-
580-template <typename structType, typename charType, typename cNodeType, typename baseNodeType>
581593 concept ObjectBuildingDispatcherMutable =
582- LexerStructHasObjectBuildingAssignAttributeToMethod <structType, charType, cNodeType> ||
583- LexerStructHasObjectBuildingAssignNodeToMethod <structType, charType, cNodeType, baseNodeType>;
594+ LexerStructHasAssignAttributeToMethod <structType, charType, cNodeType> ||
595+ LexerStructHasAssignNodeToMethod <structType, charType, cNodeType, baseNodeType>;
584596
585597 template <typename structType, typename charType, typename cNodeType, typename baseNodeType>
586598 concept ObjectBuildingDispatcher =
@@ -633,7 +645,7 @@
633645
634646 inline void AssignAttribute( const eir::FixedString <charType>& attrib, const eir::FixedString <charType>& value )
635647 {
636- if constexpr ( LexerStructHasObjectBuildingAssignAttributeToMethod <objDispType, charType, cNodeType> )
648+ if constexpr ( LexerStructHasAssignAttributeToMethod <objDispType, charType, cNodeType> )
637649 {
638650 objDispType::AssignAttributeTo( &this->node, attrib, value );
639651 }
@@ -640,7 +652,7 @@
640652 }
641653 inline bool AssignNode( const eir::FixedString <charType>& attrib, baseNodeType *node )
642654 {
643- if constexpr ( LexerStructHasObjectBuildingAssignNodeToMethod <objDispType, charType, cNodeType, baseNodeType> )
655+ if constexpr ( LexerStructHasAssignNodeToMethod <objDispType, charType, cNodeType, baseNodeType> )
644656 {
645657 // We do not have to handle referencing in the node down because if it is reachable through it then
646658 // the GC should keep it alive due to this->node itself being flagged as keep-alive.
--- testcompiler/src/cos_tests.cpp (revision 54)
+++ testcompiler/src/cos_tests.cpp (revision 55)
@@ -24,6 +24,18 @@
2424 // This were a burden because it would require character-based methods that we would not want to lock to character encodings.
2525 };
2626
27+struct Program : public COSNode
28+{
29+ inline Program( depVector <COSNode*> statements = {} ) noexcept : statements( std::move( statements ) )
30+ {
31+ return;
32+ }
33+ inline Program( const Program& ) = default;
34+ inline Program( Program&& ) = default;
35+
36+ depVector <COSNode*> statements;
37+};
38+
2739 struct Operation : public COSNode
2840 {
2941 };
@@ -260,7 +272,7 @@
260272 };
261273 struct ForLoopStatement : public COSNode
262274 {
263- inline ForLoopStatement( Operation *init = nullptr, Operation *condition = nullptr, Operation *iteration = nullptr, COSNode *exec = nullptr ) noexcept : init( init ), condition( condition ), iteration( iteration ), exec( exec )
275+ inline ForLoopStatement( COSNode *init = nullptr, Operation *condition = nullptr, Operation *iteration = nullptr, COSNode *exec = nullptr ) noexcept : init( init ), condition( condition ), iteration( iteration ), exec( exec )
264276 {
265277 return;
266278 }
@@ -278,7 +290,7 @@
278290 right.exec = nullptr;
279291 }
280292
281- Operation *init;
293+ COSNode *init;
282294 Operation *condition;
283295 Operation *iteration;
284296 COSNode *exec;
@@ -334,7 +346,7 @@
334346
335347 struct DeclarationStatement : public COSNode
336348 {
337- inline DeclarationStatement( COSNode *type = nullptr, COSNode *initializer = nullptr ) noexcept : type( type ), initializer( initializer )
349+ inline DeclarationStatement( COSNode *name = nullptr, COSNode *type = nullptr, COSNode *initializer = nullptr ) noexcept : type( type ), initializer( initializer )
338350 {
339351 return;
340352 }
@@ -341,13 +353,16 @@
341353 inline DeclarationStatement( const DeclarationStatement& ) = default;
342354 inline DeclarationStatement( DeclarationStatement&& right ) noexcept
343355 {
356+ this->name = right.name;
344357 this->type = right.type;
345358 this->initializer = right.initializer;
346359
360+ right.name = nullptr;
347361 right.type = nullptr;
348362 right.initializer = nullptr;
349363 }
350364
365+ COSNode *name;
351366 COSNode *type;
352367 COSNode *initializer;
353368 };
@@ -403,38 +418,80 @@
403418
404419 COSNode *op;
405420 };
406-struct TryStatement : public COSNode
421+struct CatchStatement : public COSNode
407422 {
408- struct catch_info
423+ inline CatchStatement( COSNode *caught_decl = nullptr, COSNode *catch_body = nullptr ) noexcept : caught_decl( caught_decl ), catch_body( catch_body )
409424 {
410- COSNode *caught_decl;
411- COSNode *catch_body;
412- };
425+ return;
426+ }
427+ inline CatchStatement( const CatchStatement& ) = default;
428+ inline CatchStatement( CatchStatement&& right ) noexcept
429+ {
430+ this->caught_decl = right.caught_decl;
431+ this->catch_body = right.catch_body;
413432
414- inline TryStatement( COSNode *try_body = nullptr, depVector <catch_info> catch_statements = {} ) noexcept : try_body( try_body ), catch_statements( std::move( catch_statements ) )
433+ right.caught_decl = nullptr;
434+ right.catch_body = nullptr;
435+ }
436+
437+ COSNode *caught_decl;
438+ COSNode *catch_body;
439+};
440+struct TryStatement : public COSNode
441+{
442+ inline TryStatement( COSNode *try_body = nullptr, CatchStatement *error = nullptr ) noexcept : try_body( try_body ), error( error )
415443 {
416444 return;
417445 }
418446 inline TryStatement( const TryStatement& ) = default;
419- inline TryStatement( TryStatement&& right ) noexcept : catch_statements( std::move( right.catch_statements ) )
447+ inline TryStatement( TryStatement&& right ) noexcept
420448 {
421449 this->try_body = right.try_body;
450+ this->error = right.error;
422451
423452 right.try_body = nullptr;
453+ right.error = nullptr;
424454 }
425455
426456 COSNode *try_body;
427-
428- depVector <catch_info> catch_statements;
457+ CatchStatement *error;
429458 };
430459
431460 struct StructStatement : public COSNode
432461 {
462+ inline StructStatement( COSNode *name = nullptr, COSNode *body = nullptr ) noexcept : name( name ), body( body )
463+ {
464+ return;
465+ }
466+ inline StructStatement( const StructStatement& ) = default;
467+ inline StructStatement( StructStatement&& right ) noexcept
468+ {
469+ this->name = right.name;
470+ this->body = right.body;
471+
472+ right.name = nullptr;
473+ right.body = nullptr;
474+ }
475+
476+ COSNode *name;
433477 COSNode *body;
434478 };
435-struct ConstructorStatement : public FunctionDefinition
479+struct ConstructorStatement : public COSNode
436480 {
437- using FunctionDefinition::FunctionDefinition;
481+ inline ConstructorStatement( depVector <COSNode*> params = {}, COSNode *body = nullptr ) noexcept : params( std::move( params ) ), body( body )
482+ {
483+ return;
484+ }
485+ inline ConstructorStatement( const ConstructorStatement& ) = default;
486+ inline ConstructorStatement( ConstructorStatement&& right ) noexcept : params( std::move( right.params ) )
487+ {
488+ this->body = right.body;
489+
490+ right.body = nullptr;
491+ }
492+
493+ depVector <COSNode*> params;
494+ COSNode *body;
438495 };
439496 struct DestructorStatement : public COSNode
440497 {
@@ -476,6 +533,31 @@
476533 depMultiString numeric_string;
477534 };
478535
536+struct CurlyPack : public COSNode
537+{
538+ inline CurlyPack( depVector <COSNode*> params = {} ) noexcept : params( std::move( params ) )
539+ {
540+ return;
541+ }
542+ inline CurlyPack( const CurlyPack& ) = default;
543+ inline CurlyPack( CurlyPack&& ) = default;
544+
545+ depVector <COSNode*> params;
546+};
547+struct ArrayDefinition : public COSNode
548+{
549+ // { i1, ... in }
550+
551+ inline ArrayDefinition( depVector <COSNode*> items = {} ) noexcept : items( std::move( items ) )
552+ {
553+ return;
554+ }
555+ inline ArrayDefinition( const ArrayDefinition& ) = default;
556+ inline ArrayDefinition( ArrayDefinition&& ) = default;
557+
558+ depVector <COSNode*> items;
559+};
560+
479561 }; // namespace COS
480562
481563 static inline bool is_num_nonzero( char c )
@@ -555,15 +637,153 @@
555637
556638 // Generate the COS syntax.
557639 assert( lexer.CompileProduction( compiler, "S", "spaces [<0,e>statement, spaces]" ) == true );
558- assert( lexer.CompileProduction( compiler, "statement", "function | declaration spaces ';' | operation spaces ';' | typedef | block | loop | if | except | objmod" ) == true );
640+ {
641+ struct program_dispatcher
642+ {
643+ inline COSNode* CreateNode( COSNode *first )
644+ {
645+ Program *node = new Program();
646+ node->statements.AddToBack( first );
647+ return node;
648+ }
649+
650+ static inline bool AssignNodeTo( Program *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
651+ {
652+ assign_to->statements.AddToBack( node );
653+ return true;
654+ }
655+ };
656+ lexer.GetNamedProduction( "S" ).setSelector <mintwo_specialized_selector <char, Program, COSNode, program_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
657+ }
658+ assert( lexer.CompileProduction( compiler, "statement", "function | takefirst declaration spaces ';' | takefirst operation spaces ';' | typedef | block | loop | if | except | objmod" ) == true );
559659 assert( lexer.CompileProduction( compiler, "function", "(type:spec spaces)^0:1 (\"func\" | \"operator\") spaces name:spec spaces '(' spaces param:paramlist spaces ')' spaces body:funcbody" ) == true );
660+ {
661+ struct function_dispatcher
662+ {
663+ static inline bool AssignNodeTo( FunctionDefinition *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
664+ {
665+ if ( attrib == "type" )
666+ {
667+ assign_to->return_type = node;
668+ return true;
669+ }
670+ else if ( attrib == "name" )
671+ {
672+ assign_to->name = node;
673+ return true;
674+ }
675+ else if ( attrib == "param" )
676+ {
677+ assign_to->params.AddToBack( node );
678+ return true;
679+ }
680+ else if ( attrib == "body" )
681+ {
682+ assign_to->body = node;
683+ return true;
684+ }
685+ return false;
686+ }
687+ };
688+ lexer.GetNamedProduction( "function" ).setSelector <direct_obj_build_selector <char, FunctionDefinition, COSNode, function_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
689+ }
560690 assert( lexer.CompileProduction( compiler, "paramlist", "[<0>declaration, spaces ',' spaces]" ) == true );
561691 assert( lexer.CompileProduction( compiler, "funcbody", "^!(block, statement+funcstatement)" ) == true );
562- assert( lexer.CompileProduction( compiler, "funcstatement", "st_type:\"return\" spaces op:operation spaces ';'" ) == true );
563- assert( lexer.CompileProduction( compiler, "spec", "npath | '$[' spaces op:operation spaces ']'" ) == true );
564- assert( lexer.CompileProduction( compiler, "declaration", "(type:spec spaces)^0:1 name:spec ( spaces '=' spaces param:operation | spaces '(' spaces [param:operation, spaces ',' spaces] spacecs ')' )^0:1" ) == true );
692+ assert( lexer.CompileProduction( compiler, "funcstatement", "\"return\" spaces (op:operation spaces)^0:1 ';'" ) == true );
693+ {
694+ struct return_dispatcher
695+ {
696+ static inline bool AssignNodeTo( ReturnStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
697+ {
698+ if ( attrib == "op" )
699+ {
700+ assign_to->op = node;
701+ return true;
702+ }
703+ return false;
704+ }
705+ };
706+ lexer.GetNamedProduction( "funcstatement" ).GetLastStep()->setSelector <direct_obj_build_selector <char, ReturnStatement, COSNode, return_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
707+ }
708+ assert( lexer.CompileProduction( compiler, "spec", "npath" ) == true );
709+ assert( lexer.CompileProduction( compiler, "spec", "'$[' spaces op:operation spaces ']'" ) == true );
710+ {
711+ struct dynspec_dispatcher
712+ {
713+ static inline bool AssignNodeTo( ResolveSpecifierOperation *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
714+ {
715+ if ( attrib == "op" )
716+ {
717+ assign_to->op = node;
718+ return true;
719+ }
720+ return false;
721+ }
722+ };
723+ lexer.GetNamedProduction( "spec" ).GetLastStep()->setSelector <direct_obj_build_selector <char, ResolveSpecifierOperation, COSNode, dynspec_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
724+ }
725+ assert( lexer.CompileProduction( compiler, "declaration", "(type:spec spaces)^0:1 name:spec ( spaces '=' spaces init:operation | spaces init:curlypack )^0:1" ) == true );
726+ {
727+ struct declaration_dispatcher
728+ {
729+ static inline bool AssignNodeTo( DeclarationStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
730+ {
731+ if ( attrib == "type" )
732+ {
733+ assign_to->type = node;
734+ return true;
735+ }
736+ else if ( attrib == "name" )
737+ {
738+ assign_to->name = node;
739+ return true;
740+ }
741+ else if ( attrib == "init" )
742+ {
743+ assign_to->initializer = node;
744+ return true;
745+ }
746+ return false;
747+ }
748+ };
749+ }
565750 assert( lexer.CompileProduction( compiler, "dtypedef", "\"typedef\" spaces srctype:spec spaces dsttype:spec spaces ';'" ) == true );
751+ {
752+ struct typedef_dispatcher
753+ {
754+ static inline bool AssignNodeTo( TypedefStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
755+ {
756+ if ( attrib == "srctype" )
757+ {
758+ assign_to->srctype = node;
759+ return true;
760+ }
761+ else if ( attrib == "dsttype" )
762+ {
763+ assign_to->dsttype = node;
764+ return true;
765+ }
766+ return false;
767+ }
768+ };
769+ lexer.GetNamedProduction( "dtypedef" ).setSelector <direct_obj_build_selector <char, TypedefStatement, COSNode, typedef_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
770+ }
566771 assert( lexer.CompileProduction( compiler, "block", "'{' spaces [<0>statement:extended statement, spaces] spaces '}'" ) == true );
772+ {
773+ struct block_dispatcher
774+ {
775+ static inline bool AssignNodeTo( BlockStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
776+ {
777+ if ( attrib == "statement" )
778+ {
779+ assign_to->statements.AddToBack( node );
780+ return true;
781+ }
782+ return false;
783+ }
784+ };
785+ lexer.GetNamedProduction( "block" ).setSelector <direct_obj_build_selector <char, BlockStatement, COSNode, block_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
786+ }
567787
568788 // Create the special "operation" step.
569789 {
@@ -1120,34 +1340,8 @@
11201340
11211341 auto tailop = lexer.MakeStep <decltype(lexer)::RuntimeEnv::StepAlternatives> ();
11221342
1123- assert( lexer.CompileInto( compiler, tailop, "str:name" ) == true );
1124- {
1125- struct name_dispatcher
1126- {
1127- static inline void AssignAttributeTo( SpecifierString *assign_to, const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
1128- {
1129- if ( attrib == "str" )
1130- {
1131- assign_to->string = value;
1132- }
1133- }
1134- };
1135- tailop.GetLastStep()->setSelector <direct_obj_build_selector <char, SpecifierString, COSNode, name_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1136- }
1137- assert( lexer.CompileInto( compiler, tailop, "str:number" ) == true );
1138- {
1139- struct numeric_dispatcher
1140- {
1141- static inline void AssignAttributeTo( NumberString *assign_to, const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
1142- {
1143- if ( attrib == "str" )
1144- {
1145- assign_to->numeric_string = value;
1146- }
1147- }
1148- };
1149- tailop.GetLastStep()->setSelector <direct_obj_build_selector <char, NumberString, COSNode, numeric_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1150- }
1343+ assert( lexer.CompileInto( compiler, tailop, "name" ) == true );
1344+ assert( lexer.CompileInto( compiler, tailop, "number" ) == true );
11511345 assert( lexer.CompileInto( compiler, tailop, "\"new\" spaces type:spec spaces ('(' spaces param:paramlist spaces ')')^0:1" ) == true );
11521346 {
11531347 struct new_dispatcher
@@ -1170,6 +1364,24 @@
11701364 };
11711365 tailop.GetLastStep()->setSelector <direct_obj_build_selector <char, NewOperation, COSNode, new_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
11721366 }
1367+ assert( lexer.CompileInto( compiler, tailop, "'{' spaces [item:procgate operation, spaces ',' spaces] spaces '}'" ) == true );
1368+ {
1369+ struct array_dispatcher
1370+ {
1371+ static inline bool AssignNodeTo( ArrayDefinition *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1372+ {
1373+ if ( attrib == "item" )
1374+ {
1375+ assign_to->items.AddToBack( node );
1376+ return true;
1377+ }
1378+ return false;
1379+ }
1380+ };
1381+ tailop.GetLastStep()->setSelector <direct_obj_build_selector <char, ArrayDefinition, COSNode, array_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1382+ }
1383+ // Not ideal for again serializing into text, but we should be automatically detecting such a case anyway due to a fixed
1384+ // operational binding strength.
11731385 assert( lexer.CompileInto( compiler, tailop, "'(' spaces procgate operation spaces ')'" ) == true );
11741386
11751387 lexer.AddStepInto( operation, std::move( tailop ) );
@@ -1223,6 +1435,21 @@
12231435 return eir::FixedString( startdata, cplen );
12241436 }
12251437 );
1438+ {
1439+ struct name_dispatcher
1440+ {
1441+ static inline void AssignAttributeTo( SpecifierString *assign_to, const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
1442+ {
1443+ if ( attrib == "str" )
1444+ {
1445+ assign_to->string = value;
1446+ }
1447+ }
1448+ };
1449+ auto& nameprod = lexer.GetNamedProduction( "name" );
1450+ nameprod.attribute_key = "str";
1451+ nameprod.setSelector <direct_obj_build_selector <char, SpecifierString, COSNode, name_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1452+ }
12261453 lexer.AddProgrammableTokenStep( "number",
12271454 []( decltype(lexer)::RuntimeEnv::LexingPoint& pt ) -> std::optional <eir::FixedString <char>>
12281455 {
@@ -1264,6 +1491,21 @@
12641491 return eir::FixedString( startdata, cplen );
12651492 }
12661493 );
1494+ {
1495+ struct numeric_dispatcher
1496+ {
1497+ static inline void AssignAttributeTo( NumberString *assign_to, const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
1498+ {
1499+ if ( attrib == "str" )
1500+ {
1501+ assign_to->numeric_string = value;
1502+ }
1503+ }
1504+ };
1505+ auto& numprod = lexer.GetNamedProduction( "number" );
1506+ numprod.attribute_key = "str";
1507+ numprod.setSelector <direct_obj_build_selector <char, NumberString, COSNode, numeric_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1508+ }
12671509 lexer.AddProgrammableTokenStep( "spaces",
12681510 []( decltype(lexer)::RuntimeEnv::LexingPoint& pt )
12691511 {
@@ -1286,62 +1528,292 @@
12861528 }
12871529 );
12881530
1289- assert( lexer.CompileProduction( compiler, "whileloop", "\"while\" spaces '(' spaces operation spaces ')' spaces loopbody" ) == true );
1531+ assert( lexer.CompileProduction( compiler, "whileloop", "\"while\" spaces '(' spaces cond:operation spaces ')' spaces body:loopbody" ) == true );
1532+ {
1533+ struct while_dispatcher
1534+ {
1535+ static inline bool AssignNodeTo( WhileLoopStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1536+ {
1537+ if ( attrib == "cond" )
1538+ {
1539+ assign_to->condition = dynamic_cast <Operation*> ( node );
1540+ }
1541+ else if ( attrib == "body" )
1542+ {
1543+ assign_to->exec = node;
1544+ }
1545+ return false;
1546+ }
1547+ };
1548+ lexer.GetNamedProduction( "whileloop" ).setSelector <direct_obj_build_selector <char, WhileLoopStatement, COSNode, while_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1549+ }
12901550 assert( lexer.CompileProduction( compiler, "loopbody", "^(extended statement, loopstatement)" ) == true );
1291- assert( lexer.CompileProduction( compiler, "loopstatement", "(\"continue\" | \"break\") spaces ';'" ) == true );
1292- assert( lexer.CompileProduction( compiler, "if", "\"if\" spaces '(' spaces operation spaces ')' spaces extended statement" ) == true );
1293- assert( lexer.CompileProduction( compiler, "except", "\"throw\" spaces (operation spaces)^0:1 ';'" ) == true );
1294- assert( lexer.CompileProduction( compiler, "except", "\"try\" spaces extended statement spaces [\"catch\" spaces '(' spaces (declaration spaces)^0:1 ')' spaces extended statement, spaces]" ) == true );
1295- assert( lexer.CompileProduction( compiler, "forloop", "\"for\" spaces '(' spaces (declaration | operation) spaces ';' spaces operation spaces ';' spaces operation spaces ')' spaces loopbody" ) == true );
1551+ assert( lexer.CompileProduction( compiler, "loopstatement", "\"break\" spaces ';'" ) == true );
1552+ {
1553+ lexer.GetNamedProduction( "loopstatement" ).GetLastStep()->setConstructor(
1554+ []
1555+ {
1556+ return new BreakStatement();
1557+ }
1558+ );
1559+ }
1560+ assert( lexer.CompileProduction( compiler, "loopstatement", "\"continue\" spaces ';'" ) == true );
1561+ {
1562+ lexer.GetNamedProduction( "loopstatement" ).GetLastStep()->setConstructor(
1563+ []
1564+ {
1565+ return new ContinueStatement();
1566+ }
1567+ );
1568+ }
1569+ assert( lexer.CompileProduction( compiler, "if", "\"if\" spaces '(' spaces cond:operation spaces ')' spaces true_branch:extended statement (spaces \"else\" spaces false_branch:extended statement)^0:1" ) == true );
1570+ {
1571+ struct if_dispatcher
1572+ {
1573+ static inline bool AssignNodeTo( IfStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1574+ {
1575+ if ( attrib == "cond" )
1576+ {
1577+ assign_to->condition = dynamic_cast <Operation*> ( node );
1578+ return true;
1579+ }
1580+ else if ( attrib == "true_branch" )
1581+ {
1582+ assign_to->true_branch = node;
1583+ return true;
1584+ }
1585+ else if ( attrib == "false_branch" )
1586+ {
1587+ assign_to->false_branch = node;
1588+ return true;
1589+ }
1590+
1591+ return false;
1592+ }
1593+ };
1594+ lexer.GetNamedProduction( "if" ).setSelector <direct_obj_build_selector <char, IfStatement, COSNode, if_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1595+ }
1596+ assert( lexer.CompileProduction( compiler, "except", "\"throw\" spaces (op:operation spaces)^0:1 ';'" ) == true );
1597+ {
1598+ struct throw_dispatcher
1599+ {
1600+ static inline bool AssignNodeTo( ThrowStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1601+ {
1602+ if ( attrib == "op" )
1603+ {
1604+ assign_to->op = node;
1605+ return true;
1606+ }
1607+ return false;
1608+ }
1609+ };
1610+ lexer.GetNamedProduction( "except" ).GetLastStep()->setSelector <direct_obj_build_selector <char, ThrowStatement, COSNode, throw_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1611+ }
1612+ assert( lexer.CompileProduction( compiler, "catch", "\"catch\" spaces '(' spaces (caught_decl:declaration spaces)^0:1 ')' spaces catch_body:extended statement" ) == true );
1613+ {
1614+ struct catch_dispatcher
1615+ {
1616+ static inline bool AssignNodeTo( CatchStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1617+ {
1618+ if ( attrib == "caught_decl" )
1619+ {
1620+ assign_to->caught_decl = node;
1621+ return true;
1622+ }
1623+ else if ( attrib == "catch_body" )
1624+ {
1625+ assign_to->catch_body = node;
1626+ return true;
1627+ }
1628+ return false;
1629+ }
1630+ };
1631+ lexer.GetNamedProduction( "catch" ).setSelector <direct_obj_build_selector <char, CatchStatement, COSNode, catch_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1632+ }
1633+ assert( lexer.CompileProduction( compiler, "except", "\"try\" spaces try_body:extended statement spaces [error:catch, spaces]" ) == true );
1634+ {
1635+ struct try_dispatcher
1636+ {
1637+ static inline bool AssignNodeTo( TryStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1638+ {
1639+ if ( attrib == "try_body" )
1640+ {
1641+ assign_to->try_body = node;
1642+ return true;
1643+ }
1644+ else if ( attrib == "error" )
1645+ {
1646+ assign_to->error = dynamic_cast <CatchStatement*> ( node );
1647+ return true;
1648+ }
1649+ return false;
1650+ }
1651+ };
1652+ lexer.GetNamedProduction( "except" ).GetLastStep()->setSelector <direct_obj_build_selector <char, TryStatement, COSNode, try_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1653+ }
1654+ assert( lexer.CompileProduction( compiler, "forloop", "\"for\" spaces '(' spaces loop_init:(declaration | operation) spaces ';' spaces loop_cond:operation spaces ';' spaces loop_iteration:operation spaces ')' spaces body:loopbody" ) == true );
1655+ {
1656+ struct for_dispatcher
1657+ {
1658+ static inline bool AssignNodeTo( ForLoopStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1659+ {
1660+ if ( attrib == "loop_init" )
1661+ {
1662+ assign_to->init = node;
1663+ return true;
1664+ }
1665+ else if ( attrib == "loop_cond" )
1666+ {
1667+ assign_to->condition = dynamic_cast <Operation*> ( node );
1668+ return true;
1669+ }
1670+ else if ( attrib == "loop_iteration" )
1671+ {
1672+ assign_to->iteration = dynamic_cast <Operation*> ( node );
1673+ return true;
1674+ }
1675+ else if ( attrib == "body" )
1676+ {
1677+ assign_to->exec = node;
1678+ return true;
1679+ }
1680+ return false;
1681+ }
1682+ };
1683+ lexer.GetNamedProduction( "forloop" ).setSelector <direct_obj_build_selector <char, ForLoopStatement, COSNode, for_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1684+ }
12961685 assert( lexer.CompileProduction( compiler, "loop", "whileloop | forloop" ) == true );
12971686 assert( lexer.CompileProduction( compiler, "structdef", "\"struct\" spaces name:spec spaces ^!(body:block, statement+typestatement) spaces ';'" ) == true );
1687+ {
1688+ struct struct_dispatcher
1689+ {
1690+ static inline bool AssignNodeTo( StructStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1691+ {
1692+ if ( attrib == "name" )
1693+ {
1694+ assign_to->name = node;
1695+ return true;
1696+ }
1697+ else if ( attrib == "body" )
1698+ {
1699+ assign_to->body = node;
1700+ return true;
1701+ }
1702+ return false;
1703+ }
1704+ };
1705+ lexer.GetNamedProduction( "structdef" ).setSelector <direct_obj_build_selector <char, StructStatement, COSNode, struct_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1706+ }
12981707 assert( lexer.CompileProduction( compiler, "typedef", "dtypedef | structdef" ) == true );
12991708 assert( lexer.CompileProduction( compiler, "typestatement", "constructor | destructor" ) == true );
13001709 assert( lexer.CompileProduction( compiler, "constructor", "\"constructor\" spaces '(' spaces param:paramlist spaces ')' spaces body:extended funcbody" ) == true );
1710+ {
1711+ struct constructor_dispatcher
1712+ {
1713+ static inline bool AssignNodeTo( ConstructorStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1714+ {
1715+ if ( attrib == "param" )
1716+ {
1717+ assign_to->params.AddToBack( node );
1718+ return true;
1719+ }
1720+ else if ( attrib == "body" )
1721+ {
1722+ assign_to->body = node;
1723+ return true;
1724+ }
1725+ return false;
1726+ }
1727+ };
1728+ lexer.GetNamedProduction( "constructor" ).setSelector <direct_obj_build_selector <char, ConstructorStatement, COSNode, constructor_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1729+ }
13011730 assert( lexer.CompileProduction( compiler, "destructor", "\"destructor\" spaces body:extended funcbody" ) == true );
1731+ {
1732+ struct destructor_dispatcher
1733+ {
1734+ static inline bool AssignNodeTo( DestructorStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1735+ {
1736+ if ( attrib == "body" )
1737+ {
1738+ assign_to->body = node;
1739+ return true;
1740+ }
1741+ return false;
1742+ }
1743+ };
1744+ lexer.GetNamedProduction( "destructor" ).setSelector <direct_obj_build_selector <char, DestructorStatement, COSNode, destructor_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1745+ }
13021746 assert( lexer.CompileProduction( compiler, "deleteop", "\"delete\" spaces op:operation spaces ';'" ) == true );
1747+ {
1748+ struct delete_dispatcher
1749+ {
1750+ static inline bool AssignNodeTo( DeleteOperation *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1751+ {
1752+ if ( attrib == "op" )
1753+ {
1754+ assign_to->op = node;
1755+ return true;
1756+ }
1757+ return false;
1758+ }
1759+ };
1760+ lexer.GetNamedProduction( "deleteop" ).setSelector <direct_obj_build_selector <char, DeleteOperation, COSNode, delete_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1761+ }
13031762 assert( lexer.CompileProduction( compiler, "replaceop", "\"replace\" spaces what:operation spaces \"with\" spaces with:operation spaces ';'" ) == true );
1763+ {
1764+ struct replace_dispatcher
1765+ {
1766+ static inline bool AssignNodeTo( ReplaceOperation *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1767+ {
1768+ if ( attrib == "what" )
1769+ {
1770+ assign_to->what = node;
1771+ return true;
1772+ }
1773+ else if ( attrib == "with" )
1774+ {
1775+ assign_to->with = node;
1776+ return true;
1777+ }
1778+ return false;
1779+ }
1780+ };
1781+ lexer.GetNamedProduction( "replaceop" ).setSelector <direct_obj_build_selector <char, ReplaceOperation, COSNode, replace_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1782+ }
13041783 assert( lexer.CompileProduction( compiler, "objmod", "deleteop | replaceop" ) == true );
13051784 assert( lexer.CompileProduction( compiler, "npath", "[op:name, spaces optype:'.' spaces]" ) == true );
1306-
1307- // Specify the object representation of the syntax above.
1308- struct function_selector
13091785 {
1310- inline COSNode* DetachFinishedNode( void )
1786+ struct npath_dispatcher
13111787 {
1312- return new FunctionDefinition( std::move( this->func ) );
1313- }
1314-
1315- inline bool AssignNode( const eir::FixedString <char>& attrib, COSNode *node )
1316- {
1317- if ( attrib == "type" )
1788+ inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
13181789 {
1319- func.return_type = node;
1320- return true;
1790+ return;
13211791 }
1322- else if ( attrib == "name" )
1792+
1793+ inline COSNode* CreateOperation( COSNode *left, COSNode *right )
13231794 {
1324- func.name = node;
1325- return true;
1795+ return new DotOperation( left, right );
13261796 }
1327- else if ( attrib == "param" )
1797+ };
1798+ lexer.GetNamedProduction( "npath" ).setSelector <left_associative_selector <char, COSNode, npath_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1799+ }
1800+ assert( lexer.CompileProduction( compiler, "curlypack", "'(' spaces [param:operation, spaces ',' spaces] spacecs ')'" ) == true );
1801+ {
1802+ struct curlypack_dispatcher
1803+ {
1804+ static inline bool AssignNodeTo( CurlyPack *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
13281805 {
1329- func.params.AddToBack( node );
1330- return true;
1806+ if ( attrib == "param" )
1807+ {
1808+ assign_to->params.AddToBack( node );
1809+ return true;
1810+ }
1811+ return false;
13311812 }
1332- else if ( attrib == "body" )
1333- {
1334- func.body = node;
1335- return true;
1336- }
1813+ };
1814+ lexer.GetNamedProduction( "curlypack" ).setSelector <direct_obj_build_selector <char, CurlyPack, COSNode, curlypack_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1815+ }
13371816
1338- return false;
1339- }
1340-
1341- FunctionDefinition func;
1342- };
1343- lexer.GetNamedProduction( "function" ).setSelector <function_selector> ();
1344-
13451817 printf( "testing COS operations..." );
13461818 {
13471819 assert( lexer.TestProduction( "1 + 1;" ) == true );
--- testcompiler/src/lexingenv_tests.cpp (revision 54)
+++ testcompiler/src/lexingenv_tests.cpp (revision 55)
@@ -5638,7 +5638,7 @@
56385638 seplist.SetSeparationStep( &toksep );
56395639 seplist.min_item_cnt = 1;
56405640 seplist.is_alternation = false;
5641- seplist.setSelector <mintwo_specialized_selector <char, Node, list_dispatcher, decltype(env)>> ( &env );
5641+ seplist.setSelector <mintwo_specialized_selector <char, List, Node, list_dispatcher, decltype(env)>> ( &env );
56425642
56435643 decltype(env)::StepToken tok_ilist_beg( &env );
56445644 tok_ilist_beg.token_str = "(";
Show on old repository browser