import os import sys import dataclasses LAMBDA_INDEX=0 TMP_DIR="build" @dataclasses.dataclass class fun_name_t: name:str return_type:str params:list body:str # 判断是否需要重新生成 def check_rebuild(dst:str,src:list): if(not os.path.exists(dst)): return True dst_time=os.path.getmtime(dst) src_time=[] for i in src: src_time.append(os.path.getmtime(i)) src_time.sort() if(src_time[-1]>dst_time): return True return False def find_closed(text:str,par:tuple=('(',')')): count_left=0 count_right=0 for i in range(len(text)): if(text[i]==par[0]): count_left+=1 elif(text[i]==par[1]): count_right+=1 if(count_left==0): continue if(count_left==count_right): # print(f"count_left={count_left} count_right={count_right}") return i+1 # print(f"count_left={count_left} count_right={count_right}") return 0 # 找到lambda字符 def calc_lambda_text(text:str): lambda_list=[] while True: index=text.find("lambda(") if(index==-1): break # print(f"index={index}") lenght=find_closed(text[index:]) if(lenght>0): lambda_list.append(text[index:index+lenght]) text=text[index+lenght:] else: break return lambda_list # 根据lambda字符生成函数名 def create_lambda(text:str): global LAMBDA_INDEX text=text.replace("lambda(","")[:-1] # 去掉lambda和首末括号 fun_name=f"__lambda_{LAMBDA_INDEX}" LAMBDA_INDEX+=1 return_type=text[:text.find("(")] # 有","则至少有两个参数否则可能有一个参数,可能没有 param_str=text[text.find("(")+1:text.find(")")] params=[] if(param_str.count(',')>0): params=param_str.split(',') for i in range(len(params)): params[i]=params[i].strip() else: t_str=param_str.strip() if(len(t_str)>0)and(t_str!="void"): params.append(t_str) body_start=text.find("{")+1 body_end=find_closed(text,('{','}'))-1 return fun_name_t(fun_name,return_type,params,text[body_start:body_end]) # 生成lambda展开后的文件 返回新的源文件列表 def search_lambda(src_list:list) -> list: for index,item in enumerate(src_list): with open(item,encoding='utf-8') as f: d=f.read() if(d.count("lambda_use")!=1): continue lam_index=d.find("lambda_use") # 如果标签不在一行的开头 视为不使用lambda if(lam_index!=0 and d[lam_index-1]!='\n'): continue # 获取lambda文件名 base_path=os.path.join(TMP_DIR,os.path.dirname(item)) if not os.path.exists(base_path): os.makedirs(base_path) dst_file_name=os.path.join(base_path, os.path.basename(item)) src_list[index]=dst_file_name # 不需要重新生成lambda文件 if(not check_rebuild(dst_file_name,[item])): continue lam_list=calc_lambda_text(d) lambda_funs=[] for lam in lam_list: lambda_funs.append(create_lambda(lam)) print(f"生成 {dst_file_name}") with open(dst_file_name,mode='w+',encoding='utf-8') as f: lambda_funs_text="" for lam,fun in zip(lam_list,lambda_funs): lambda_funs_text+=f"static {fun.return_type} {fun.name}({','.join(fun.params)}){'{'}{fun.body}{'}'}\n" d=d.replace(lam,fun.name) d=d.replace("lambda_use",lambda_funs_text) f.write(d) return src_list if __name__=="__main__": t=search_lambda(sys.argv[1:]) print(t)