bool expr_object(pass_opt_t* opt, ast_t** astp) { ast_t* ast = *astp; bool ok = true; AST_GET_CHILDREN(ast, cap, provides, members); ast_clearflag(cap, AST_FLAG_PRESERVE); ast_clearflag(provides, AST_FLAG_PRESERVE); ast_clearflag(members, AST_FLAG_PRESERVE); ast_t* annotation = ast_consumeannotation(ast); const char* c_id = package_hygienic_id(&opt->check); ast_t* t_params; ast_t* t_args; collect_type_params(ast, &t_params, &t_args); const char* nice_id = (const char*)ast_data(ast); if(nice_id == NULL) nice_id = "object literal"; // Create a new anonymous type. BUILD(def, ast, NODE(TK_CLASS, AST_SCOPE ANNOTATE(annotation) NICE_ID(c_id, nice_id) TREE(t_params) NONE TREE(provides) NODE(TK_MEMBERS) NONE NONE)); // We will have a create method in the type. BUILD(create, members, NODE(TK_NEW, AST_SCOPE NONE ID("create") NONE NODE(TK_PARAMS) NONE NONE NODE(TK_SEQ, NODE(TK_TRUE)) NONE NONE)); BUILD(type_ref, ast, NODE(TK_REFERENCE, ID(c_id))); if(ast_id(t_args) != TK_NONE) { // Need to add type args to our type reference BUILD(t, ast, NODE(TK_QUALIFY, TREE(type_ref) TREE(t_args))); type_ref = t; } ast_free_unattached(t_args); // We will replace object..end with $0.create(...) BUILD(call, ast, NODE(TK_CALL, NODE(TK_POSITIONALARGS) NONE NONE NODE(TK_DOT, TREE(type_ref) ID("create")))); ast_t* create_params = ast_childidx(create, 3); ast_t* create_body = ast_childidx(create, 6); ast_t* call_args = ast_child(call); ast_t* class_members = ast_childidx(def, 4); ast_t* member = ast_child(members); bool has_fields = false; bool has_behaviours = false; while(member != NULL) { switch(ast_id(member)) { case TK_FVAR: case TK_FLET: case TK_EMBED: { add_field_to_object(opt, member, class_members, create_params, create_body, call_args); has_fields = true; break; } case TK_BE: // If we have behaviours, we must be an actor. ast_append(class_members, member); has_behaviours = true; break; default: // Keep all the methods as they are. ast_append(class_members, member); break; } member = ast_sibling(member); } // Add the create function at the end. ast_append(class_members, create); // Add new type to current module and bring it up to date with passes. ast_t* module = ast_nearest(ast, TK_MODULE); ast_append(module, def); // Turn any free variables into fields. ast_t* captures = ast_from(ast, TK_MEMBERS); ast_t* last_capture = NULL; if(!capture_from_type(opt, *astp, &def, captures, &last_capture)) ok = false; for(ast_t* p = ast_child(captures); p != NULL; p = ast_sibling(p)) { add_field_to_object(opt, p, class_members, create_params, create_body, call_args); has_fields = true; } ast_free_unattached(captures); ast_resetpass(def, PASS_SUGAR); // Handle capability and whether the anonymous type is a class, primitive or // actor. token_id cap_id = ast_id(cap); if(has_behaviours) { // Change the type to an actor. ast_setid(def, TK_ACTOR); if(cap_id != TK_NONE && cap_id != TK_TAG) { ast_error(opt->check.errors, cap, "object literals with behaviours are " "actors and so must have tag capability"); ok = false; } cap_id = TK_TAG; } else if(!has_fields && (cap_id == TK_NONE || cap_id == TK_TAG || cap_id == TK_BOX || cap_id == TK_VAL)) { // Change the type from a class to a primitive. ast_setid(def, TK_PRIMITIVE); cap_id = TK_VAL; } if(ast_id(def) != TK_PRIMITIVE) pony_assert(!ast_has_annotation(def, "ponyint_bare")); // Reset constructor to pick up the correct defaults. ast_setid(ast_child(create), cap_id); ast_t* result = ast_childidx(create, 4); ast_replace(&result, type_for_class(opt, def, result, cap_id, TK_EPHEMERAL, false)); // Catch up provides before catching up the entire type. if(!catch_up_provides(opt, provides)) return false; // Type check the anonymous type. if(!ast_passes_type(&def, opt, PASS_EXPR)) return false; // Replace object..end with $0.create(...) ast_replace(astp, call); if(ast_visit(astp, pass_syntax, NULL, opt, PASS_SYNTAX) != AST_OK) return false; if(!ast_passes_subtree(astp, opt, PASS_EXPR)) return false; return ok; }
JSON_OBJECT stu_to_json(JSON_OBJECT json,void *data,T_PkgType * typ,const char *choose,char *colidx) { int i,colnum,n; T_PkgType *tp; char buf[100]; const char *cp; if(!json) return json; colnum=set_offset(typ); tp=typ; if(!choose||!*choose) { // 没有选择,全部加入 for(i=0;tp->type>=0;i++,tp++) { if(tp->bindtype & NOSELECT) continue; if(choose&&isnull((char *)data+tp->offset,tp->type)) continue; if(tp->type==CH_STRUCT) { JSON_OBJECT sub=json_object_new_object(); stu_to_json(sub,(char *)data+tp->offset, (T_PkgType *)tp->format,0,0); json_object_object_add(json,plain_name(tp->name),sub); continue; } add_field_to_object(json,data,tp); } return json; } cp=choose; do { char *p; *buf=0; cp=stptok(skipblk((char *)cp),buf,sizeof(buf),",|"); //可以用的分隔符 p=buf; TRIM(p); if(!*p) continue; if(isdigit(*p)) { //数字选择,字段号范围:"1-3,6-11" int ret,beg,end; end=beg=-1; ret=sscanf(buf,"%d - %d",&beg,&end); if(!ret) continue; if(ret==1) end=beg; if(end<beg) end=beg; for(ret=beg;ret<=end;ret++) { if(typ[ret].type==CH_STRUCT) { JSON_OBJECT sub=json_object_new_object(); stu_to_json(sub,(char *)data+typ[ret].offset, (T_PkgType *)typ[ret].format,0,0); json_object_object_add(json,plain_name(typ[ret].name),sub); continue; } add_field_to_object(json,data,&typ[ret]); } } else { //字母,字段名 :"colname1,colname2,..." n=index_col(colidx,colnum,p,typ); if(n<0) continue; if(typ[n].type==CH_STRUCT) { JSON_OBJECT sub=json_object_new_object(); stu_to_json(sub,(char *)data+typ[n].offset, (T_PkgType *)typ[n].format,0,0); json_object_object_add(json,plain_name(typ[n].name),sub); continue; } add_field_to_object(json,data,typ+n); } } while(*cp++); return json; }