bool expr_field(pass_opt_t* opt, ast_t* ast) { AST_GET_CHILDREN(ast, id, type, init); // An embedded field must have a known, non-actor type. if(ast_id(ast) == TK_EMBED) { if(!is_known(type) || is_actor(type)) { ast_error(ast, "embedded fields must always be primitives or classes"); return false; } } if(ast_id(init) != TK_NONE) { // Initialiser type must match declared type. if(!coerce_literals(&init, type, opt)) return false; ast_t* init_type = ast_type(init); if(is_typecheck_error(init_type)) return false; init_type = alias(init_type); if(!is_subtype(init_type, type)) { ast_error(init, "field/param initialiser is not a subtype of the field/param type"); ast_error(type, "field/param type: %s", ast_print_type(type)); ast_error(init, "initialiser type: %s", ast_print_type(init_type)); ast_free_unattached(init_type); return false; } // If it's an embedded field, check for a constructor result. if(ast_id(ast) == TK_EMBED) { if((ast_id(init) != TK_CALL) || (ast_id(ast_childidx(init, 2)) != TK_NEWREF)) { ast_error(ast, "an embedded field must be initialised using a constructor"); return false; } } ast_free_unattached(init_type); } ast_settype(ast, type); return true; }
bool Grammar::is_statement(const std::string& str) { std::string trimmed_str = str_utils::trim(str); if (trimmed_str.size() == 0 || trimmed_str[int(trimmed_str.size()) - 1] != ';') return false; trimmed_str = str_utils::rtrim(trimmed_str.substr(0, int(trimmed_str.size()) - 1)); for (int i = 0; i < int(trimmed_str.size()); i++) if (str_utils::is_space(trimmed_str[i]) && is_actor(trimmed_str.substr(0, i))) { std::string message = str_utils::ltrim(trimmed_str.substr(i + 1)); return (is_unary_message(message) || is_keyword_message(message)); } return false; }
bool is_actor(ast_t* type) { switch(ast_id(type)) { case TK_TUPLETYPE: return false; case TK_UNIONTYPE: { ast_t* child = ast_child(type); while(child != NULL) { if(!is_actor(child)) return false; child = ast_sibling(child); } return true; } case TK_ISECTTYPE: { ast_t* child = ast_child(type); while(child != NULL) { if(is_actor(child)) return true; child = ast_sibling(child); } return false; } case TK_NOMINAL: { ast_t* def = (ast_t*)ast_data(type); switch(ast_id(def)) { case TK_INTERFACE: case TK_TRAIT: case TK_PRIMITIVE: case TK_CLASS: return false; case TK_ACTOR: return true; default: {} } break; } case TK_ARROW: return is_actor(ast_childidx(type, 1)); case TK_TYPEPARAMREF: { ast_t* def = (ast_t*)ast_data(type); ast_t* constraint = ast_childidx(def, 1); return is_actor(constraint); } default: {} } assert(0); return false; }