示例#1
0
bool prism::resolve::types_match( sooty::const_parseme_ptr_ref lhsi, sooty::const_parseme_ptr_ref rhsi )
{
	ATMA_ASSERT(lhsi && rhsi);
	sooty::parseme_ptr lhs = type_of(lhsi);
	sooty::parseme_ptr rhs = type_of(rhsi);
	
	if (lhs->id == ID::any_type || rhs->id == ID::any_type)
		return true;
	
	// pointers and arrays are different!
	if (lhs->id == ID::pointer_type)
		return rhs->id == ID::pointer_type && types_match(marshall::pointer_type::pointee_type(lhs), marshall::pointer_type::pointee_type(rhs));
	else if (lhs->id == ID::array_type)
		return rhs->id == ID::array_type && types_match(marshall::array_type::type(lhs), marshall::array_type::type(rhs));
	else if (lhs->id == ID::reference_type)
		return rhs->id == ID::reference_type && types_match(marshall::array_type::type(lhs), marshall::array_type::type(rhs));
		
	if (rhs->id == ID::pointer_type || rhs->id == ID::array_type || rhs->id == ID::reference_type)
		return false;
	
	ATMA_ASSERT(rhs->id == ID::type_definition);
	return marshall::type_definition::name(lhs)->value.string == marshall::type_definition::name(rhs)->value.string;
}
示例#2
0
bool prism::resolve::type_can_convert_to( sooty::const_parseme_ptr_ref lhsi, sooty::const_parseme_ptr_ref rhsi )
{
	ATMA_ASSERT(lhsi && rhsi);
	sooty::parseme_ptr lhs = type_of(lhsi);
	sooty::parseme_ptr rhs = type_of(rhsi);
	
	if (lhs->id == ID::reference_type)
		if (rhs->id == ID::reference_type)
			return types_match(lhs->children.front(), rhs->children.front());
		else
			return types_match(lhs->children.front(), rhs);
	else
		if (rhs->id == ID::reference_type)
			return types_match(lhs, rhs->children.front());
		else
			return types_match(lhs, rhs);
}
示例#3
0
void prism::semantic_analysis::analyse::member_function_call(semantic_info& si, sooty::parseme_ptr_ref call)
{
	sooty::parseme_ptr_ref argument_list = marshall::member_function_call::argument_list(call);
	ATMA_ASSERT( !argument_list->children.empty() );
	std::for_each(argument_list->children.begin() + 1, argument_list->children.end(), boost::bind(&expression, boost::ref(si), _1) );
	
	// lookup type-definition
	sooty::parseme_ptr type_definition = resolve::type_of(marshall::member_function_call::argument_list(call)->children[0]);
	if (type_definition->id == ID::reference_type) {
		type_definition = resolve::type_of(type_definition->children.front());
	}
	
	// find all matching function definitions
	sooty::parseme_container matching_functions;
	sooty::depth_first_copy_if(std::back_inserter(matching_functions), type_definition, resolve::function_matches_function_call_pred(call));
	if (matching_functions.empty()) {
		++si.errors;
		std::cerr << error(call, "no function found for function-call:\n\t") << undecorated_function_call(call) << std::endl;
		return;
	}
	else if (matching_functions.size() > 1) {
		++si.errors;
		std::cerr << error(call, "too many definitions found!") << std::endl;
		return;
	}
	
	// sort the functions from most applicable to least
	std::sort(matching_functions.begin(), matching_functions.end(), prism::depth_pred());

	// take the most applicable and make sure that it's the only one of its kind. if it's not,
	// that means we have an ambiguity, and that's too bad
	std::pair<sooty::parseme_container::iterator, sooty::parseme_container::iterator> bounds =
		std::equal_range(matching_functions.begin(), matching_functions.end(), matching_functions.front(), prism::depth_pred());
	if ( std::distance(bounds.first, bounds.second) != 1 )
		return;

	// increase the use-count of the function
	++marshall::function::semantics::use_count(matching_functions.front()).integer;
}
示例#4
0
void prism::semantic_analysis::analyse::expression(semantic_info& si, sooty::parseme_ptr_ref N)
{
	switch (N->id)
	{
		case ID::add:
		case ID::sub:
		case ID::mul:
		case ID::div:
		case ID::equ:
		case ID::intrinsic_int_add:
		case ID::intrinsic_int_sub:
		case ID::intrinsic_int_mul:
		case ID::intrinsic_int_div:
		case ID::intrinsic_int_eq:
			expression( si, marshall::binary_expression::lhs(N) );
			expression( si, marshall::binary_expression::rhs(N) );
			if (!resolve::types_match( marshall::binary_expression::lhs(N), marshall::binary_expression::rhs(N) )) {
				std::cerr << error(N, "arguments are not the same type!");
				++si.errors;
			}
			break;
		
		case ID::dereference:
		case ID::address_of:
			expression(si, N->children.front());
			break;
		
		case ID::index_operator:
		{
			// expression of lhs (something), and rhs (the index)
			sooty::parseme_ptr lhs = marshall::binary_expression::lhs(N);
			expression(si, lhs);
			expression(si, marshall::binary_expression::rhs(N));
			
			// find out the resultant type. currently we only support arrays and pointers.
			// in the future we'll support user-defined types having the member operator
			sooty::parseme_ptr lhs_type = resolve::type_of(lhs);
			sooty::const_parseme_ptr_ref lhs_type_structure = resolve::type_structure_of(lhs_type);
			ATMA_ASSERT(lhs_type_structure->id == ID::array_type || lhs_type_structure->id == ID::pointer_type);
			break;
		}
		
		case ID::new_:
			type(si, marshall::new_::type(N));
			std::for_each(
				marshall::new_::arguments(N)->children.begin(),
				marshall::new_::arguments(N)->children.end(),
				boost::bind(analyse::expression, boost::ref(si), _1)
			);
			break;
		
		case ID::member_operator:
		{
			sooty::parseme_ptr_ref lhs = marshall::binary_expression::lhs(N);
			sooty::parseme_ptr_ref rhs = marshall::binary_expression::rhs(N);
			
			// lhs is an expression, rhs is an identifier (which we *don't* want to expand)
			expression(si, lhs);
			
			// rhs! we need to find get the type-definition of the lhs and find the rhs's type in it
			ATMA_ASSERT( rhs->id == ID::identifier );
			sooty::parseme_ptr lhs_type = resolve::type_of(lhs);
			
			// references are okay!
			if (lhs_type->id == ID::reference_type)
				lhs_type = resolve::type_of(lhs_type->children.front());
			
			sooty::parseme_ptr lhs_members = marshall::type_definition::members(lhs_type);
			
			ATMA_ASSERT( lhs_members->id == ID::member_definitions );
			for (sooty::parseme_container::const_iterator i = lhs_members->children.begin(); i != lhs_members->children.end(); ++i)
			{
				sooty::const_parseme_ptr_ref member = *i;
				if (member->id == ID::variable_definition)
				{
					if ( marshall::variable_definition::name(member)->value.string == marshall::identifier::name(rhs)->value.string ) {
						// find the type-definition for this variable-definition
						sooty::parseme_ptr member_td = marshall::variable_definition::type(member);
						if (member_td->id == ID::reference_type) {
							sooty::parseme_ptr old_N = N;
							N = sooty::make_parseme(N->parent.lock(), ID::un_reference);
							N->children.push_back(old_N);
							old_N->parent = N;
						}
					}
				}
			}
			break;
		}
		
		case ID::identifier:
		{
			sooty::parseme_ptr P = resolve::identifier_to_variable_definition(N);
			if (!P) {
				++si.errors;
				std::cerr << "error (" << N->position << "): identifier " << N->value.string << " is unknown" << std::endl;
			}
			
			if ( resolve::type_of(N)->id == ID::reference_type ) {
				sooty::parseme_ptr us = N;
				N = sooty::make_parseme(us->parent.lock(), ID::un_reference, sooty::value_t());
				N->children.push_back(us);
			}
			
			break;
		}
		
		case ID::member_function_call:
		{
			member_function_call(si, N);
			break;
		}
		
		case ID::function_call:
		{
			function_call(si, N);
			break;
		}
	}
}
示例#5
0
//=====================================================================
// type_of
//=====================================================================
sooty::parseme_ptr prism::resolve::type_of(sooty::const_parseme_ptr_ref N)
{
	ATMA_ASSERT(N);
	
	switch (N->id)
	{
		// intrinsics
		case ID::int_type:
		case ID::real_type:
		case ID::bool_type:
		case ID::void_type:
		case ID::pointer_type:
		case ID::array_type:
		case ID::reference_type:
		case ID::any_type:
			return N;
		
		case ID::bitwidth:
			//return type_of( prism::synthesize::type_identifier(N, "bitwidth_type") );
			return prism::resolve::bitwidth_type(N);
		
		case ID::identifier:
		{
			sooty::parseme_ptr D = prism::resolve::identifier_to_variable_definition(N);
			ATMA_ASSERT(D);
			if (!D)
				return type_of( prism::resolve::identifier_to_variable_definition(N) );
			else
				return type_of(D);
		}
		
		case ID::type_identifier:
		{
			//return type_definition_of(N);
			sooty::parseme_ptr result = marshall::type_identifier::semantics::type_definition(N).parseme;
			ATMA_ASSERT(result);
			return result;
		}
		
		case ID::type_definition:
			return N;
		
		case ID::dereference:
		{
			sooty::parseme_ptr p = type_of(N->children[0]);
			ATMA_ASSERT(p->id == ID::pointer_type);
			return type_of(p->children[0]);
		}

		case ID::int_literal:
			return type_of( synthesize::int_type(N) );
		
		case ID::real_literal:
			return type_of( synthesize::real_type(N) );
		
		case ID::bool_literal:
			return synthesize::bool_type(N);
		
		case ID::string_literal:
			return synthesize::string_type(N);
			
		case ID::eq_operator:
			return type_of( N->children[0] );
		
		case ID::add_operator:
		case ID::function:
			return type_of( marshall::function::return_type(N) );
			
		case ID::function_call:
			return type_of( sooty::upwards_bredth_first_find_first_if(N, resolve::function_matches_function_call_pred(N)) );
		
		case ID::member_function_call:
			return resolve::function_of_member_function_call( N );
		
		case ID::variable_definition:
			return type_of( marshall::variable_definition::type(N) );
		
		case ID::parameter:
			return type_of( marshall::parameter::type(N) );
		
		case ID::un_reference:
			return type_of( N->children.front() );
		
		case ID::address_of:
		{
			// we need to synthesize a new type
			sooty::parseme_ptr childtype = type_of(N->children[0]);
			sooty::parseme_ptr ptype = sooty::parseme::create( sooty::parseme_ptr(), ID::pointer_type, sooty::value_t(), sooty::lexical_position() );
			ptype->children.push_back(childtype);
			return ptype;
		}
		
		case ID::new_:
		{
			// we need to synthesize a new type
			sooty::parseme_ptr childtype = type_of(N->children[0]);
			sooty::parseme_ptr ptype = sooty::parseme::create( sooty::parseme_ptr(), ID::pointer_type, sooty::value_t(), sooty::lexical_position() );
			ptype->children.push_back(childtype);
			return ptype;
		}
		
		
		case ID::add:
		case ID::sub:
		case ID::mul:
		case ID::div:
		case ID::equ:
			return type_of( marshall::binary_expression::lhs(N) );
		
		// expression of lhs (something), and rhs (the index)
		case ID::index_operator:
		{
			// currently we only support arrays and pointers. in the future we'll support
			// user-defined types having the member operator
			sooty::parseme_ptr lhs = marshall::binary_expression::lhs(N);
			sooty::parseme_ptr lhs_type = resolve::type_of(lhs);
			sooty::const_parseme_ptr_ref lhs_type_structure = resolve::type_structure_of(lhs_type);
			ATMA_ASSERT(lhs_type_structure->id == ID::array_type || lhs_type_structure->id == ID::pointer_type);
			
			if (lhs_type_structure->id == ID::pointer_type) {
				return resolve::type_of(marshall::pointer_type::pointee_type(lhs_type_structure));
			}
			else if (lhs_type_structure->id == ID::array_type) {
				return resolve::type_of(marshall::array_type::type(lhs_type_structure));
			}
			
			ATMA_HALT("bad!");
			return sooty::parseme_ptr();
		}
		
		
		case ID::member_operator:
		{
			sooty::const_parseme_ptr_ref lhs = marshall::binary_expression::lhs(N);
			sooty::const_parseme_ptr_ref rhs = marshall::binary_expression::rhs(N);

			// lhs! find its type-structure
			sooty::parseme_ptr lhs_type = resolve::type_of(lhs, resolve::remove_refs());
			ATMA_ASSERT(lhs_type);
			
			// rhs! we need to find get the type-definition of the lhs and find the rhs's type in it
			ATMA_ASSERT( rhs->id == ID::identifier );
			const std::string& rhs_identifier = marshall::binary_expression::rhs(N)->value.string;
			sooty::parseme_ptr member = resolve::member_of_type_definition( lhs_type, rhs_identifier );
			if (member)
				return resolve::type_of(member);
			
			ATMA_HALT("bad!");
			return sooty::parseme_ptr();
		}
		
		case ID::intrinsic_int_add:
		case ID::intrinsic_int_sub:
		case ID::intrinsic_int_mul:
		case ID::intrinsic_int_div:
			return type_of(synthesize::int_type(N));
		
		default: 
		{
			ATMA_ASSERT(false && "not defined");
			return sooty::parseme_ptr();
		}
	}
}