// 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"); }
// 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; }
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(""); } } } } }