mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-30 14:30:53 -07:00 
			
		
		
		
	Added extern linkage bodies to upfront constructors, more work on parsing constructors
- Made some more parsing helper functions - Got initial prototype of parse_friend done - getting ready to complete prototype of parse_function
This commit is contained in:
		
							
								
								
									
										545
									
								
								project/gen.cpp
									
									
									
									
									
								
							
							
						
						
									
										545
									
								
								project/gen.cpp
									
									
									
									
									
								
							| @@ -65,6 +65,7 @@ namespace gen | ||||
| #	define AST_BODY_CLASS_UNALLOWED_TYPES \ | ||||
| 	case Class_Body:                      \ | ||||
| 	case Enum_Body:                       \ | ||||
| 	case Extern_Linkage:                  \ | ||||
| 	case Friend:                          \ | ||||
| 	case Function_Body:                   \ | ||||
| 	case Function_Fwd:                    \ | ||||
| @@ -84,6 +85,7 @@ namespace gen | ||||
| 	case Access_Private:                     \ | ||||
| 	case Class_Body:                         \ | ||||
| 	case Enum_Body:                          \ | ||||
| 	case Extern_Linkage:                     \ | ||||
| 	case Friend:                             \ | ||||
| 	case Function_Body:                      \ | ||||
| 	case Function_Fwd:                       \ | ||||
| @@ -135,8 +137,27 @@ namespace gen | ||||
| 	case Struct_Body: 						  \ | ||||
| 	case Typename: | ||||
|  | ||||
| #	define AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES \ | ||||
| 	case Access_Public: 					       \ | ||||
| 	case Access_Protected: 					       \ | ||||
| 	case Access_Private: 					       \ | ||||
| 	case Class_Body: 						       \ | ||||
| 	case Enum_Body: 						       \ | ||||
| 	case Execution: 						       \ | ||||
| 	case Friend: 							       \ | ||||
| 	case Function_Body: 					       \ | ||||
| 	case Global_Body: 						       \ | ||||
| 	case Namespace_Body: 					       \ | ||||
| 	case Operator_Member: 					       \ | ||||
| 	case Operator_Member_Fwd: 				       \ | ||||
| 	case Parameters: 						       \ | ||||
| 	case Specifiers: 						       \ | ||||
| 	case Struct_Body: 						       \ | ||||
| 	case Typename: | ||||
|  | ||||
| #	define AST_BODY_STRUCT_UNALLOWED_TYPES \ | ||||
| 	case Enum_Body: 					   \ | ||||
| 	case Extern_Linkage:                   \ | ||||
| 	case Execution: 					   \ | ||||
| 	case Function_Body: 				   \ | ||||
| 	case Global_Body: 					   \ | ||||
| @@ -206,7 +227,7 @@ namespace gen | ||||
| 				{ | ||||
| 					AST_BODY_CLASS_UNALLOWED_TYPES | ||||
| 					{ | ||||
| 						log_failure( "AST::add: Cannot add an AST to a class body." ); | ||||
| 						log_failure( "AST::add: Cannot add %s to a class body.", other->type_str() ); | ||||
| 						return false; | ||||
| 					} | ||||
|  | ||||
| @@ -223,6 +244,23 @@ namespace gen | ||||
| 				log_failure( "AST::add: Cannot add an AST to an enum forward declaration." ); | ||||
| 				return false; | ||||
|  | ||||
| 			case Extern_Linkage: | ||||
| 				log_failure( "AST::add: Cannot add an AST to an extern linkage, only to its body." ); | ||||
| 				return false; | ||||
|  | ||||
| 			case Extern_Linkage_Body: | ||||
| 				switch ( other->Type ) | ||||
| 				{ | ||||
| 					AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES | ||||
| 					{ | ||||
| 						log_failure( "AST::add: Cannot add %s to an extern linkage body.", other->type_str() ); | ||||
| 						return false; | ||||
| 					} | ||||
|  | ||||
| 					default: | ||||
| 						break; | ||||
| 				} | ||||
|  | ||||
| 			case Enum_Body: | ||||
| 				if ( other->Type != Untyped ) | ||||
| 				{ | ||||
| @@ -252,7 +290,7 @@ namespace gen | ||||
| 				{ | ||||
| 					AST_BODY_FUNCTION_UNALLOWED_TYPES | ||||
| 					{ | ||||
| 						log_failure( "AST::add: Cannot add an AST to a function body." ); | ||||
| 						log_failure( "AST::add: Cannot add %s to a function body.", other->type_str() ); | ||||
| 						return false; | ||||
| 					} | ||||
|  | ||||
| @@ -270,7 +308,7 @@ namespace gen | ||||
| 				{ | ||||
| 					AST_BODY_GLOBAL_UNALLOWED_TYPES | ||||
| 					{ | ||||
| 						log_failure( "AST::add: Cannot add an AST to a global body." ); | ||||
| 						log_failure( "AST::add: Cannot add %s to a global body.", other->type_str() ); | ||||
| 						return false; | ||||
| 					} | ||||
|  | ||||
| @@ -279,7 +317,6 @@ namespace gen | ||||
| 				} | ||||
| 			break; | ||||
|  | ||||
|  | ||||
| 			case Namespace: | ||||
| 				if ( Type != Global_Body ) | ||||
| 				{ | ||||
| @@ -292,7 +329,7 @@ namespace gen | ||||
| 				{ | ||||
| 					AST_BODY_NAMESPACE_UNALLOWED_TYPES | ||||
| 					{ | ||||
| 						log_failure( "AST::add: Cannot add an AST to a namespace body." ); | ||||
| 						log_failure( "AST::add: Cannot add %s to a namespace body.", other->type_str() ); | ||||
| 						return false; | ||||
| 					} | ||||
|  | ||||
| @@ -326,7 +363,7 @@ namespace gen | ||||
| 				{ | ||||
| 					AST_BODY_STRUCT_UNALLOWED_TYPES | ||||
| 					{ | ||||
| 						log_failure( "AST::add: Cannot add to a struct body." ); | ||||
| 						log_failure( "AST::add: Cannot add %s to a struct body.", other->type_str() ); | ||||
| 						return false; | ||||
| 					} | ||||
|  | ||||
| @@ -384,10 +421,6 @@ namespace gen | ||||
| 			case Access_Public: | ||||
| 			case Access_Protected: | ||||
| 			case Access_Private: | ||||
| 			case Class_Fwd: | ||||
| 			case Enum_Fwd: | ||||
| 			case Function_Fwd: | ||||
| 			case Specifiers: | ||||
| 				// Can just be the same, as its a cached string. | ||||
| 				result->Content = Content; | ||||
| 				return result; | ||||
| @@ -395,16 +428,28 @@ namespace gen | ||||
| 			// The main purpose of this is to make sure entires in the AST are unique, | ||||
| 			// So that we can assign the new parent without corrupting the existing AST. | ||||
| 			case Class: | ||||
| 			case Class_Fwd: | ||||
| 			case Class_Body: | ||||
| 			case Enum: | ||||
| 			case Enum_Fwd: | ||||
| 			case Enum_Body: | ||||
| 			case Enum_Class: | ||||
| 			case Enum_Class_Fwd: | ||||
| 			case Extern_Linkage: | ||||
| 			case Extern_Linkage_Body: | ||||
| 			case Friend: | ||||
| 			case Function: | ||||
| 			case Function_Fwd: | ||||
| 			case Function_Body: | ||||
| 			case Global_Body: | ||||
| 			case Namespace: | ||||
| 			case Namespace_Body: | ||||
| 			case Operator: | ||||
| 			case Operator_Fwd: | ||||
| 			case Operator_Member: | ||||
| 			case Operator_Member_Fwd: | ||||
| 			case Parameters: | ||||
| 			case Function: | ||||
| 			case Function_Body: | ||||
| 			case Specifiers: | ||||
| 			case Struct: | ||||
| 			case Struct_Fwd: | ||||
| 			case Struct_Body: | ||||
| @@ -412,6 +457,7 @@ namespace gen | ||||
| 			case Typedef: | ||||
| 			case Typename: | ||||
| 			case Using: | ||||
| 			case Using_Namespace: | ||||
| 				s32 index = 0; | ||||
| 				s32 left  = num_entries(); | ||||
| 				while ( left -- ) | ||||
| @@ -532,6 +578,10 @@ namespace gen | ||||
| 				result = string_append_fmt( result, "enum class %s : %s;\n", Name, underlying_type()->to_string() ); | ||||
| 			break; | ||||
|  | ||||
| 			case Extern_Linkage: | ||||
| 				result = string_append_fmt( result, "extern %s\n{\n%s\n};\n", Name, body()->to_string() ); | ||||
| 			break; | ||||
|  | ||||
| 			case Friend: | ||||
| 				result = string_append_fmt( result, "friend %s;\n", Entries[0]->to_string() ); | ||||
| 			break; | ||||
| @@ -773,6 +823,7 @@ namespace gen | ||||
|  | ||||
| 			case Class_Body: | ||||
| 			case Enum_Body: | ||||
| 			case Extern_Linkage_Body: | ||||
| 			case Function_Body: | ||||
| 			case Global_Body: | ||||
| 			case Namespace_Body: | ||||
| @@ -1581,6 +1632,32 @@ namespace gen | ||||
| 		result       = make_code(); | ||||
| 		result->Type = ECode::Execution; | ||||
|  | ||||
| 		result->add_entry( untyped_code ); | ||||
|  | ||||
| 		result.lock(); | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| 	Code def_extern_linkage( s32 length, char const* name, Code body ) | ||||
| 	{ | ||||
| 		using namespace ECode; | ||||
|  | ||||
| 		name_check( def_extern_linkage, length, name ); | ||||
| 		null_check( def_extern_linkage, body ); | ||||
|  | ||||
| 		if ( body->Type != Extern_Linkage_Body || body->Type != Untyped ) | ||||
| 		{ | ||||
| 			log_failure("gen::def_extern_linkage: body is not of extern_linkage or untyped type %s", body->debug_str()); | ||||
| 			return Code::Invalid; | ||||
| 		} | ||||
|  | ||||
| 		Code | ||||
| 		result = make_code(); | ||||
| 		result->Type = Extern_Linkage; | ||||
| 		result->Name = get_cached_string( name, length ); | ||||
|  | ||||
| 		result->add_entry( body ); | ||||
|  | ||||
| 		result.lock(); | ||||
| 		return result; | ||||
| 	} | ||||
| @@ -1697,18 +1774,18 @@ namespace gen | ||||
| 		name_check( def_namespace, length, name ); | ||||
| 		null_check( def_namespace, body ); | ||||
|  | ||||
| 		Code | ||||
| 		result          = make_code(); | ||||
| 		result->Type    = Namespace; | ||||
| 		result->Name    = get_cached_string( name, length ); | ||||
| 		result->Entries = make_code_entries(); | ||||
|  | ||||
| 		if ( body->Type != Namespace_Body || body->Type != Untyped ) | ||||
| 		{ | ||||
| 			log_failure("gen::def_namespace: body is not of namespace or untyped type %s", body->debug_str()); | ||||
| 			return Code::Invalid; | ||||
| 		} | ||||
|  | ||||
| 		Code | ||||
| 		result          = make_code(); | ||||
| 		result->Type    = Namespace; | ||||
| 		result->Name    = get_cached_string( name, length ); | ||||
| 		result->Entries = make_code_entries(); | ||||
|  | ||||
| 		result->add_entry( body ); | ||||
|  | ||||
| 		result.lock(); | ||||
| @@ -1763,7 +1840,7 @@ namespace gen | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| 	Code def_param( Code type, s32 length, char const* name ) | ||||
| 	Code def_param( Code type, s32 length, char const* name, Code value ) | ||||
| 	{ | ||||
| 		using namespace ECode; | ||||
|  | ||||
| @@ -1776,6 +1853,12 @@ namespace gen | ||||
| 			return Code::Invalid; | ||||
| 		} | ||||
|  | ||||
| 		if ( value && value->Type != Untyped ) | ||||
| 		{ | ||||
| 			log_failure( "gen::def_param: value is not untyped - %s", value->debug_str() ); | ||||
| 			return Code::Invalid; | ||||
| 		} | ||||
|  | ||||
| 		Code | ||||
| 		result       = make_code(); | ||||
| 		result->Type = Parameters; | ||||
| @@ -1783,6 +1866,9 @@ namespace gen | ||||
|  | ||||
| 		result->add_entry( type ); | ||||
|  | ||||
| 		if ( value ) | ||||
| 			result->add_entry( value ); | ||||
|  | ||||
| 		result.lock(); | ||||
| 		return result; | ||||
| 	} | ||||
| @@ -2141,6 +2227,41 @@ namespace gen | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| 	Code def_extern_linkage_body( s32 num, ... ) | ||||
| 	{ | ||||
| 		def_body_start( def_extern_linkage_body ); | ||||
|  | ||||
| 		Code | ||||
| 		result       = make_code(); | ||||
| 		result->Type = Extern_Linkage_Body; | ||||
|  | ||||
| 		va_list va; | ||||
| 		va_start(va, num); | ||||
| 		def_body_code_validation_start( def_extern_linkage_body, va_arg(va, Code) ); | ||||
| 			AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES | ||||
| 		def_body_code_validation_end( def_extern_linkage_body ); | ||||
| 		va_end(va); | ||||
|  | ||||
| 		result.lock(); | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| 	Code def_extern_linkage_body( s32 num, Code* codes ) | ||||
| 	{ | ||||
| 		def_body_code_array_start( def_extern_linkage_body ); | ||||
|  | ||||
| 		Code | ||||
| 		result       = make_code(); | ||||
| 		result->Type = Extern_Linkage_Body; | ||||
|  | ||||
| 		def_body_code_validation_start( def_extern_linkage_body, *codes; codes++ ); | ||||
| 			AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES | ||||
| 		def_body_code_validation_end( def_extern_linkage_body ); | ||||
|  | ||||
| 		result.lock(); | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| 	Code def_function_body( s32 num, ... ) | ||||
| 	{ | ||||
| 		def_body_start( def_function_body ); | ||||
| @@ -2267,8 +2388,7 @@ namespace gen | ||||
| 		s32         name_length = va_arg(va, s32 ); | ||||
| 		char const* name        = va_arg(va, char const*); | ||||
|  | ||||
| 		result->Name    = get_cached_string( name, name_length ); | ||||
| 		result->Entries = make_code_entries(); | ||||
| 		result->Name = get_cached_string( name, name_length ); | ||||
|  | ||||
| 		if ( type->Type != Typename ) | ||||
| 		{ | ||||
| @@ -2531,14 +2651,18 @@ namespace gen | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| 	Code make_global_body( s32 length, char const* name, s32 num, ... ) | ||||
| 	Code make_global_body( s32 length, char const* name ) | ||||
| 	{ | ||||
| 		name_check( make_global_body, length, name ); | ||||
|  | ||||
| 		Code | ||||
| 		result       = make_code(); | ||||
| 		result->Type = ECode::Global_Body; | ||||
| 		result->Name = get_cached_string( name, length ); | ||||
|  | ||||
| 		if ( length > 0 ) | ||||
| 			result->Name = get_cached_string( name, length ); | ||||
|  | ||||
|  | ||||
|  | ||||
| 		return result; | ||||
| 	} | ||||
| @@ -2744,6 +2868,11 @@ namespace gen | ||||
| 			sptr        Length; | ||||
| 			TokType     Type; | ||||
| 			bool 	    IsAssign; | ||||
|  | ||||
| 			operator bool() | ||||
| 			{ | ||||
| 				return Text && Length && Type != TokType::Invalid; | ||||
| 			} | ||||
| 		}; | ||||
|  | ||||
| 		TokType get_tok_type( char const* word, s32 length ) | ||||
| @@ -3266,6 +3395,160 @@ namespace gen | ||||
| #	define check( Type_ ) left && currtok.Type == Type_ | ||||
| #pragma endregion Helper Macros | ||||
|  | ||||
| 	Code parse_type( Parser::TokArray& toks, char const* func_name ); | ||||
|  | ||||
| 	inline | ||||
| 	Code parse_array_decl( Parser::TokArray& toks, char const* func_name ) | ||||
| 	{ | ||||
| 		using namespace Parser; | ||||
|  | ||||
| 		if ( check( TokType::BraceSquare_Open ) ) | ||||
| 		{ | ||||
| 			eat( TokType::BraceSquare_Open ); | ||||
|  | ||||
| 			if ( left == 0 ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, unexpected end of typedef definition ( '[]' scope started )", txt(parse_typedef) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			if ( currtok.Type == TokType::BraceSquare_Close ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, empty array expression in typedef definition", txt(parse_typedef) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			Token untyped_tok = currtok; | ||||
|  | ||||
| 			while ( left && currtok.Type != TokType::BraceSquare_Close ) | ||||
| 			{ | ||||
| 				untyped_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)untyped_tok.Text; | ||||
| 			} | ||||
|  | ||||
| 			Code array_expr = untyped_str( untyped_tok.Length, untyped_tok.Text ); | ||||
|  | ||||
| 			if ( left == 0 ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, unexpected end of type definition, expected ]", txt(parse_typedef) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			if ( currtok.Type != TokType::BraceSquare_Close ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, expected ] in type definition, not %s", txt(parse_typedef), str_tok_type( currtok.Type ) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			eat( TokType::BraceSquare_Close ); | ||||
| 			return array_expr; | ||||
| 		} | ||||
|  | ||||
| 		return Code::Invalid; | ||||
| 	} | ||||
|  | ||||
| 	inline | ||||
| 	Parser::Token parse_identifier( Parser::TokArray& toks, char const* func_name ) | ||||
| 	{ | ||||
| 		using namespace Parser; | ||||
| 		Token name = currtok; | ||||
|  | ||||
| 		eat( TokType::Identifier ); | ||||
|  | ||||
| 		while ( left && currtok.Type == TokType::Access_StaticSymbol ) | ||||
| 		{ | ||||
| 			eat( TokType::Access_StaticSymbol ); | ||||
|  | ||||
| 			if ( left == 0 ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, unexpected end of type definition, expected identifier", func_name ); | ||||
| 				return { nullptr, 0, TokType::Invalid }; | ||||
| 			} | ||||
|  | ||||
| 			if ( currtok.Type != TokType::Identifier ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, expected identifier in type definition, not %s", func_name, str_tok_type( currtok.Type ) ); | ||||
| 				return { nullptr, 0, TokType::Invalid }; | ||||
| 			} | ||||
|  | ||||
| 			name.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)name.Text; | ||||
| 			eat( TokType::Identifier ); | ||||
| 		} | ||||
|  | ||||
| 		return name; | ||||
| 	} | ||||
|  | ||||
| 	Code parse_params( Parser::TokArray& toks, char const* context ) | ||||
| 	{ | ||||
| 		using namespace Parser; | ||||
| 		using namespace ECode; | ||||
|  | ||||
| 		eat( TokType::Capture_Start ); | ||||
|  | ||||
| 		if ( check(TokType::Capture_End) ) | ||||
| 		{ | ||||
| 			eat( TokType::Capture_End ); | ||||
| 			return { nullptr }; | ||||
| 		} | ||||
|  | ||||
| 		Code | ||||
| 		result = make_code(); | ||||
| 		result->Type = Parameters; | ||||
|  | ||||
| 		while ( left && currtok.Type != TokType::Capture_End) | ||||
| 		{ | ||||
| 			Code type  = { nullptr }; | ||||
| 			Code value = { nullptr }; | ||||
|  | ||||
| 			type = parse_type( toks, context ); | ||||
| 			if ( type == Code::Invalid ) | ||||
| 				return Code::Invalid; | ||||
|  | ||||
| 			Token name = currtok; | ||||
| 			eat( TokType::Identifier ); | ||||
|  | ||||
| 			if ( currtok.IsAssign ) | ||||
| 			{ | ||||
| 				eat( TokType::Operator ); | ||||
|  | ||||
| 				Token value_tok = currtok; | ||||
|  | ||||
| 				if ( currtok.Type == TokType::Statement_End ) | ||||
| 				{ | ||||
| 					log_failure( "gen::%s: Expected value after assignment operator", context ); | ||||
| 					return Code::Invalid; | ||||
| 				} | ||||
|  | ||||
| 				while ( left && currtok.Type != TokType::Statement_End ) | ||||
| 				{ | ||||
| 					value_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)value_tok.Text; | ||||
| 					eat( currtok.Type ); | ||||
| 				} | ||||
|  | ||||
| 				value = parse_type( toks, context ); | ||||
| 			} | ||||
|  | ||||
| 			Code | ||||
| 			param = make_code(); | ||||
| 			param->Type = Parameters; | ||||
| 			param->Name = get_cached_string( name.Text, name.Length ); | ||||
|  | ||||
| 			param->add_entry( type ); | ||||
|  | ||||
| 			if ( value ) | ||||
| 				param->add_entry( value ); | ||||
|  | ||||
| 			param.lock(); | ||||
|  | ||||
| 			result->add_entry( param ); | ||||
| 			eat( TokType::Comma ); | ||||
| 		} | ||||
| 		eat( TokType::Capture_End ); | ||||
|  | ||||
| 		result.lock(); | ||||
| 		return result; | ||||
| 	#	undef context | ||||
| 	} | ||||
|  | ||||
| 	Code parse_class( s32 length, char const* def ) | ||||
| 	{ | ||||
| 		using namespace Parser; | ||||
| @@ -3391,14 +3674,10 @@ namespace gen | ||||
| 	#	undef context | ||||
| 	} | ||||
|  | ||||
| 	Code parse_execution( s32 length, char const* exec_def ) | ||||
| 	{ | ||||
| 		not_implemented( parse_execution ); | ||||
| 	} | ||||
|  | ||||
| 	Code parse_friend( s32 length, char const* def ) | ||||
| 	{ | ||||
| 		using namespace Parser; | ||||
| 		using namespace ECode; | ||||
|  | ||||
| #		define context parse_friend | ||||
| 		check_parse_args( parse_friend, length, def ); | ||||
| @@ -3409,19 +3688,46 @@ namespace gen | ||||
|  | ||||
| 		eat( TokType::Decl_Friend ); | ||||
|  | ||||
| 		// This can either be a simple type, or a function declaration. | ||||
| 		// If its a function declaration, it will have a return type, followed by a name, followed by a parameter list. | ||||
| 		// If its a simple type, it will have a type, followed by a name. | ||||
| 		Code function = { nullptr }; | ||||
|  | ||||
| 		// Type declaration or return type | ||||
| 		Code type = parse_type( toks, txt(parse_friend) ); | ||||
| 		if ( type == Code::Invalid ) | ||||
| 			return Code::Invalid; | ||||
|  | ||||
| 		// Funciton declaration | ||||
| 		if ( currtok.Type == TokType::Identifier ) | ||||
| 		{ | ||||
| 			// Name | ||||
| 			Token name = parse_identifier( toks, txt(parse_friend) ); | ||||
|  | ||||
| 			// Parameter list | ||||
| 			Code params = parse_params( toks, txt(parse_friend) ); | ||||
|  | ||||
| 		using namespace ECode; | ||||
| 			function       = make_code(); | ||||
| 			function->Type = Function_Fwd; | ||||
| 			function->Name = get_cached_string( name.Text, name.Length ); | ||||
| 			function->add_entry( type ); | ||||
|  | ||||
| 		Code result = make_code(); | ||||
| 			if ( params ) | ||||
| 				function->add_entry( params ); | ||||
|  | ||||
| 			function.lock(); | ||||
| 		} | ||||
|  | ||||
| 		eat( TokType::Statement_End ); | ||||
|  | ||||
| 		Code | ||||
| 		result       = make_code(); | ||||
| 		result->Type = Friend; | ||||
|  | ||||
| 		if ( function ) | ||||
| 			result->add_entry( function ); | ||||
|  | ||||
| 		else | ||||
| 			result->add_entry( type ); | ||||
|  | ||||
| 		result.lock(); | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| @@ -3441,48 +3747,12 @@ namespace gen | ||||
| 			arena_init_from_allocator( & mem, heap(), kilobytes( 10 ) ); | ||||
| 		do_once_end | ||||
|  | ||||
| 		// Pretty sure its impossible to have more than this. | ||||
| 		SpecifierT specs_found[16] { ESpecifier::Num_Specifiers }; | ||||
|  | ||||
| 		u8 num_specifiers; | ||||
|  | ||||
| 		// Making all significant tokens have a max length of 128 for this parser. | ||||
| 		constexpr sw LengthID = 128; | ||||
|  | ||||
| 		struct Param | ||||
| 		{ | ||||
| 			char const Type[LengthID]; | ||||
| 			char const Name[LengthID]; | ||||
| 		}; | ||||
|  | ||||
| 		static | ||||
| 		Param Params[ 64 ] { 0 }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 		using namespace ECode; | ||||
|  | ||||
| 		Code specifiers = def_specifiers( num_specifiers, specs_found ); | ||||
|  | ||||
| 		Code params   = make_code(); | ||||
| 		// Code ret_type = def_type( ret_length, ret_type_str ); | ||||
| 		// Code body     = untyped_str( body_length, body_str ); | ||||
|  | ||||
| 		Code | ||||
| 		result       = make_code(); | ||||
| 		// result->Name = get_cached_string( name, name_length ); | ||||
| 		result->Type = Function; | ||||
| 		result = make_code(); | ||||
|  | ||||
| 		// result->add_entry( body ); | ||||
|  | ||||
| 		if ( specifiers ) | ||||
| 			result->add_entry( specifiers ); | ||||
|  | ||||
| 		// result->add_entry( ret_type ); | ||||
|  | ||||
| 		if ( params ) | ||||
| 			result->add_entry( params ); | ||||
|  | ||||
| 		result.lock(); | ||||
| 		return result; | ||||
| @@ -3530,7 +3800,7 @@ namespace gen | ||||
| 		if ( toks.Arr == nullptr ) | ||||
| 			return Code::Invalid; | ||||
|  | ||||
| 		Token* name = nullptr; | ||||
| 		Token name = { nullptr, 0, TokType::Invalid }; | ||||
|  | ||||
| 		SpecifierT specs_found[16] { ESpecifier::Num_Specifiers }; | ||||
| 		s32        num_specifiers = 0; | ||||
| @@ -3613,7 +3883,7 @@ namespace gen | ||||
| 			return Code::Invalid; | ||||
| 		} | ||||
|  | ||||
| 		name = & currtok; | ||||
| 		name = currtok; | ||||
| 		eat( TokType::Identifier ); | ||||
|  | ||||
| 		Code expr = { nullptr }; | ||||
| @@ -3639,46 +3909,7 @@ namespace gen | ||||
| 			expr = untyped_str( expr_tok.Length, expr_tok.Text ); | ||||
| 		} | ||||
|  | ||||
| 		if ( check( TokType::BraceSquare_Open ) ) | ||||
| 		{ | ||||
| 			eat( TokType::BraceSquare_Open ); | ||||
|  | ||||
| 			if ( left == 0 ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, unexpected end of typedef definition ( '[]' scope started )", txt(parse_typedef) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			if ( currtok.Type == TokType::BraceSquare_Close ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, empty array expression in typedef definition", txt(parse_typedef) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			Token | ||||
| 			untyped_tok = currtok; | ||||
|  | ||||
| 			while ( left && currtok.Type != TokType::BraceSquare_Close ) | ||||
| 			{ | ||||
| 				untyped_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)untyped_tok.Text; | ||||
| 			} | ||||
|  | ||||
| 			array_expr = untyped_str( untyped_tok.Length, untyped_tok.Text ); | ||||
|  | ||||
| 			if ( left == 0 ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, unexpected end of type definition, expected ]", txt(parse_typedef) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			if ( currtok.Type != TokType::BraceSquare_Close ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, expected ] in type definition, not %s", txt(parse_typedef), str_tok_type( currtok.Type ) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			eat( TokType::BraceSquare_Close ); | ||||
| 		} | ||||
| 		array_expr = parse_array_decl( toks, txt(parse_variable) ); | ||||
|  | ||||
| 		eat( TokType::Statement_End ); | ||||
|  | ||||
| @@ -3686,7 +3917,7 @@ namespace gen | ||||
|  | ||||
| 		Code result  = make_code(); | ||||
| 		result->Type = Variable; | ||||
| 		result->Name = get_cached_string( name->Text, name->Length ); | ||||
| 		result->Name = get_cached_string( name.Text, name.Length ); | ||||
|  | ||||
| 		result->add_entry( type ); | ||||
|  | ||||
| @@ -3742,13 +3973,14 @@ namespace gen | ||||
| 			name = currtok; | ||||
| 			eat( currtok.Type ); | ||||
|  | ||||
| 			name.Length = (  (sptr)currtok.Text + currtok.Length ) - (sptr)name.Text; | ||||
| 			name.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)name.Text; | ||||
| 			eat( TokType::Identifier ); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			name = currtok; | ||||
| 			eat( TokType::Identifier ); | ||||
| 			name = parse_identifier( toks, func_name ); | ||||
| 			if ( ! name ) | ||||
| 				return Code::Invalid; | ||||
| 		} | ||||
|  | ||||
| 		while ( left && tok_is_specifier( currtok ) ) | ||||
| @@ -3836,45 +4068,7 @@ namespace gen | ||||
| 		name = currtok; | ||||
| 		eat( TokType::Identifier ); | ||||
|  | ||||
| 		if ( check( TokType::BraceSquare_Open ) ) | ||||
| 		{ | ||||
| 			eat( TokType::BraceSquare_Open ); | ||||
|  | ||||
| 			if ( left == 0 ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, unexpected end of typedef definition ( '[]' scope started )", txt(parse_typedef) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			if ( currtok.Type == TokType::BraceSquare_Close ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, empty array expression in typedef definition", txt(parse_typedef) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			Token untyped_tok = currtok; | ||||
|  | ||||
| 			while ( left && currtok.Type != TokType::BraceSquare_Close ) | ||||
| 			{ | ||||
| 				untyped_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)untyped_tok.Text; | ||||
| 			} | ||||
|  | ||||
| 			array_expr = untyped_str( untyped_tok.Length, untyped_tok.Text ); | ||||
|  | ||||
| 			if ( left == 0 ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, unexpected end of type definition, expected ]", txt(parse_typedef) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			if ( currtok.Type != TokType::BraceSquare_Close ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, expected ] in type definition, not %s", txt(parse_typedef), str_tok_type( currtok.Type ) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			eat( TokType::BraceSquare_Close ); | ||||
| 		} | ||||
| 		array_expr = parse_array_decl( toks, txt(parse_typedef) ); | ||||
|  | ||||
| 		eat( TokType::Statement_End ); | ||||
|  | ||||
| @@ -3932,46 +4126,7 @@ namespace gen | ||||
| 			type = parse_type( toks, txt(parse_typedef) ); | ||||
| 		} | ||||
|  | ||||
| 		if ( ! is_namespace && check( TokType::BraceSquare_Open ) ) | ||||
| 		{ | ||||
| 			eat( TokType::BraceSquare_Open ); | ||||
|  | ||||
| 			if ( left == 0 ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, unexpected end of typedef definition ( '[]' scope started )", txt(parse_typedef) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			if ( currtok.Type == TokType::BraceSquare_Close ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, empty array expression in typedef definition", txt(parse_typedef) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			Token | ||||
| 			untyped_tok = currtok; | ||||
|  | ||||
| 			while ( left && currtok.Type != TokType::BraceSquare_Close ) | ||||
| 			{ | ||||
| 				untyped_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)untyped_tok.Text; | ||||
| 			} | ||||
|  | ||||
| 			array_expr = untyped_str( untyped_tok.Length, untyped_tok.Text ); | ||||
|  | ||||
| 			if ( left == 0 ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, unexpected end of type definition, expected ]", txt(parse_typedef) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			if ( currtok.Type != TokType::BraceSquare_Close ) | ||||
| 			{ | ||||
| 				log_failure( "%s: Error, expected ] in type definition, not %s", txt(parse_typedef), str_tok_type( currtok.Type ) ); | ||||
| 				return Code::Invalid; | ||||
| 			} | ||||
|  | ||||
| 			eat( TokType::BraceSquare_Close ); | ||||
| 		} | ||||
| 		array_expr = parse_array_decl( toks, txt(parse_typedef) ); | ||||
|  | ||||
| 		eat( TokType::Statement_End ); | ||||
|  | ||||
|   | ||||
| @@ -51,6 +51,8 @@ namespace gen | ||||
| 		Entry( Enum_Class )          \ | ||||
| 		Entry( Enum_Class_Fwd )      \ | ||||
| 		Entry( Execution )           \ | ||||
| 		Entry( Extern_Linkage )      \ | ||||
| 		Entry( Extern_Linkage_Body ) \ | ||||
| 		Entry( Friend )              \ | ||||
| 		Entry( Function )            \ | ||||
| 		Entry( Function_Fwd )        \ | ||||
| @@ -214,7 +216,6 @@ namespace gen | ||||
| 		Entry( API_Export,       API_Import_Code )   \ | ||||
| 		Entry( Alignas,          alignas )                                          \ | ||||
| 		Entry( Array_Decl,       "You cannot stringize an array declare this way" ) \ | ||||
| 		Entry( C_Linkage,        extern "C" )        \ | ||||
| 		Entry( Const,            const )             \ | ||||
| 		Entry( Consteval,        consteval )         \ | ||||
| 		Entry( Constexpr,        constexpr )         \ | ||||
| @@ -714,10 +715,11 @@ namespace gen | ||||
|  | ||||
| 	Code def_friend         ( Code symbol ); | ||||
| 	Code def_function       ( s32 length, char const* name, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode, Code body = NoCode ); | ||||
| 	Code def_extern_linkage ( s32 length, char const* name,                                                                         Code body ); | ||||
| 	Code def_namespace      ( s32 length, char const* name,                                                                         Code body ); | ||||
| 	Code def_operator       (             OperatorT   op,   Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode, Code body = NoCode ); | ||||
|  | ||||
| 	Code def_param          ( Code type, s32 length, char const* name ); | ||||
| 	Code def_param          ( Code type, s32 length, char const* name, Code value = NoCode ); | ||||
|  | ||||
| 	Code def_specifier      ( SpecifierT specifier ); | ||||
|  | ||||
| @@ -728,34 +730,37 @@ namespace gen | ||||
|  | ||||
| 	Code def_variable       ( Code type, s32 length, char const* name, Code value = NoCode, Code specifiers = NoCode ); | ||||
|  | ||||
| 	Code def_class_body     ( s32 num, ... ); | ||||
| 	Code def_enum_body      ( u32 num, ... ); | ||||
| 	Code def_enum_body      ( u32 num, Code* codes ); | ||||
| 	Code def_global_body    ( s32 num, ... ); | ||||
| 	Code def_global_body    ( s32 num, Code* codes ); | ||||
| 	Code def_function_body  ( s32 num, ... ); | ||||
| 	Code def_function_body  ( s32 num, Code* codes ); | ||||
| 	Code def_namespace_body ( s32 num, ... ); | ||||
| 	Code def_namespace_body ( s32 num, Code* codes ); | ||||
| 	Code def_params         ( s32 num, ... ); | ||||
| 	Code def_params         ( s32 num, Code* params ); | ||||
| 	Code def_specifiers     ( s32 num , ... ); | ||||
| 	Code def_specifiers     ( s32 num, SpecifierT* specs ); | ||||
| 	Code def_struct_body    ( s32 num, ... ); | ||||
| 	Code def_struct_body    ( s32 num, Code* codes ); | ||||
| 	Code def_class_body         ( s32 num, ... ); | ||||
| 	Code def_enum_body          ( s32 num, ... ); | ||||
| 	Code def_enum_body          ( s32 num, Code* codes ); | ||||
| 	Code def_extern_linkage_body( s32 num, ... ); | ||||
| 	Code def_extern_linkage_body( s32 num, Code* codes ); | ||||
| 	Code def_global_body        ( s32 num, ... ); | ||||
| 	Code def_global_body        ( s32 num, Code* codes ); | ||||
| 	Code def_function_body      ( s32 num, ... ); | ||||
| 	Code def_function_body      ( s32 num, Code* codes ); | ||||
| 	Code def_namespace_body     ( s32 num, ... ); | ||||
| 	Code def_namespace_body     ( s32 num, Code* codes ); | ||||
| 	Code def_params             ( s32 num, ... ); | ||||
| 	Code def_params             ( s32 num, Code* params ); | ||||
| 	Code def_specifiers         ( s32 num , ... ); | ||||
| 	Code def_specifiers         ( s32 num, SpecifierT* specs ); | ||||
| 	Code def_struct_body        ( s32 num, ... ); | ||||
| 	Code def_struct_body        ( s32 num, Code* codes ); | ||||
| #	pragma endregion Upfront | ||||
|  | ||||
| #	pragma region Incremental | ||||
| #	ifdef GEN_FEATURE_INCREMENTAL | ||||
| 	Code make_class       ( s32 length,     char const* name, Code parent = NoCode,                                Code specifiers = NoCode ); | ||||
| 	Code make_enum        ( s32 length,     char const* name, Code type   = NoCode, EnumT specifier = EnumRegular ); | ||||
| 	Code make_function    ( s32 length,     char const* name, Code params = NoCode, Code  ret_type  = NoCode,      Code specifiers = NoCode ); | ||||
| 	Code make_global_body ( s32 length = 1, char const* name = "", s32 num = 0, ... ); | ||||
| 	Code make_namespace   ( s32 length,     char const* name ); | ||||
| 	Code make_operator    (                 OperatorT   op,   Code params = NoCode, Code  ret_type  = NoCode,      Code specifiers = NoCode ); | ||||
| 	Code make_params      (); | ||||
| 	Code make_specifiers  (); | ||||
| 	Code make_struct      ( s32 length,     char const* name, Code parent = NoCode,                                Code specifiers = NoCode ); | ||||
| 	Code make_class         ( s32 length,     char const* name, Code parent = NoCode,                                Code specifiers = NoCode ); | ||||
| 	Code make_enum          ( s32 length,     char const* name, Code type   = NoCode, EnumT specifier = EnumRegular ); | ||||
| 	Code make_extern_linkage( s32 length,     char const* name ); | ||||
| 	Code make_function      ( s32 length,     char const* name, Code params = NoCode, Code  ret_type  = NoCode,      Code specifiers = NoCode ); | ||||
| 	Code make_global_body   ( s32 length = 1, char const* name = "" ); | ||||
| 	Code make_namespace     ( s32 length,     char const* name ); | ||||
| 	Code make_operator      (                 OperatorT   op,   Code params = NoCode, Code  ret_type  = NoCode,      Code specifiers = NoCode ); | ||||
| 	Code make_params        (); | ||||
| 	Code make_specifiers    (); | ||||
| 	Code make_struct        ( s32 length,     char const* name, Code parent = NoCode,                                Code specifiers = NoCode ); | ||||
| #	endif | ||||
| #	pragma endregion Incremental | ||||
|  | ||||
| @@ -763,7 +768,6 @@ namespace gen | ||||
| 	#ifdef GEN_FEATURE_PARSING | ||||
| 	Code parse_class      ( s32 length, char const* class_def     ); | ||||
| 	Code parse_enum       ( s32 length, char const* enum_def      ); | ||||
| 	Code parse_execution  ( s32 length, char const* exec_def      ); | ||||
| 	Code parse_friend     ( s32 length, char const* friend_def    ); | ||||
| 	Code parse_function   ( s32 length, char const* fn_def        ); | ||||
| 	Code parse_global_body( s32 length, char const* body_def      ); | ||||
| @@ -1007,28 +1011,29 @@ namespace gen | ||||
|  | ||||
| // Upfront | ||||
|  | ||||
| #	define class( Name_, ... )           gen::def_class( txt_n_len(Name_), __VA_ARGS__ ) | ||||
| #	define enum( Name_, Type_, Body_ )   gen::def_enum ( txt_n_len(Name_), type_ns(Type_), Body_ ) | ||||
| #	define class( Name_, ... )            gen::def_class( txt_n_len(Name_), __VA_ARGS__ ) | ||||
| #	define enum( Name_, Type_, Body_ )    gen::def_enum ( txt_n_len(Name_), type_ns(Type_), Body_ ) | ||||
|  | ||||
| #	define function( ... )               macrofn_polymorphic( function, __VA_ARGS__ ) | ||||
| #	define namespace( Name_, Body_ )     gen::def_namespace      ( txt_n_len(Name_),  Body_ ) | ||||
| #	define operator( Op_, ... )          macrofn_polymorphic( operator, __VA_ARGS__ ) | ||||
| #	define params( ... )                 macrofn_polymorphic( params, __VA_ARGS__ ) | ||||
| #	define specifiers( ... )             gen::def_specifiers     ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define struct( Name_, ... )          gen::def_struct         ( txt_n_len(Name_), __VA_ARGS__ ) | ||||
| #	define variable( Type_, Name_, ... ) gen::def_variable       ( type_ns(Type_), txt_n_len(Name_), __VA_ARGS__ ) | ||||
| #	define type( Value_, ... )           gen::def_type           ( txt_n_len(Value_), __VA_ARGS__ ) | ||||
| #	define type_fmt( Fmt_, ... )         gen::def_type           ( bprintf( Fmt_, __VA_ARGS__ ) ) | ||||
| #	define using( Name_, Type_ )		 gen::def_using          ( txt_n_len(Name_), type_ns(Type_) ) | ||||
| #	define using_namespace( Name_ )      gen::def_using_namespace( txt_n_len(Name_) ) | ||||
| #	define extern_linkage( Name_, Body_ ) gen::def_extern_linkage( txt_n_len(Name_), Body_ ) | ||||
| #	define function( ... )                macrofn_polymorphic( function, __VA_ARGS__ ) | ||||
| #	define namespace( Name_, Body_ )      gen::def_namespace      ( txt_n_len(Name_),  Body_ ) | ||||
| #	define operator( Op_, ... )           macrofn_polymorphic( operator, __VA_ARGS__ ) | ||||
| #	define params( ... )                  macrofn_polymorphic( params, __VA_ARGS__ ) | ||||
| #	define specifiers( ... )              gen::def_specifiers     ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define struct( Name_, ... )           gen::def_struct         ( txt_n_len(Name_), __VA_ARGS__ ) | ||||
| #	define variable( Type_, Name_, ... )  gen::def_variable       ( type_ns(Type_), txt_n_len(Name_), __VA_ARGS__ ) | ||||
| #	define type( Value_, ... )            gen::def_type           ( txt_n_len(Value_), __VA_ARGS__ ) | ||||
| #	define type_fmt( Fmt_, ... )          gen::def_type           ( bprintf( Fmt_, __VA_ARGS__ ) ) | ||||
| #	define using( Name_, Type_ )		  gen::def_using          ( txt_n_len(Name_), type_ns(Type_) ) | ||||
| #	define using_namespace( Name_ )       gen::def_using_namespace( txt_n_len(Name_) ) | ||||
|  | ||||
| #	define class_body(      ... )        gen::def_class_body    ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define enum_body(       ... )        gen::def_enum_body     ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define global_body(     ... )        gen::def_global_body   ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define function_body(   ... )        gen::def_function_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define namespace_body(  ... )        gen::def_namespace_body( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define operator_body(   ... )        gen::def_operator_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define struct_body(     ... )        gen::def_struct_body   ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define class_body(      ... )         gen::def_class_body    ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define enum_body(       ... )         gen::def_enum_body     ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define global_body(     ... )         gen::def_global_body   ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define function_body(   ... )         gen::def_function_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define namespace_body(  ... )         gen::def_namespace_body( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define operator_body(   ... )         gen::def_operator_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define struct_body(     ... )         gen::def_struct_body   ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
|  | ||||
| #	ifdef GEN_FEATURE_INCREMENTAL | ||||
| // Incremental | ||||
|   | ||||
		Reference in New Issue
	
	Block a user