示例#1
0
// In an assignment expression, the left operand shall
// refer to a mutable object. The types of the left and
// right operands shall match.
//
// TODO: If we have const types, then we'd have to add this
// checking.
void
Elaborator::elaborate(Assign_stmt* s)
{
  // FIXME: Write a better predicate?
  Expr* lhs = elaborate(s->object());
  if (!is<Reference_type>(lhs->type()))
    throw Type_error({}, "assignment to rvalue");

  // Apply rvalue conversion to the value and update the
  // expression.
  Expr *rhs = require_value(*this, s->second);

  // The types shall match. Compare t1 using the non-reference
  // type of the object.
  Type const* t1 = lhs->type()->nonref();
  Type const* t2 = rhs->type();
  if (t1 != t2)
    throw Type_error({}, "assignment to an object of a different type");
}
示例#2
0
// The target function operand is converted to
// an rvalue and shall have funtion type.
Expr*
Elaborator::elaborate(Call_expr* e)
{
  // Apply lvalue to rvalue conversion and ensure that
  // the target has function type.
  Expr* f = require_value(*this, e->first);
  Type const* t1 = f->type();
  if (!is<Function_type>(t1))
    throw Type_error({}, "cannot call to non-function");
  Function_type const* t = cast<Function_type>(t1);

  // Check for basic function arity.
  Type_seq const& parms = t->parameter_types();
  Expr_seq& args = e->arguments();
  if (args.size() < parms.size())
    throw Type_error({}, "too few arguments");
  if (parms.size() < args.size())
    throw Type_error({}, "too many arguments");

  // Check that each argument conforms to the the
  // parameter.
  for (std::size_t i = 0; i < parms.size(); ++i) {
    Type const* p = parms[i];
    Expr* a = require_converted(*this, args[i], p);
    if (!a) {
      std::stringstream ss;
      ss << "type mismatch in argument " << i + 1 << '\n';
      throw Type_error({}, ss.str());
    }
  }

  // The type of the expression is that of the
  // function return type.
  e->type(t->return_type());

  return e;
}
示例#3
0
void command_line_parser::parse_options(void)
{
	while(const char* token = m_command_line.peek())
	{
		if (*token != '-')
			break;
		std::string param(m_command_line.read());
		logger().trace(corecpp::concat<std::string>({"parsing ", param}), __FILE__, __LINE__);
		if (param.substr(0,2) == "--")
		{
			std::string value = "";
			auto pos = param.find('=');
			if(pos == std::string::npos)
			{
				//param with no value => value is let to an empty string
				param = param.substr(2);
			}
			else
			{
				value = param.substr(pos);
				param = param.substr(2, param.length() - 2 - pos);
			}
			auto option = get_option(param);
			if (option == m_options.end())
				throw std::invalid_argument(param);
			if (option->require_value() && (pos == std::string::npos))
				throw value_error(param);
			option->read(value);
		}
		else if (param[0] == '-')
		{
			param = param.substr(1);
			const char* value = m_command_line.peek();
			if(value && *value == '-') //another option
				value = nullptr;
			//for loop because we can have multiple params
			for(auto iter = param.begin(); iter != param.end(); )
			{
				char shortname = *iter;
				auto option = get_option(shortname);
				if(option == m_options.end())
					throw std::invalid_argument(std::string(1, shortname));

				if (++iter == param.end())//last option => must give the value to it
				{
					if (!value && option->require_value())
						throw value_error(param);
					if (option->require_value())
					{
						value = m_command_line.read(); //consume the parameter
						option->read(value);
					}
					else
						option->read("");
				}
				else //not the last parameter => should not need a value
				{
					if (option->require_value())
						throw value_error(param);
					option->read("");
				}
			}
		}
	}
}