• R/O
  • SSH
  • HTTPS

eircompile: Commit


Commit MetaInfo

Revision65 (tree)
Time2021-12-24 03:33:53
Authorquiret

Log Message

- fixed a bug in the Eir lexer where certain attribute-prefixes of calculation paths were destroyed without restoration + added unit test to cement the bugfix
- fleshed out COS some more

Change Summary

Incremental Difference

--- eircompile/include/eircompile/lexing_env.h (revision 64)
+++ eircompile/include/eircompile/lexing_env.h (revision 65)
@@ -3315,17 +3315,15 @@
33153315 }
33163316
33173317 // After incrementing we just restore the state that is supposed to exist.
3318- iter->attrib_prefix = std::move( prev_iter->attrib_prefix );
3318+ if ( this->is_top_most_attrib_sequence == false )
3319+ {
3320+ calc_stack_top.unprependAttributeForDevolution( prev_iter->current_step->attribute_key.ToFixed() );
3321+ }
33193322
33203323 if ( this->is_top_most_attrib_sequence == false && this->break_pt_iter == prev_iter )
33213324 {
33223325 this->is_top_most_attrib_sequence = true;
33233326 }
3324-
3325- if ( this->is_top_most_attrib_sequence == false )
3326- {
3327- iter->unprependAttributeForDevolution( prev_iter->current_step->attribute_key.ToFixed() );
3328- }
33293327 }
33303328 }
33313329
@@ -3364,11 +3362,9 @@
33643362 }
33653363
33663364 // Devolve the path logic in the way down we go.
3367- next_iter->attrib_prefix = std::move( prev_iter->attrib_prefix );
3368-
33693365 if ( this->is_top_most_attrib_sequence == false )
33703366 {
3371- next_iter->prependAttributeForDevolution( prev_iter->current_step->attribute_key.ToFixed() );
3367+ calc_stack_top.prependAttributeForDevolution( next_iter->current_step->attribute_key.ToFixed() );
33723368 }
33733369
33743370 // If we are to take the result from the above entry anyway, then we can skip the entry that will be the one that
@@ -3382,6 +3378,9 @@
33823378
33833379 if ( this->is_top_most_attrib_sequence )
33843380 {
3381+ // Just like above.
3382+ calc_stack_top.prependAttributeForDevolution( next_iter->current_step->attribute_key.ToFixed() );
3383+
33853384 // We are past the top-most which was already built anyway.
33863385 this->is_top_most_attrib_sequence = false;
33873386
@@ -3397,6 +3396,11 @@
33973396 return ( this->iter == nullptr );
33983397 }
33993398
3399+ inline const auto& GetAttributePrefix( void ) const
3400+ {
3401+ return calc_stack_top.attrib_prefix;
3402+ }
3403+
34003404 private:
34013405 eir::Vector <CalcPathEntry, EnvironmentAllocator>& calc_stack_notop;
34023406 CalcPathEntry& calc_stack_top;
@@ -4298,7 +4302,7 @@
42984302 // Make sure we initialize to this point.
42994303 calcstack_init_to_entry( maybe_entry );
43004304
4301- auto& attrib_name = maybe_entry.attrib_prefix;
4305+ const auto& attrib_name = dev_iter.GetAttributePrefix();
43024306
43034307 maybe_entry.AssignAttribute( attrib_name.ToFixed(), tkstep->token_str.ToFixed() );
43044308 }
@@ -4367,7 +4371,7 @@
43674371 // Make sure we initialize to this point.
43684372 calcstack_init_to_entry( maybe_entry );
43694373
4370- auto& attrib_name = maybe_entry.attrib_prefix;
4374+ auto& attrib_name = dev_iter.GetAttributePrefix();
43714375
43724376 maybe_entry.AssignAttribute( attrib_name.ToFixed(), restok.ToFixed() );
43734377 }
@@ -4688,9 +4692,15 @@
46884692 {
46894693 Step *next_step = indirstep->callback( *this );
46904694
4691- if ( next_step == nullptr || push_onto_execution( next_step ) == false )
4695+ // We treat ourselves as empty.
4696+ if ( next_step == nullptr )
46924697 {
46934698 has_op_finished = true;
4699+ is_op_successful = true;
4700+ }
4701+ else if ( push_onto_execution( next_step ) == false )
4702+ {
4703+ has_op_finished = true;
46944704 is_op_successful = false;
46954705 }
46964706 }
@@ -5049,7 +5059,7 @@
50495059
50505060 try
50515061 {
5052- auto& attrib_name = assign_node_entry.attrib_prefix;
5062+ const auto& attrib_name = dev_iter.GetAttributePrefix();
50535063
50545064 bool couldAssign;
50555065
@@ -5412,6 +5422,11 @@
54125422 {
54135423 CalcPathEntry& ent = GetCurrentExecutionCalcPathEntryByIndex( cstack_idx );
54145424
5425+ if ( std::holds_alternative <cNodeType*> ( ent.pcalc ) == false )
5426+ {
5427+ return nullptr;
5428+ }
5429+
54155430 return std::get <cNodeType*> ( ent.pcalc );
54165431 }
54175432
--- testcompiler/src/cos_tests.cpp (revision 64)
+++ testcompiler/src/cos_tests.cpp (revision 65)
@@ -193,6 +193,51 @@
193193 using BinaryOperation::BinaryOperation;
194194 };
195195
196+struct AssignAddOperation : public BinaryOperation
197+{
198+ using BinaryOperation::BinaryOperation;
199+};
200+struct AssignSubOperation : public BinaryOperation
201+{
202+ using BinaryOperation::BinaryOperation;
203+};
204+struct AssignMulOperation : public BinaryOperation
205+{
206+ using BinaryOperation::BinaryOperation;
207+};
208+struct AssignDivOperation : public BinaryOperation
209+{
210+ using BinaryOperation::BinaryOperation;
211+};
212+struct AssignModulusOperation : public BinaryOperation
213+{
214+ using BinaryOperation::BinaryOperation;
215+};
216+struct AssignBitwiseXorOperation : public BinaryOperation
217+{
218+ using BinaryOperation::BinaryOperation;
219+};
220+struct AssignBitwiseAndOperation : public BinaryOperation
221+{
222+ using BinaryOperation::BinaryOperation;
223+};
224+struct AssignBitwiseOrOperation : public BinaryOperation
225+{
226+ using BinaryOperation::BinaryOperation;
227+};
228+struct AssignDotOperation : public BinaryOperation
229+{
230+ using BinaryOperation::BinaryOperation;
231+};
232+struct AssignBitshiftLeftOperation : public BinaryOperation
233+{
234+ using BinaryOperation::BinaryOperation;
235+};
236+struct AssignBitshiftRightOperation : public BinaryOperation
237+{
238+ using BinaryOperation::BinaryOperation;
239+};
240+
196241 struct FunctionCallOperation : public Operation
197242 {
198243 inline FunctionCallOperation( COSNode *what = nullptr, depVector <COSNode*> params = {} ) noexcept : what( what ), params( std::move( params ) )
@@ -626,6 +671,8 @@
626671 ASSIGN_BIT_AND,
627672 ASSIGN_BIT_OR,
628673 ASSIGN_DOT,
674+ ASSIGN_BITSHIFT_LEFT,
675+ ASSIGN_BITSHIFT_RIGHT,
629676
630677 COMPARE_EQUALITY,
631678 COMPARE_GREATER_THAN,
@@ -850,8 +897,8 @@
850897 };
851898 lexer.GetNamedProduction( "S" ).setSelector <mintwo_specialized_selector <char, Program, COSNode, program_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
852899 }
853- assert( lexer.CompileProduction( compiler, "statement", "typedef | block | loop | if | except | objmod | takefirst multdecl spaces ';' | takefirst operation spaces ';'" ) == true );
854- assert( lexer.CompileProduction( compiler, "funcbody", "^!(block, <b> statement+funcstatement)" ) == true );
900+ assert( lexer.CompileProduction( compiler, "statement", "typedef | block | loop | if | except | objmod | multdecl | takefirst operation spaces ';'" ) == true );
901+ assert( lexer.CompileProduction( compiler, "funcbody", "^(statement, <b> funcstatement)" ) == true );
855902 assert( lexer.CompileProduction( compiler, "funcstatement", "\"return\" spaces (op:operation spaces)^0:1 ';'" ) == true );
856903 {
857904 struct return_dispatcher
@@ -868,26 +915,9 @@
868915 };
869916 lexer.GetNamedProduction( "funcstatement" ).GetLastStep()->setSelector <direct_obj_build_selector <char, ReturnStatement, COSNode, return_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
870917 }
871- assert( lexer.CompileProduction( compiler, "spec", "npath" ) == true );
872- assert( lexer.CompileProduction( compiler, "spec", "'$[' spaces op:operation spaces ']'" ) == true );
873- {
874- struct dynspec_dispatcher
875- {
876- static inline bool AssignNodeTo( ResolveSpecifierOperation *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
877- {
878- if ( attrib == "op" )
879- {
880- assign_to->op = node;
881- return true;
882- }
883- return false;
884- }
885- };
886- lexer.GetNamedProduction( "spec" ).GetLastStep()->setSelector <direct_obj_build_selector <char, ResolveSpecifierOperation, COSNode, dynspec_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
887- }
888- assert( lexer.CompileProduction( compiler, "optoksingle_epostfix", "'+-*/%^&|!.=<>'" ) == true );
918+ assert( lexer.CompileProduction( compiler, "optoksingle_epostfix", "\"<<\" | \">>\" | '+-*/%^&|!.=<>'" ) == true );
889919 assert( lexer.CompileProduction( compiler, "optoksingle", "'~' | optoksingle_epostfix" ) == true );
890- assert( lexer.CompileProduction( compiler, "optoks", "\"&&\" | \"||\" | \"<<\" | \">>\" | optoksingle_epostfix '=' | optoksingle" ) == true );
920+ assert( lexer.CompileProduction( compiler, "optoks", "\"&&\" | \"||\" | optoksingle_epostfix '=' | optoksingle" ) == true );
891921 assert( lexer.CompileProduction( compiler, "spec", "\"operator\" spaces optok:optoks" ) == true );
892922 {
893923 struct specifier_op_dispatcher
@@ -1019,14 +1049,39 @@
10191049 {
10201050 assign_to->op_type = eOpType::BITSHIFT_LEFT;
10211051 }
1052+ else if ( value == "<<=" )
1053+ {
1054+ assign_to->op_type = eOpType::ASSIGN_BITSHIFT_LEFT;
1055+ }
10221056 else if ( value == ">>" )
10231057 {
10241058 assign_to->op_type = eOpType::BITSHIFT_RIGHT;
10251059 }
1060+ else if ( value == ">>=" )
1061+ {
1062+ assign_to->op_type = eOpType::ASSIGN_BITSHIFT_RIGHT;
1063+ }
10261064 }
10271065 };
10281066 lexer.GetNamedProduction( "spec" ).GetLastStep()->setSelector <direct_obj_build_selector <char, SpecifierOperator, COSNode, specifier_op_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
10291067 }
1068+ assert( lexer.CompileProduction( compiler, "spec", "npath" ) == true );
1069+ assert( lexer.CompileProduction( compiler, "spec", "\"$[\" spaces op:operation spaces ']'" ) == true );
1070+ {
1071+ struct dynspec_dispatcher
1072+ {
1073+ static inline bool AssignNodeTo( ResolveSpecifierOperation *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1074+ {
1075+ if ( attrib == "op" )
1076+ {
1077+ assign_to->op = node;
1078+ return true;
1079+ }
1080+ return false;
1081+ }
1082+ };
1083+ lexer.GetNamedProduction( "spec" ).GetLastStep()->setSelector <direct_obj_build_selector <char, ResolveSpecifierOperation, COSNode, dynspec_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1084+ }
10301085 assert( lexer.CompileProduction( compiler, "dtypedef", "\"typedef\" spaces tmultdecl spaces ';'" ) == true );
10311086 assert( lexer.CompileProduction( compiler, "block", "'{' spaces [<0>statement:extended statement, spaces] spaces '}'" ) == true );
10321087 {
@@ -1049,25 +1104,145 @@
10491104 {
10501105 auto operation = lexer.MakeStep <decltype(lexer)::RuntimeEnv::StepProceduralSequence> ();
10511106
1052- assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:'=' spaces]" ) != nullptr );
1107+ assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:('=' | \"+=\" | \"-=\" | \"*=\" | \"/=\" | \"%=\" | \"^=\" | \"&=\" | \"|=\" | \".=\") spaces]" ) != nullptr );
10531108 {
10541109 struct assignment_dispatcher
10551110 {
1111+ enum class eOpType
1112+ {
1113+ UNSPECIFIED,
1114+ ASSIGN,
1115+ ASSIGN_ADD,
1116+ ASSIGN_SUB,
1117+ ASSIGN_MUL,
1118+ ASSIGN_DIV,
1119+ ASSIGN_MODULUS,
1120+ ASSIGN_BIT_XOR,
1121+ ASSIGN_BIT_AND,
1122+ ASSIGN_BIT_OR,
1123+ ASSIGN_DOT,
1124+ ASSIGN_BITSHIFT_LEFT,
1125+ ASSIGN_BITSHIFT_RIGHT
1126+ };
1127+
10561128 inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
10571129 {
1058- return;
1130+ if ( attrib != "optype" )
1131+ return;
1132+
1133+ if ( value == "=" )
1134+ {
1135+ this->op_type = eOpType::ASSIGN;
1136+ }
1137+ else if ( value == "+=" )
1138+ {
1139+ this->op_type = eOpType::ASSIGN_ADD;
1140+ }
1141+ else if ( value == "-=" )
1142+ {
1143+ this->op_type = eOpType::ASSIGN_SUB;
1144+ }
1145+ else if ( value == "*=" )
1146+ {
1147+ this->op_type = eOpType::ASSIGN_MUL;
1148+ }
1149+ else if ( value == "/=" )
1150+ {
1151+ this->op_type = eOpType::ASSIGN_DIV;
1152+ }
1153+ else if ( value == "%=" )
1154+ {
1155+ this->op_type = eOpType::ASSIGN_MODULUS;
1156+ }
1157+ else if ( value == "^=" )
1158+ {
1159+ this->op_type = eOpType::ASSIGN_BIT_XOR;
1160+ }
1161+ else if ( value == "&=" )
1162+ {
1163+ this->op_type = eOpType::ASSIGN_BIT_AND;
1164+ }
1165+ else if ( value == "|=" )
1166+ {
1167+ this->op_type = eOpType::ASSIGN_BIT_OR;
1168+ }
1169+ else if ( value == ".=" )
1170+ {
1171+ this->op_type = eOpType::ASSIGN_DOT;
1172+ }
1173+ else if ( value == "<<=" )
1174+ {
1175+ this->op_type = eOpType::ASSIGN_BITSHIFT_LEFT;
1176+ }
1177+ else if ( value == ">>=" )
1178+ {
1179+ this->op_type = eOpType::ASSIGN_BITSHIFT_RIGHT;
1180+ }
10591181 }
10601182
10611183 inline COSNode* CreateOperation( COSNode *left, COSNode *right ) const
10621184 {
1063- return new AssignmentOperation( left, right );
1185+ eOpType op_type = this->op_type;
1186+
1187+ if ( op_type == eOpType::ASSIGN )
1188+ {
1189+ return new AssignmentOperation( left, right );
1190+ }
1191+ else if ( op_type == eOpType::ASSIGN_ADD )
1192+ {
1193+ return new AssignAddOperation( left, right );
1194+ }
1195+ else if ( op_type == eOpType::ASSIGN_SUB )
1196+ {
1197+ return new AssignSubOperation( left, right );
1198+ }
1199+ else if ( op_type == eOpType::ASSIGN_MUL )
1200+ {
1201+ return new AssignMulOperation( left, right );
1202+ }
1203+ else if ( op_type == eOpType::ASSIGN_DIV )
1204+ {
1205+ return new AssignDivOperation( left, right );
1206+ }
1207+ else if ( op_type == eOpType::ASSIGN_MODULUS )
1208+ {
1209+ return new AssignModulusOperation( left, right );
1210+ }
1211+ else if ( op_type == eOpType::ASSIGN_BIT_XOR )
1212+ {
1213+ return new AssignBitwiseXorOperation( left, right );
1214+ }
1215+ else if ( op_type == eOpType::ASSIGN_BIT_AND )
1216+ {
1217+ return new AssignBitwiseAndOperation( left, right );
1218+ }
1219+ else if ( op_type == eOpType::ASSIGN_BIT_OR )
1220+ {
1221+ return new AssignBitwiseOrOperation( left, right );
1222+ }
1223+ else if ( op_type == eOpType::ASSIGN_DOT )
1224+ {
1225+ return new AssignDotOperation( left, right );
1226+ }
1227+ else if ( op_type == eOpType::ASSIGN_BITSHIFT_LEFT )
1228+ {
1229+ return new AssignBitshiftLeftOperation( left, right );
1230+ }
1231+ else if ( op_type == eOpType::ASSIGN_BITSHIFT_RIGHT )
1232+ {
1233+ return new AssignBitshiftRightOperation( left, right );
1234+ }
1235+
1236+ throw lexing_invalid_parameter_exception();
10641237 }
1238+
1239+ eOpType op_type = eOpType::UNSPECIFIED;
10651240 };
10661241 operation.GetLastStep()->setSelector <right_associative_selector <char, COSNode, assignment_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
10671242 }
1068- assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:'|' spaces]" ) != nullptr );
1243+ assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:\"||\" spaces]" ) != nullptr );
10691244 {
1070- struct bor_dispatcher
1245+ struct logical_or_dispatcher
10711246 {
10721247 inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
10731248 {
@@ -1076,14 +1251,14 @@
10761251
10771252 inline COSNode* CreateOperation( COSNode *left, COSNode *right )
10781253 {
1079- return new BitwiseOrOperation( left, right );
1254+ return new LogicalOrOperation( left, right );
10801255 }
10811256 };
1082- operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, bor_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1257+ operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, logical_or_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
10831258 }
1084- assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:'^' spaces]" ) != nullptr );
1259+ assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:\"&&\" spaces]" ) != nullptr );
10851260 {
1086- struct bxor_dispatcher
1261+ struct logical_and_dispatcher
10871262 {
10881263 inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
10891264 {
@@ -1092,14 +1267,14 @@
10921267
10931268 inline COSNode* CreateOperation( COSNode *left, COSNode *right )
10941269 {
1095- return new BitwiseXorOperation( left, right );
1270+ return new LogicalAndOperation( left, right );
10961271 }
10971272 };
1098- operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, bxor_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1273+ operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, logical_and_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
10991274 }
1100- assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:'&' spaces]" ) != nullptr );
1275+ assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:'|' spaces]" ) != nullptr );
11011276 {
1102- struct band_dispatcher
1277+ struct bor_dispatcher
11031278 {
11041279 inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
11051280 {
@@ -1108,14 +1283,14 @@
11081283
11091284 inline COSNode* CreateOperation( COSNode *left, COSNode *right )
11101285 {
1111- return new BitwiseAndOperation( left, right );
1286+ return new BitwiseOrOperation( left, right );
11121287 }
11131288 };
1114- operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, band_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1289+ operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, bor_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
11151290 }
1116- assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:\"||\" spaces]" ) != nullptr );
1291+ assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:'^' spaces]" ) != nullptr );
11171292 {
1118- struct logical_or_dispatcher
1293+ struct bxor_dispatcher
11191294 {
11201295 inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
11211296 {
@@ -1124,26 +1299,33 @@
11241299
11251300 inline COSNode* CreateOperation( COSNode *left, COSNode *right )
11261301 {
1127- return new LogicalOrOperation( left, right );
1302+ return new BitwiseXorOperation( left, right );
11281303 }
11291304 };
1130- operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, logical_or_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1305+ operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, bxor_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
11311306 }
1132- assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:\"&&\" spaces]" ) != nullptr );
1307+ assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:('&'^1:2) spaces]" ) != nullptr );
11331308 {
1134- struct logical_and_dispatcher
1309+ struct band_dispatcher
11351310 {
11361311 inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
11371312 {
1138- return;
1313+ if ( attrib == "optype" )
1314+ {
1315+ if ( value == "&&" )
1316+ {
1317+ // This is important because a double-ampersand can never be a bitwise-and.
1318+ throw lexing_invalid_parameter_exception();
1319+ }
1320+ }
11391321 }
11401322
11411323 inline COSNode* CreateOperation( COSNode *left, COSNode *right )
11421324 {
1143- return new LogicalAndOperation( left, right );
1325+ return new BitwiseAndOperation( left, right );
11441326 }
11451327 };
1146- operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, logical_and_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1328+ operation.GetLastStep()->setSelector <left_associative_selector <char, COSNode, band_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
11471329 }
11481330 assert( lexer.CompileInto( compiler, operation, "[opitem:operation, spaces optype:(\"==\" | \"!=\" | \"<=\" | \">=\" | '<' | '>') spaces]" ) != nullptr );
11491331 {
@@ -2436,8 +2618,7 @@
24362618 };
24372619 lexer.GetNamedProduction( "tmultdecl" ).setSelector <tmultdecl_selector> ();
24382620 }
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 );
2621+ assert( lexer.CompileProduction( compiler, "funcsigtempl", "functag spaces ( '(' spaces locator spaces (subfunc:funcsigtempl|locnametempl) spaces ')' | name:replaceable nameplacehold ) spaces '(' spaces paramlist_opt spaces ')'" ) == true );
24412622 {
24422623 struct funcsig_selector
24432624 {
@@ -2495,8 +2676,9 @@
24952676 FuncsigDefinition funcsig;
24962677 FuncsigDefinition *subfunc = nullptr;
24972678 };
2498- lexer.GetNamedProduction( "funcsigdecl" ).setSelector <funcsig_selector> ();
2679+ lexer.GetNamedProduction( "funcsigtempl" ).setSelector <funcsig_selector> ();
24992680 }
2681+ assert( lexer.CompileProduction( compiler, "funcsigdecl", "&(funcsigtempl, nameplacehold=spec)" ) == true );
25002682 assert( lexer.CompileProduction( compiler, "locnametempl", "name:replaceable nameplacehold (spaces [arrspec:arrayspec, spaces])^0:1" ) == true ); // helper
25012683 assert( lexer.CompileProduction( compiler, "locatedname", "&(locnametempl, nameplacehold=spec)" ) == true );
25022684 assert( lexer.CompileProduction( compiler, "arrayspec", "'[' spaces (idx:operation spaces)^0:1 endtok:']'" ) == true ); // helper
@@ -2505,7 +2687,7 @@
25052687 assert( lexer.CompileProduction( compiler, "declaration", "&(decltemplate, nameplacehold=spec, initplacehold=declinit)" ) == true );
25062688 assert( lexer.CompileProduction( compiler, "decl_optnoinit", "&(decltemplate, nameplacehold=(spec)^0:1, initplacehold=empty)" ) == true );
25072689 assert( lexer.CompileProduction( compiler, "decl_opt", "&(decltemplate, nameplacehold=(spec)^0:1, initplacehold=declinit)" ) == true );
2508- assert( lexer.CompileProduction( compiler, "multdecl", "utype:spec spaces [locator spaces (func:funcsigdecl|locatedname) declinit, spaces nextdecl:',' spaces]" ) == true );
2690+ assert( lexer.CompileProduction( compiler, "multdecl", "utype:spec spaces [locator spaces (func:funcsigdecl|locatedname) declinit, spaces nextdecl:',' spaces] mdeclterm" ) == true );
25092691 {
25102692 struct declaration_selector
25112693 {
@@ -2531,6 +2713,12 @@
25312713 this->decl.initializer = node;
25322714 return true;
25332715 }
2716+ else if ( attrib == "init_s" )
2717+ {
2718+ this->decl.initializer = node;
2719+ this->special_init = true;
2720+ return true;
2721+ }
25342722 else if ( LexingEnvUtils::GetLastAttributionItemInPathFixed( attrib ) == "name" )
25352723 {
25362724 this->decl.name = node;
@@ -2594,6 +2782,7 @@
25942782 FuncsigDefinition *func = nullptr;
25952783 declaratory_locator_builder locbuild;
25962784 DeclarationStatement decl;
2785+ bool special_init = false;
25972786 COSNode *built_type = nullptr;
25982787 };
25992788 lexer.GetNamedProduction( "declaration" ).setSelector <declaration_selector> ();
@@ -2650,10 +2839,10 @@
26502839 auto special_declinit = lexer.MakeStep <decltype(lexer)::RuntimeEnv::StepCustomIndirection> ();
26512840
26522841 // INDEX 0: array enclosure.
2653- auto *step_arrenclose = lexer.CompileInto( special_declinit, "'{' spaces ([initexpr, spaces ',' spaces] spaces)^0:1 '}'" );
2842+ auto *step_arrenclose = lexer.CompileInto( compiler, special_declinit, "'{' spaces ([initexpr, spaces ',' spaces] spaces)^0:1 '}'" );
26542843
26552844 // INDEX 1: outer value.
2656- auto *step_outerval = lexer.CompileInto( special_declinit, "'{' spaces operation spaces '}'" );
2845+ auto *step_outerval = lexer.CompileInto( compiler, special_declinit, "'{' spaces operation spaces '}'" );
26572846
26582847 // We also need the following productions which are already defined:
26592848 // * operation
@@ -2762,9 +2951,51 @@
27622951 };
27632952
27642953 lexer.AddStep( "initexpr", std::move( special_declinit ) );
2954+
2955+ // Implement the terminator after the multi-declaration.
2956+ auto mdeclterm = lexer.MakeStep <decltype(lexer)::RuntimeEnv::StepCustomIndirection> ();
2957+
2958+ auto *step_spaceterm = lexer.CompileInto( compiler, mdeclterm, "spaces ';'" );
2959+
2960+ mdeclterm.callback = [&]( decltype(lexer)::RuntimeEnv::ProductionMachine& machine ) -> decltype(lexer)::RuntimeEnv::Step*
2961+ {
2962+ auto& step_multdecl = lexer.GetNamedProduction( "multdecl" );
2963+
2964+ size_t cstack_size = machine.GetCurrentCalcStackSize() - 2;
2965+
2966+ multdecl_selector *mdecl_sel = nullptr;
2967+
2968+ while ( cstack_size > 0 )
2969+ {
2970+ cstack_size--;
2971+
2972+ auto *cstep = machine.GetCurrentExecutionStepByIndex( cstack_size );
2973+
2974+ if ( cstep == &step_multdecl )
2975+ {
2976+ mdecl_sel = (multdecl_selector*)machine.GetCurrentExecutionSelectorDataByIndex( cstack_size );
2977+ break;
2978+ }
2979+ }
2980+
2981+ if ( mdecl_sel )
2982+ {
2983+ if ( dynamic_cast <FuncsigDefinition*> ( mdecl_sel->declsel.GetBuiltType() ) != nullptr &&
2984+ mdecl_sel->declsel.special_init == true )
2985+ {
2986+ // Empty and successful.
2987+ return nullptr;
2988+ }
2989+ }
2990+
2991+ // Just the regular terminator with the semi-colon.
2992+ return step_spaceterm;
2993+ };
2994+
2995+ lexer.AddStep( "mdeclterm", std::move( mdeclterm ) );
27652996 }
2766- assert( lexer.CompileProduction( compiler, "declinit", "( spaces init:initexpr | spaces '=' spaces init:operation | spaces init:curlypack )^0:1" ) == true );
2767- assert( lexer.CompileProduction( compiler, "functag", "\"func\" | \"operator\" | \"proc\"" ) == true );
2997+ assert( lexer.CompileProduction( compiler, "declinit", "( spaces init_s:initexpr | spaces '=' spaces init:operation | spaces init:curlypack )^0:1" ) == true );
2998+ assert( lexer.CompileProduction( compiler, "functag", "\"func\" | \"proc\"" ) == true );
27682999 assert( lexer.CompileProduction( compiler, "type", "&(decltemplate, nameplacehold=spec, initplacehold=empty)" ) == true );
27693000 {
27703001 struct type_selector
@@ -2813,7 +3044,7 @@
28133044 };
28143045 lexer.GetNamedProduction( "type" ).setSelector <type_selector> ();
28153046 }
2816- assert( lexer.CompileProduction( compiler, "paramlist_opt", "[<0>decl_opt, spaces ',' spaces]" ) == true );
3047+ assert( lexer.CompileProduction( compiler, "paramlist_opt", "[<0>param:decl_opt, spaces ',' spaces]" ) == true );
28173048
28183049 printf( "testing COS operations (non-deep)..." );
28193050 {
@@ -3587,46 +3818,47 @@
35873818 {
35883819 COSNode *_root = lexer.StartProduction( "2 | 1 & 0 == 2;" );
35893820
3590- CompareEqualityOperation *root = dynamic_cast <CompareEqualityOperation*> ( _root );
3821+ BitwiseOrOperation *root = dynamic_cast <BitwiseOrOperation*> ( _root );
35913822
35923823 assert( root != nullptr );
35933824
3594- BitwiseOrOperation *left_root = dynamic_cast <BitwiseOrOperation*> ( root->left );
3825+ NumberString *left = dynamic_cast <NumberString*> ( root->left );
35953826
3596- assert( left_root != nullptr );
3827+ assert( left != nullptr );
3828+ assert( left->numeric_string == "2" );
35973829
3598- NumberString *first = dynamic_cast <NumberString*> ( left_root->left );
3830+ left->Delete();
35993831
3600- assert( first != nullptr );
3601- assert( first->numeric_string == "2" );
3832+ BitwiseAndOperation *right = dynamic_cast <BitwiseAndOperation*> ( root->right );
36023833
3603- first->Delete();
3834+ assert( right != nullptr );
36043835
3605- BitwiseAndOperation *right_left_root = dynamic_cast <BitwiseAndOperation*> ( left_root->right );
3836+ NumberString *right_left = dynamic_cast <NumberString*> ( right->left );
36063837
3607- assert( right_left_root != nullptr );
3838+ assert( right_left != nullptr );
3839+ assert( right_left->numeric_string == "1" );
36083840
3609- NumberString *second = dynamic_cast <NumberString*> ( right_left_root->left );
3610- NumberString *third = dynamic_cast <NumberString*> ( right_left_root->right );
3841+ right_left->Delete();
36113842
3612- assert( second != nullptr );
3613- assert( second->numeric_string == "1" );
3614- assert( third != nullptr );
3615- assert( third->numeric_string == "0" );
3843+ CompareEqualityOperation *right_right = dynamic_cast <CompareEqualityOperation*> ( right->right );
36163844
3617- second->Delete();
3618- third->Delete();
3845+ assert( right_right != nullptr );
3846+
3847+ NumberString *right_right_left = dynamic_cast <NumberString*> ( right_right->left );
3848+
3849+ assert( right_right_left != nullptr );
3850+ assert( right_right_left->numeric_string == "0" );
36193851
3620- right_left_root->Delete();
3621- left_root->Delete();
3852+ right_right_left->Delete();
36223853
3623- NumberString *fourth = dynamic_cast <NumberString*> ( root->right );
3854+ NumberString *right_right_right = dynamic_cast <NumberString*> ( right_right->right );
36243855
3625- assert( fourth != nullptr );
3626- assert( fourth->numeric_string == "2" );
3856+ assert( right_right_right != nullptr );
3857+ assert( right_right_right->numeric_string == "2" );
36273858
3628- fourth->Delete();
3629-
3859+ right_right_right->Delete();
3860+ right_right->Delete();
3861+ right->Delete();
36303862 root->Delete();
36313863 }
36323864
@@ -3634,42 +3866,40 @@
36343866 {
36353867 COSNode *_root = lexer.StartProduction( "10|~0==10;" );
36363868
3637- CompareEqualityOperation *root = dynamic_cast <CompareEqualityOperation*> ( _root );
3638-
3869+ BitwiseOrOperation *root = dynamic_cast <BitwiseOrOperation*> ( _root );
3870+
36393871 assert( root != nullptr );
36403872
3641- BitwiseOrOperation *left_root = dynamic_cast <BitwiseOrOperation*> ( root->left );
3873+ NumberString *left = dynamic_cast <NumberString*> ( root->left );
36423874
3643- assert( left_root != nullptr );
3875+ assert( left != nullptr );
3876+ assert( left->numeric_string == "10" );
36443877
3645- NumberString *first = dynamic_cast <NumberString*> ( left_root->left );
3878+ left->Delete();
36463879
3647- assert( first != nullptr );
3648- assert( first->numeric_string == "10" );
3880+ CompareEqualityOperation *right = dynamic_cast <CompareEqualityOperation*> ( root->right );
36493881
3650- first->Delete();
3882+ assert( right != nullptr );
36513883
3652- BitwiseNegationOperation *right_left_root = dynamic_cast <BitwiseNegationOperation*> ( left_root->right );
3884+ BitwiseNegationOperation *right_left = dynamic_cast <BitwiseNegationOperation*> ( right->left );
36533885
3654- assert( right_left_root != nullptr );
3886+ assert( right_left != nullptr );
36553887
3656- NumberString *second = dynamic_cast <NumberString*> ( right_left_root->op );
3888+ NumberString *right_left_op = dynamic_cast <NumberString*> ( right_left->op );
36573889
3658- assert( second != nullptr );
3659- assert( second->numeric_string == "0" );
3890+ assert( right_left_op != nullptr );
3891+ assert( right_left_op->numeric_string == "0" );
36603892
3661- second->Delete();
3893+ right_left_op->Delete();
3894+ right_left->Delete();
36623895
3663- right_left_root->Delete();
3664- left_root->Delete();
3896+ NumberString *right_right = dynamic_cast <NumberString*> ( right->right );
3897+
3898+ assert( right_right != nullptr );
3899+ assert( right_right->numeric_string == "10" );
36653900
3666- NumberString *third = dynamic_cast <NumberString*> ( root->right );
3667-
3668- assert( third != nullptr );
3669- assert( third->numeric_string == "10" );
3670-
3671- third->Delete();
3672-
3901+ right_right->Delete();
3902+ right->Delete();
36733903 root->Delete();
36743904 }
36753905
@@ -4011,6 +4241,96 @@
40114241
40124242 root->Delete();
40134243 }
4244+
4245+ // 30)
4246+ {
4247+ COSNode *_root = lexer.StartProduction( "(2 | 1 & 0) == 2;" );
4248+
4249+ CompareEqualityOperation *root = dynamic_cast <CompareEqualityOperation*> ( _root );
4250+
4251+ assert( root != nullptr );
4252+
4253+ BitwiseOrOperation *left_root = dynamic_cast <BitwiseOrOperation*> ( root->left );
4254+
4255+ assert( left_root != nullptr );
4256+
4257+ NumberString *first = dynamic_cast <NumberString*> ( left_root->left );
4258+
4259+ assert( first != nullptr );
4260+ assert( first->numeric_string == "2" );
4261+
4262+ first->Delete();
4263+
4264+ BitwiseAndOperation *right_left_root = dynamic_cast <BitwiseAndOperation*> ( left_root->right );
4265+
4266+ assert( right_left_root != nullptr );
4267+
4268+ NumberString *second = dynamic_cast <NumberString*> ( right_left_root->left );
4269+ NumberString *third = dynamic_cast <NumberString*> ( right_left_root->right );
4270+
4271+ assert( second != nullptr );
4272+ assert( second->numeric_string == "1" );
4273+ assert( third != nullptr );
4274+ assert( third->numeric_string == "0" );
4275+
4276+ second->Delete();
4277+ third->Delete();
4278+
4279+ right_left_root->Delete();
4280+ left_root->Delete();
4281+
4282+ NumberString *fourth = dynamic_cast <NumberString*> ( root->right );
4283+
4284+ assert( fourth != nullptr );
4285+ assert( fourth->numeric_string == "2" );
4286+
4287+ fourth->Delete();
4288+
4289+ root->Delete();
4290+ }
4291+
4292+ // 31)
4293+ {
4294+ COSNode *_root = lexer.StartProduction( "(10|~0)==10;" );
4295+
4296+ CompareEqualityOperation *root = dynamic_cast <CompareEqualityOperation*> ( _root );
4297+
4298+ assert( root != nullptr );
4299+
4300+ BitwiseOrOperation *left_root = dynamic_cast <BitwiseOrOperation*> ( root->left );
4301+
4302+ assert( left_root != nullptr );
4303+
4304+ NumberString *first = dynamic_cast <NumberString*> ( left_root->left );
4305+
4306+ assert( first != nullptr );
4307+ assert( first->numeric_string == "10" );
4308+
4309+ first->Delete();
4310+
4311+ BitwiseNegationOperation *right_left_root = dynamic_cast <BitwiseNegationOperation*> ( left_root->right );
4312+
4313+ assert( right_left_root != nullptr );
4314+
4315+ NumberString *second = dynamic_cast <NumberString*> ( right_left_root->op );
4316+
4317+ assert( second != nullptr );
4318+ assert( second->numeric_string == "0" );
4319+
4320+ second->Delete();
4321+
4322+ right_left_root->Delete();
4323+ left_root->Delete();
4324+
4325+ NumberString *third = dynamic_cast <NumberString*> ( root->right );
4326+
4327+ assert( third != nullptr );
4328+ assert( third->numeric_string == "10" );
4329+
4330+ third->Delete();
4331+
4332+ root->Delete();
4333+ }
40144334 }
40154335 printf( "ok.\n" );
40164336
@@ -5049,32 +5369,705 @@
50495369 {
50505370 // 1)
50515371 {
5372+ COSNode *_root = lexer.StartProduction( "int func test() { return 0; }" );
50525373
5374+ DeclarationStatement *root = dynamic_cast <DeclarationStatement*> ( _root );
5375+
5376+ assert( root != nullptr );
5377+
5378+ SpecifierString *name = dynamic_cast <SpecifierString*> ( root->name );
5379+
5380+ assert( name != nullptr );
5381+ assert( name->string == "test" );
5382+
5383+ name->Delete();
5384+
5385+ FuncsigDefinition *type = dynamic_cast <FuncsigDefinition*> ( root->type );
5386+
5387+ assert( type != nullptr );
5388+ assert( type->params.GetCount() == 0 );
5389+
5390+ SpecifierString *type_rtype = dynamic_cast <SpecifierString*> ( type->return_type );
5391+
5392+ assert( type_rtype != nullptr );
5393+ assert( type_rtype->string == "int" );
5394+
5395+ type_rtype->Delete();
5396+
5397+ type->Delete();
5398+
5399+ BlockStatement *body = dynamic_cast <BlockStatement*> ( root->initializer );
5400+
5401+ assert( body != nullptr );
5402+ assert( body->statements.GetCount() == 1 );
5403+
5404+ ReturnStatement *body_1 = dynamic_cast <ReturnStatement*> ( body->statements[0] );
5405+
5406+ assert( body_1 != nullptr );
5407+
5408+ NumberString *body_1_op = dynamic_cast <NumberString*> ( body_1->op );
5409+
5410+ assert( body_1_op != nullptr );
5411+ assert( body_1_op->numeric_string == "0" );
5412+
5413+ body_1_op->Delete();
5414+ body_1->Delete();
5415+ body->Delete();
5416+ root->Delete();
50535417 }
50545418
50555419 // 2)
50565420 {
5421+ COSNode *_root = lexer.StartProduction( "any func doit(any p1, any p2){p1+=p2;p1+=getvalue();return p1;}" );
50575422
5423+ DeclarationStatement *root = dynamic_cast <DeclarationStatement*> ( _root );
5424+
5425+ assert( root != nullptr );
5426+
5427+ SpecifierString *name = dynamic_cast <SpecifierString*> ( root->name );
5428+
5429+ assert( name != nullptr );
5430+ assert( name->string == "doit" );
5431+
5432+ name->Delete();
5433+
5434+ FuncsigDefinition *type = dynamic_cast <FuncsigDefinition*> ( root->type );
5435+
5436+ assert( type != nullptr );
5437+ assert( type->params.GetCount() == 2 );
5438+
5439+ SpecifierString *type_rtype = dynamic_cast <SpecifierString*> ( type->return_type );
5440+
5441+ assert( type_rtype != nullptr );
5442+ assert( type_rtype->string == "any" );
5443+
5444+ type_rtype->Delete();
5445+
5446+ DeclarationStatement *type_p1 = dynamic_cast <DeclarationStatement*> ( type->params[0] );
5447+
5448+ assert( type_p1 != nullptr );
5449+ assert( type_p1->initializer == nullptr );
5450+
5451+ SpecifierString *type_p1_type = dynamic_cast <SpecifierString*> ( type_p1->type );
5452+
5453+ assert( type_p1_type != nullptr );
5454+ assert( type_p1_type->string == "any" );
5455+
5456+ type_p1_type->Delete();
5457+
5458+ SpecifierString *type_p1_name = dynamic_cast <SpecifierString*> ( type_p1->name );
5459+
5460+ assert( type_p1_name != nullptr );
5461+ assert( type_p1_name->string == "p1" );
5462+
5463+ type_p1_name->Delete();
5464+ type_p1->Delete();
5465+
5466+ DeclarationStatement *type_p2 = dynamic_cast <DeclarationStatement*> ( type->params[1] );
5467+
5468+ assert( type_p2 != nullptr );
5469+ assert( type_p2->initializer == nullptr );
5470+
5471+ SpecifierString *type_p2_type = dynamic_cast <SpecifierString*> ( type_p2->type );
5472+
5473+ assert( type_p2_type != nullptr );
5474+ assert( type_p2_type->string == "any" );
5475+
5476+ type_p2_type->Delete();
5477+
5478+ SpecifierString *type_p2_name = dynamic_cast <SpecifierString*> ( type_p2->name );
5479+
5480+ assert( type_p2_name != nullptr );
5481+ assert( type_p2_name->string == "p2" );
5482+
5483+ type_p2_name->Delete();
5484+ type_p2->Delete();
5485+ type->Delete();
5486+
5487+ BlockStatement *init = dynamic_cast <BlockStatement*> ( root->initializer );
5488+
5489+ assert( init != nullptr );
5490+ assert( init->statements.GetCount() == 3 );
5491+
5492+ AssignAddOperation *init_1 = dynamic_cast <AssignAddOperation*> ( init->statements[0] );
5493+
5494+ assert( init_1 != nullptr );
5495+
5496+ SpecifierString *init_1_left = dynamic_cast <SpecifierString*> ( init_1->left );
5497+
5498+ assert( init_1_left != nullptr );
5499+ assert( init_1_left->string == "p1" );
5500+
5501+ init_1_left->Delete();
5502+
5503+ SpecifierString *init_1_right = dynamic_cast <SpecifierString*> ( init_1->right );
5504+
5505+ assert( init_1_right != nullptr );
5506+ assert( init_1_right->string == "p2" );
5507+
5508+ init_1_right->Delete();
5509+ init_1->Delete();
5510+
5511+ AssignAddOperation *init_2 = dynamic_cast <AssignAddOperation*> ( init->statements[1] );
5512+
5513+ assert( init_2 != nullptr );
5514+
5515+ SpecifierString *init_2_left = dynamic_cast <SpecifierString*> ( init_2->left );
5516+
5517+ assert( init_2_left != nullptr );
5518+ assert( init_2_left->string == "p1" );
5519+
5520+ init_2_left->Delete();
5521+
5522+ FunctionCallOperation *init_2_right = dynamic_cast <FunctionCallOperation*> ( init_2->right );
5523+
5524+ assert( init_2_right != nullptr );
5525+ assert( init_2_right->params.GetCount() == 0 );
5526+
5527+ SpecifierString *init_2_right_what = dynamic_cast <SpecifierString*> ( init_2_right->what );
5528+
5529+ assert( init_2_right_what != nullptr );
5530+ assert( init_2_right_what->string == "getvalue" );
5531+
5532+ init_2_right_what->Delete();
5533+ init_2_right->Delete();
5534+ init_2->Delete();
5535+
5536+ ReturnStatement *init_3 = dynamic_cast <ReturnStatement*> ( init->statements[2] );
5537+
5538+ assert( init_3 != nullptr );
5539+
5540+ SpecifierString *init_3_op = dynamic_cast <SpecifierString*> ( init_3->op );
5541+
5542+ assert( init_3_op != nullptr );
5543+ assert( init_3_op->string == "p1" );
5544+
5545+ init_3_op->Delete();
5546+ init_3->Delete();
5547+ init->Delete();
5548+ root->Delete();
50585549 }
50595550
50605551 // 3)
50615552 {
5553+ COSNode *_root = lexer.StartProduction( "any func get(int a) return a+1;" );
50625554
5555+ DeclarationStatement *root = dynamic_cast <DeclarationStatement*> ( _root );
5556+
5557+ assert( root != nullptr );
5558+
5559+ SpecifierString *name = dynamic_cast <SpecifierString*> ( root->name );
5560+
5561+ assert( name != nullptr );
5562+ assert( name->string == "get" );
5563+
5564+ name->Delete();
5565+
5566+ FuncsigDefinition *type = dynamic_cast <FuncsigDefinition*> ( root->type );
5567+
5568+ assert( type != nullptr );
5569+ assert( type->params.GetCount() == 1 );
5570+
5571+ SpecifierString *type_rtype = dynamic_cast <SpecifierString*> ( type->return_type );
5572+
5573+ assert( type_rtype != nullptr );
5574+ assert( type_rtype->string == "any" );
5575+
5576+ type_rtype->Delete();
5577+
5578+ DeclarationStatement *type_p1 = dynamic_cast <DeclarationStatement*> ( type->params[0] );
5579+
5580+ assert( type_p1 != nullptr );
5581+ assert( type_p1->initializer == nullptr );
5582+
5583+ SpecifierString *type_p1_type = dynamic_cast <SpecifierString*> ( type_p1->type );
5584+
5585+ assert( type_p1_type != nullptr );
5586+ assert( type_p1_type->string == "int" );
5587+
5588+ type_p1_type->Delete();
5589+
5590+ SpecifierString *type_p1_name = dynamic_cast <SpecifierString*> ( type_p1->name );
5591+
5592+ assert( type_p1_name != nullptr );
5593+ assert( type_p1_name->string == "a" );
5594+
5595+ type_p1_name->Delete();
5596+ type_p1->Delete();
5597+ type->Delete();
5598+
5599+ ReturnStatement *init = dynamic_cast <ReturnStatement*> ( root->initializer );
5600+
5601+ assert( init != nullptr );
5602+
5603+ AddOperation *init_op = dynamic_cast <AddOperation*> ( init->op );
5604+
5605+ assert( init_op != nullptr );
5606+
5607+ SpecifierString *init_op_left = dynamic_cast <SpecifierString*> ( init_op->left );
5608+
5609+ assert( init_op_left != nullptr );
5610+ assert( init_op_left->string == "a" );
5611+
5612+ init_op_left->Delete();
5613+
5614+ NumberString *init_op_right = dynamic_cast <NumberString*> ( init_op->right );
5615+
5616+ assert( init_op_right != nullptr );
5617+ assert( init_op_right->numeric_string == "1" );
5618+
5619+ init_op_right->Delete();
5620+ init_op->Delete();
5621+ init->Delete();
5622+ root->Delete();
50635623 }
50645624
50655625 // 4)
50665626 {
5627+ COSNode *_root = lexer.StartProduction( "any func set(any key, any value=2){ map[key] = value; }" );
50675628
5629+ DeclarationStatement *root = dynamic_cast <DeclarationStatement*> ( _root );
5630+
5631+ assert( root != nullptr );
5632+
5633+ SpecifierString *name = dynamic_cast <SpecifierString*> ( root->name );
5634+
5635+ assert( name != nullptr );
5636+ assert( name->string == "set" );
5637+
5638+ name->Delete();
5639+
5640+ FuncsigDefinition *type = dynamic_cast <FuncsigDefinition*> ( root->type );
5641+
5642+ assert( type != nullptr );
5643+ assert( type->params.GetCount() == 2 );
5644+
5645+ SpecifierString *type_rtype = dynamic_cast <SpecifierString*> ( type->return_type );
5646+
5647+ assert( type_rtype != nullptr );
5648+ assert( type_rtype->string == "any" );
5649+
5650+ type_rtype->Delete();
5651+
5652+ DeclarationStatement *type_p1 = dynamic_cast <DeclarationStatement*> ( type->params[0] );
5653+
5654+ assert( type_p1 != nullptr );
5655+ assert( type_p1->initializer == nullptr );
5656+
5657+ SpecifierString *type_p1_type = dynamic_cast <SpecifierString*> ( type_p1->type );
5658+
5659+ assert( type_p1_type != nullptr );
5660+ assert( type_p1_type->string == "any" );
5661+
5662+ type_p1_type->Delete();
5663+
5664+ SpecifierString *type_p1_name = dynamic_cast <SpecifierString*> ( type_p1->name );
5665+
5666+ assert( type_p1_name != nullptr );
5667+ assert( type_p1_name->string == "key" );
5668+
5669+ type_p1_name->Delete();
5670+ type_p1->Delete();
5671+
5672+ DeclarationStatement *type_p2 = dynamic_cast <DeclarationStatement*> ( type->params[1] );
5673+
5674+ assert( type_p2 != nullptr );
5675+
5676+ SpecifierString *type_p2_type = dynamic_cast <SpecifierString*> ( type_p2->type );
5677+
5678+ assert( type_p2_type != nullptr );
5679+ assert( type_p2_type->string == "any" );
5680+
5681+ type_p2_type->Delete();
5682+
5683+ SpecifierString *type_p2_name = dynamic_cast <SpecifierString*> ( type_p2->name );
5684+
5685+ assert( type_p2_name != nullptr );
5686+ assert( type_p2_name->string == "value" );
5687+
5688+ type_p2_name->Delete();
5689+
5690+ NumberString *type_p2_init = dynamic_cast <NumberString*> ( type_p2->initializer );
5691+
5692+ assert( type_p2_init != nullptr );
5693+ assert( type_p2_init->numeric_string == "2" );
5694+
5695+ type_p2_init->Delete();
5696+ type_p2->Delete();
5697+ type->Delete();
5698+
5699+ BlockStatement *init = dynamic_cast <BlockStatement*> ( root->initializer );
5700+
5701+ assert( init != nullptr );
5702+ assert( init->statements.GetCount() == 1 );
5703+
5704+ AssignmentOperation *init_1 = dynamic_cast <AssignmentOperation*> ( init->statements[0] );
5705+
5706+ assert( init_1 != nullptr );
5707+
5708+ EdgeBracketsOperation *init_1_left = dynamic_cast <EdgeBracketsOperation*> ( init_1->left );
5709+
5710+ assert( init_1_left != nullptr );
5711+
5712+ SpecifierString *init_1_left_left = dynamic_cast <SpecifierString*> ( init_1_left->left );
5713+
5714+ assert( init_1_left_left != nullptr );
5715+ assert( init_1_left_left->string == "map" );
5716+
5717+ init_1_left_left->Delete();
5718+
5719+ SpecifierString *init_1_left_right = dynamic_cast <SpecifierString*> ( init_1_left->right );
5720+
5721+ assert( init_1_left_right != nullptr );
5722+ assert( init_1_left_right->string == "key" );
5723+
5724+ init_1_left_right->Delete();
5725+ init_1_left->Delete();
5726+
5727+ SpecifierString *init_1_right = dynamic_cast <SpecifierString*> ( init_1->right );
5728+
5729+ assert( init_1_right != nullptr );
5730+ assert( init_1_right->string == "value" );
5731+
5732+ init_1_right->Delete();
5733+ init_1->Delete();
5734+ init->Delete();
5735+ root->Delete();
50685736 }
50695737
50705738 // 5)
50715739 {
5740+ COSNode *_root = lexer.StartProduction( "any func operator + (any left, any right) {if(type(left)==int&&type(right)==int)return builtin_add(left,right);}" );
50725741
5742+ DeclarationStatement *root = dynamic_cast <DeclarationStatement*> ( _root );
5743+
5744+ assert( root != nullptr );
5745+
5746+ SpecifierOperator *name = dynamic_cast <SpecifierOperator*> ( root->name );
5747+
5748+ assert( name != nullptr );
5749+ assert( name->op_type == SpecifierOperator::eOpType::ADD );
5750+
5751+ name->Delete();
5752+
5753+ FuncsigDefinition *type = dynamic_cast <FuncsigDefinition*> ( root->type );
5754+
5755+ assert( type != nullptr );
5756+ assert( type->params.GetCount() == 2 );
5757+
5758+ DeclarationStatement *type_p1 = dynamic_cast <DeclarationStatement*> ( type->params[0] );
5759+
5760+ assert( type_p1 != nullptr );
5761+ assert( type_p1->initializer == nullptr );
5762+
5763+ SpecifierString *type_p1_type = dynamic_cast <SpecifierString*> ( type_p1->type );
5764+
5765+ assert( type_p1_type != nullptr );
5766+ assert( type_p1_type->string == "any" );
5767+
5768+ type_p1_type->Delete();
5769+
5770+ SpecifierString *type_p1_name = dynamic_cast <SpecifierString*> ( type_p1->name );
5771+
5772+ assert( type_p1_name != nullptr );
5773+ assert( type_p1_name->string == "left" );
5774+
5775+ type_p1_name->Delete();
5776+ type_p1->Delete();
5777+
5778+ DeclarationStatement *type_p2 = dynamic_cast <DeclarationStatement*> ( type->params[1] );
5779+
5780+ assert( type_p2 != nullptr );
5781+ assert( type_p2->initializer == nullptr );
5782+
5783+ SpecifierString *type_p2_type = dynamic_cast <SpecifierString*> ( type_p2->type );
5784+
5785+ assert( type_p2_type != nullptr );
5786+ assert( type_p2_type->string == "any" );
5787+
5788+ type_p2_type->Delete();
5789+
5790+ SpecifierString *type_p2_name = dynamic_cast <SpecifierString*> ( type_p2->name );
5791+
5792+ assert( type_p2_name != nullptr );
5793+ assert( type_p2_name->string == "right" );
5794+
5795+ type_p2_name->Delete();
5796+ type_p2->Delete();
5797+ type->Delete();
5798+
5799+ BlockStatement *init = dynamic_cast <BlockStatement*> ( root->initializer );
5800+
5801+ assert( init != nullptr );
5802+ assert( init->statements.GetCount() == 1 );
5803+
5804+ IfStatement *init_1 = dynamic_cast <IfStatement*> ( init->statements[0] );
5805+
5806+ assert( init_1 != nullptr );
5807+ assert( init_1->false_branch == nullptr );
5808+
5809+ LogicalAndOperation *init_1_cond = dynamic_cast <LogicalAndOperation*> ( init_1->condition );
5810+
5811+ assert( init_1_cond != nullptr );
5812+
5813+ CompareEqualityOperation *init_1_cond_left = dynamic_cast <CompareEqualityOperation*> ( init_1_cond->left );
5814+
5815+ assert( init_1_cond_left != nullptr );
5816+
5817+ FunctionCallOperation *init_1_cond_left_left = dynamic_cast <FunctionCallOperation*> ( init_1_cond_left->left );
5818+
5819+ assert( init_1_cond_left_left != nullptr );
5820+ assert( init_1_cond_left_left->params.GetCount() == 1 );
5821+
5822+ SpecifierString *init_1_cond_left_left_what = dynamic_cast <SpecifierString*> ( init_1_cond_left_left->what );
5823+
5824+ assert( init_1_cond_left_left_what != nullptr );
5825+ assert( init_1_cond_left_left_what->string == "type" );
5826+
5827+ init_1_cond_left_left_what->Delete();
5828+
5829+ SpecifierString *init_1_cond_left_left_1 = dynamic_cast <SpecifierString*> ( init_1_cond_left_left->params[0] );
5830+
5831+ assert( init_1_cond_left_left_1 != nullptr );
5832+ assert( init_1_cond_left_left_1->string == "left" );
5833+
5834+ init_1_cond_left_left_1->Delete();
5835+ init_1_cond_left_left->Delete();
5836+
5837+ SpecifierString *init_1_cond_left_right = dynamic_cast <SpecifierString*> ( init_1_cond_left->right );
5838+
5839+ assert( init_1_cond_left_right != nullptr );
5840+ assert( init_1_cond_left_right->string == "int" );
5841+
5842+ init_1_cond_left_right->Delete();
5843+ init_1_cond_left->Delete();
5844+
5845+ CompareEqualityOperation *init_1_cond_right = dynamic_cast <CompareEqualityOperation*> ( init_1_cond->right );
5846+
5847+ assert( init_1_cond_right != nullptr );
5848+
5849+ FunctionCallOperation *init_1_cond_right_left = dynamic_cast <FunctionCallOperation*> ( init_1_cond_right->left );
5850+
5851+ assert( init_1_cond_right_left != nullptr );
5852+ assert( init_1_cond_right_left->params.GetCount() == 1 );
5853+
5854+ SpecifierString *init_1_cond_right_left_what = dynamic_cast <SpecifierString*> ( init_1_cond_right_left->what );
5855+
5856+ assert( init_1_cond_right_left_what != nullptr );
5857+ assert( init_1_cond_right_left_what->string == "type" );
5858+
5859+ init_1_cond_right_left_what->Delete();
5860+
5861+ SpecifierString *init_1_cond_right_left_1 = dynamic_cast <SpecifierString*> ( init_1_cond_right_left->params[0] );
5862+
5863+ assert( init_1_cond_right_left_1 != nullptr );
5864+ assert( init_1_cond_right_left_1->string == "right" );
5865+
5866+ init_1_cond_right_left_1->Delete();
5867+ init_1_cond_right_left->Delete();
5868+
5869+ SpecifierString *init_1_cond_right_right = dynamic_cast <SpecifierString*> ( init_1_cond_right->right );
5870+
5871+ assert( init_1_cond_right_right != nullptr );
5872+ assert( init_1_cond_right_right->string == "int" );
5873+
5874+ init_1_cond_right_right->Delete();
5875+ init_1_cond_right->Delete();
5876+ init_1_cond->Delete();
5877+
5878+ ReturnStatement *init_1_tb = dynamic_cast <ReturnStatement*> ( init_1->true_branch );
5879+
5880+ assert( init_1_tb != nullptr );
5881+
5882+ FunctionCallOperation *init_1_tb_op = dynamic_cast <FunctionCallOperation*> ( init_1_tb->op );
5883+
5884+ assert( init_1_tb_op != nullptr );
5885+ assert( init_1_tb_op->params.GetCount() == 2 );
5886+
5887+ SpecifierString *init_1_tb_op_what = dynamic_cast <SpecifierString*> ( init_1_tb_op->what );
5888+
5889+ assert( init_1_tb_op_what != nullptr );
5890+ assert( init_1_tb_op_what->string == "builtin_add" );
5891+
5892+ init_1_tb_op_what->Delete();
5893+
5894+ SpecifierString *init_1_tb_op_1 = dynamic_cast <SpecifierString*> ( init_1_tb_op->params[0] );
5895+
5896+ assert( init_1_tb_op_1 != nullptr );
5897+ assert( init_1_tb_op_1->string == "left" );
5898+
5899+ init_1_tb_op_1->Delete();
5900+
5901+ SpecifierString *init_1_tb_op_2 = dynamic_cast <SpecifierString*> ( init_1_tb_op->params[1] );
5902+
5903+ assert( init_1_tb_op_2 != nullptr );
5904+ assert( init_1_tb_op_2->string == "right" );
5905+
5906+ init_1_tb_op_2->Delete();
5907+ init_1_tb_op->Delete();
5908+ init_1_tb->Delete();
5909+ init_1->Delete();
5910+ init->Delete();
5911+ root->Delete();
50735912 }
50745913
50755914 // 6)
50765915 {
5916+ COSNode *_root = lexer.StartProduction( "int func main(int argc, char*argv[]){while(true){if(runtime==false)return -1;}return 0;}" );
50775917
5918+ DeclarationStatement *root = dynamic_cast <DeclarationStatement*> ( _root );
5919+
5920+ assert( root != nullptr );
5921+
5922+ SpecifierString *name = dynamic_cast <SpecifierString*> ( root->name );
5923+
5924+ assert( name != nullptr );
5925+ assert( name->string == "main" );
5926+
5927+ name->Delete();
5928+
5929+ FuncsigDefinition *type = dynamic_cast <FuncsigDefinition*> ( root->type );
5930+
5931+ assert( type != nullptr );
5932+ assert( type->params.GetCount() == 2 );
5933+
5934+ SpecifierString *type_rtype = dynamic_cast <SpecifierString*> ( type->return_type );
5935+
5936+ assert( type_rtype != nullptr );
5937+ assert( type_rtype->string == "int" );
5938+
5939+ type_rtype->Delete();
5940+
5941+ DeclarationStatement *type_p1 = dynamic_cast <DeclarationStatement*> ( type->params[0] );
5942+
5943+ assert( type_p1 != nullptr );
5944+ assert( type_p1->initializer == nullptr );
5945+
5946+ SpecifierString *type_p1_type = dynamic_cast <SpecifierString*> ( type_p1->type );
5947+
5948+ assert( type_p1_type != nullptr );
5949+ assert( type_p1_type->string == "int" );
5950+
5951+ type_p1_type->Delete();
5952+
5953+ SpecifierString *type_p1_name = dynamic_cast <SpecifierString*> ( type_p1->name );
5954+
5955+ assert( type_p1_name != nullptr );
5956+ assert( type_p1_name->string == "argc" );
5957+
5958+ type_p1_name->Delete();
5959+ type_p1->Delete();
5960+
5961+ DeclarationStatement *type_p2 = dynamic_cast <DeclarationStatement*> ( type->params[1] );
5962+
5963+ assert( type_p2 != nullptr );
5964+ assert( type_p2->initializer == nullptr );
5965+
5966+ SpecifierString *type_p2_name = dynamic_cast <SpecifierString*> ( type_p2->name );
5967+
5968+ assert( type_p2_name != nullptr );
5969+ assert( type_p2_name->string == "argv" );
5970+
5971+ type_p2_name->Delete();
5972+
5973+ ArrayTypeSpecifier *type_p2_type = dynamic_cast <ArrayTypeSpecifier*> ( type_p2->type );
5974+
5975+ assert( type_p2_type != nullptr );
5976+ assert( type_p2_type->array_size_op == nullptr );
5977+
5978+ PointerTypeSpecifier *type_p2_type_spec = dynamic_cast <PointerTypeSpecifier*> ( type_p2_type->spec );
5979+
5980+ assert( type_p2_type_spec != nullptr );
5981+
5982+ SpecifierString *type_p2_type_spec_spec = dynamic_cast <SpecifierString*> ( type_p2_type_spec->spec );
5983+
5984+ assert( type_p2_type_spec_spec != nullptr );
5985+ assert( type_p2_type_spec_spec->string == "char" );
5986+
5987+ type_p2_type_spec_spec->Delete();
5988+ type_p2_type_spec->Delete();
5989+ type_p2_type->Delete();
5990+ type_p2->Delete();
5991+ type->Delete();
5992+
5993+ BlockStatement *init = dynamic_cast <BlockStatement*> ( root->initializer );
5994+
5995+ assert( init != nullptr );
5996+ assert( init->statements.GetCount() == 2 );
5997+
5998+ WhileLoopStatement *init_1 = dynamic_cast <WhileLoopStatement*> ( init->statements[0] );
5999+
6000+ assert( init_1 != nullptr );
6001+
6002+ SpecifierString *init_1_cond = dynamic_cast <SpecifierString*> ( init_1->condition );
6003+
6004+ assert( init_1_cond != nullptr );
6005+ assert( init_1_cond->string == "true" );
6006+
6007+ init_1_cond->Delete();
6008+
6009+ BlockStatement *init_1_exec = dynamic_cast <BlockStatement*> ( init_1->exec );
6010+
6011+ assert( init_1_exec != nullptr );
6012+ assert( init_1_exec->statements.GetCount() == 1 );
6013+
6014+ IfStatement *init_1_exec_1 = dynamic_cast <IfStatement*> ( init_1_exec->statements[0] );
6015+
6016+ assert( init_1_exec_1 != nullptr );
6017+ assert( init_1_exec_1->false_branch == nullptr );
6018+
6019+ CompareEqualityOperation *init_1_exec_1_cond = dynamic_cast <CompareEqualityOperation*> ( init_1_exec_1->condition );
6020+
6021+ assert( init_1_exec_1_cond != nullptr );
6022+
6023+ SpecifierString *init_1_exec_1_cond_left = dynamic_cast <SpecifierString*> ( init_1_exec_1_cond->left );
6024+
6025+ assert( init_1_exec_1_cond_left != nullptr );
6026+ assert( init_1_exec_1_cond_left->string == "runtime" );
6027+
6028+ init_1_exec_1_cond_left->Delete();
6029+
6030+ SpecifierString *init_1_exec_1_cond_right = dynamic_cast <SpecifierString*> ( init_1_exec_1_cond->right );
6031+
6032+ assert( init_1_exec_1_cond_right != nullptr );
6033+ assert( init_1_exec_1_cond_right->string == "false" );
6034+
6035+ init_1_exec_1_cond_right->Delete();
6036+ init_1_exec_1_cond->Delete();
6037+
6038+ ReturnStatement *init_1_exec_1_tb = dynamic_cast <ReturnStatement*> ( init_1_exec_1->true_branch );
6039+
6040+ assert( init_1_exec_1_tb != nullptr );
6041+
6042+ NumericNegationOperation *init_1_exec_1_tb_op = dynamic_cast <NumericNegationOperation*> ( init_1_exec_1_tb->op );
6043+
6044+ assert( init_1_exec_1_tb_op != nullptr );
6045+
6046+ NumberString *init_1_exec_1_tb_op_op = dynamic_cast <NumberString*> ( init_1_exec_1_tb_op->op );
6047+
6048+ assert( init_1_exec_1_tb_op_op != nullptr );
6049+ assert( init_1_exec_1_tb_op_op->numeric_string == "1" );
6050+
6051+ init_1_exec_1_tb_op_op->Delete();
6052+ init_1_exec_1_tb_op->Delete();
6053+ init_1_exec_1_tb->Delete();
6054+ init_1_exec_1->Delete();
6055+ init_1_exec->Delete();
6056+ init_1->Delete();
6057+
6058+ ReturnStatement *init_2 = dynamic_cast <ReturnStatement*> ( init->statements[1] );
6059+
6060+ assert( init_2 != nullptr );
6061+
6062+ NumberString *init_2_op = dynamic_cast <NumberString*> ( init_2->op );
6063+
6064+ assert( init_2_op != nullptr );
6065+ assert( init_2_op->numeric_string == "0" );
6066+
6067+ init_2_op->Delete();
6068+ init_2->Delete();
6069+ init->Delete();
6070+ root->Delete();
50786071 }
50796072 }
50806073 printf( "ok.\n" );
--- testcompiler/src/lexingenv_tests.cpp (revision 64)
+++ testcompiler/src/lexingenv_tests.cpp (revision 65)
@@ -7062,4 +7062,81 @@
70627062 }
70637063 }
70647064 printf( "ok.\n" );
7065+
7066+ printf( "testing ProductionMachine lexical value transgression no calcpath attrib-prefix trashing..." );
7067+ {
7068+ // There could be an implementation bug which would overwrite the attribute-prefixes of calculation-path
7069+ // entries and not restore them, causing bugchecks inside of the lexer implementation.
7070+ // If this unit tests passes then our implementation does not contain said bug.
7071+
7072+ static bool has_received_attrib = false;
7073+
7074+ struct receiver_node : public LexNodeType
7075+ {
7076+ LexNodeType* Clone( void ) override
7077+ {
7078+ return new receiver_node( *this );
7079+ }
7080+
7081+ void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) override
7082+ {
7083+ assert( attrib == "se.th.fo" );
7084+ assert( value == "meow" );
7085+
7086+ has_received_attrib = true;
7087+ }
7088+ };
7089+
7090+ struct sender_node : public LexNodeType
7091+ {
7092+ LexNodeType* Clone( void ) override
7093+ {
7094+ return new sender_node( *this );
7095+ }
7096+
7097+ void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) override
7098+ {
7099+ throw lexing_value_transgression_exception();
7100+ }
7101+ };
7102+
7103+ TestAllocEnv env( eir::constr_with_alloc::DEFAULT, &globalHeapAlloc );
7104+
7105+ decltype(env)::StepToken tok_important( &env );
7106+ tok_important.token_str = "meow";
7107+ tok_important.attribute_key = "fo";
7108+
7109+ decltype(env)::StepAttribution contain_imp( &env );
7110+ contain_imp.SetNode( &tok_important );
7111+ contain_imp.attribute_key = "th";
7112+ contain_imp.setConstructor(
7113+ []
7114+ {
7115+ return new sender_node();
7116+ }
7117+ );
7118+
7119+ decltype(env)::StepAttribution indir( &env );
7120+ indir.SetNode( &contain_imp );
7121+ indir.attribute_key = "se";
7122+
7123+ decltype(env)::StepAttribution rec( &env );
7124+ rec.SetNode( &indir );
7125+ rec.attribute_key = "fi";
7126+ rec.setConstructor(
7127+ []
7128+ {
7129+ return new receiver_node();
7130+ }
7131+ );
7132+
7133+ decltype(env)::ProductionMachine machine( &env );
7134+
7135+ machine.Execute( "meow", &rec );
7136+
7137+ assert( machine.successful == true );
7138+
7139+ assert( has_received_attrib == true );
7140+ }
7141+ printf( "ok.\n" );
70657142 }
\ No newline at end of file
Show on old repository browser