//-*-java-*- CodeFrag { void resolveVars(Weaver big) to {VarAssignment,VarVisibility,VarModifiers,VarDataType,VarMethodBody,VarPackage} { {{ FixVisibility vis_var; FixModifiers mod_var; FixDataType ret_var; JavaCode body_var; FixPackage pack_var; }} before VarAssignment {{ Var.assign(host.get_symbol(), host.get_rvalue(), big); }} before AddClass {{ pack_var = null; }} after AddClass {{ /* * Empty package is stored as an empty collection in the symboltable, * but as null in the syntax tree (because of type information). */ if(pack_var != null) host.set_pack(pack_var.isEmpty() ? null : pack_var); }} before {ClassMethod,InterfaceMethod} {{ vis_var = null; mod_var = null; ret_var = null; body_var = null; }} after ClassMethod {{ /* * Empty modifiers are also stored as an empty collection * in the symboltable, but as null in the syntax tree. */ if(vis_var != null) host.set_vis(vis_var); if(mod_var != null) host.set_mods(mod_var.isEmpty() ? null : mod_var); if(ret_var != null) host.set_type((MemberType)ret_var); if(body_var != null) host.long_set_body(body_var); }} before VarVisibility {{ Ident var = host.get_varref().get_name(); if(!Var.defined(var)) Err.err(var+" undefined. Failed visibility lookup."); else try { vis_var = (FixVisibility)Var.lookup(var); } catch(ClassCastException e) { Err.err(var+" is not of type \"Visibility\"."); } }} before VarModifiers {{ Ident var = host.get_varref().get_name(); if(!Var.defined(var)) Err.err(var+" undefined. Failed modifiers lookup."); else try { mod_var = (FixModifiers)Var.lookup(var); } catch(ClassCastException e) { Err.err(var+" is not of type \"Modifiers\"."); } }} before VarDataType {{ // return type Ident var = host.get_varref().get_name(); if(!Var.defined(var)) Err.err(var+" undefined. Failed return type lookup."); else try { ret_var = (FixDataType)Var.lookup(var); } catch(ClassCastException e) { Err.err(var+" is not of type \"DataType\"."); } }} before VarMethodBody {{ Ident var = host.get_varref().get_name(); if(!Var.defined(var)) Err.err(var+" undefined. Failed method body lookup."); else try { body_var = (JavaCode)Var.lookup(var); } catch(ClassCastException e) { Err.err(var+" is not of type \"JavaCode\"."); } }} before VarPackage {{ Ident var = host.get_varref().get_name(); if(!Var.defined(var)) Err.err(var+" undefined. Failed package lookup."); else try { pack_var = (FixPackage)Var.lookup(var); } catch(ClassCastException e) { Err.err(var+" is not of type \"Package\"."); } }} } } Var { {{static Hashtable symboltable = new Hashtable();}} static void assign(Ident symbol, Rvalue rvalue, Weaver big) {{ if(rvalue instanceof RVisibility) { FixVisibility vis = big.findVisibility(((RVisibility)rvalue).get_name()); /* symboltable.put(symbol.toString(), vis==null ? new FixVisibility() : vis); */ if(vis == null) Err.err("Could not find visibility for "+symbol+"."); else symboltable.put(symbol.toString(), vis); } else if(rvalue instanceof RModifiers) { FixModifiers mods = big.findModifiers(((RModifiers)rvalue).get_name()); symboltable.put(symbol.toString(),mods==null? new FixModifiers() : mods); } else if(rvalue instanceof RReturnType) { FixDataType ret = big.findReturnType(((RReturnType)rvalue).get_name()); if(ret == null) Err.err("Could not find return type for "+symbol+"."); else symboltable.put(symbol.toString(), ret); } else if(rvalue instanceof RBody) { JavaCode body = big.findBody(((RBody)rvalue).get_name()); if(body == null) Err.err("Could not find method body for "+symbol+"."); else symboltable.put(symbol.toString(), body); } else if(rvalue instanceof RJavaCode) { JavaCode code = ((RJavaCode)rvalue).get_javacode(); symboltable.put(symbol.toString(), code); } else if(rvalue instanceof RPackage) { FixPackage pkg = big.findPackage(((RPackage)rvalue).get_name()); symboltable.put(symbol.toString(), pkg==null ? new FixPackage() : pkg); } else if(rvalue instanceof RVar) { RVarExp exp = ((RVar)rvalue).get_exp(); if(exp.get_next()==null) symboltable.put(symbol.toString(),lookup(exp.get_varref().get_name())); else symboltable.put(symbol.toString(), exp.get_code()); } else Err.bug("Uninterpretable assignment to variable "+symbol+"."); }} static boolean defined(Ident symbol) {{ return symboltable.containsKey(symbol.toString()); }} static Object lookup(Ident symbol) {{ return symboltable.get(symbol.toString()); }} } RVarExp { JavaCode get_code() {{ return JavaCode.parse("("+"@"+extract_text().toString()+"@"+")"); }} private StringBuffer extract_text() {{ JavaCode jc_frag; try { jc_frag = (JavaCode)Var.lookup(get_varref().get_name()); } catch(ClassCastException e) { Err.err(get_varref().get_name()+" is not of type JavaCode."); return new StringBuffer(""); } StringBuffer sb_frag = new StringBuffer(jc_frag.get_text().toString()); jc_frag = null; if(get_next()==null) return sb_frag; return sb_frag.append(get_next().extract_text()); }} } Weaver { FixVisibility findVisibility(FullMethodName name) {{ // may return null Enumeration part_enum = this.findCIParts(name).elements(); FixVisibility vis = null; boolean first = true; while(part_enum.hasMoreElements()) { ClassMethod pcp = (ClassMethod)part_enum.nextElement(); FixVisibility current = pcp.long_get_vis(); if(first) { vis = current; first = false; } else if(vis == null && current == null) continue; else try { // one kind of error is better than two if(!current.equals(vis)) throw new NullPointerException(); } catch(NullPointerException e) { Err.err("Conflicting visibilities of "+ name.long_get_methodident()+"."); vis = null; break; } } return vis; }} FixModifiers findModifiers(FullMethodName name) {{ Enumeration part_enum = this.findCIParts(name).elements(); FixModifiers mods = null; boolean first = true; while(part_enum.hasMoreElements()) { ClassMethod pcp = (ClassMethod)part_enum.nextElement(); FixModifiers current = pcp.long_get_mods(); if(first) { mods = current; first = false; } else if(mods == null && current == null) continue; else try { // one kind of error is better than two if(!current.equals(mods)) throw new NullPointerException(); } catch(NullPointerException e) { Err.err("Conflicting modifiers of "+ name.long_get_methodident()+"."); mods = null; break; } } return mods; }} FixDataType findReturnType(FullMethodName name) {{ // null return => error Enumeration part_enum = this.findCIParts(name).elements(); FixDataType ret = null; while(part_enum.hasMoreElements()) { ClassMethod pcp = (ClassMethod)part_enum.nextElement(); FixDataType current = pcp.long_get_return(); if(current==null) { Err.err("Could not find return type of "+ name.long_get_methodident()+"."); ret = null; break; } if(ret==null) ret = current; else if(!current.equals(ret)) { Err.err("Conflicting return type of "+name.long_get_methodident()+"."); ret = null; break; } } return ret; }} JavaCode findBody(FullMethodName name) {{ // null return => error Enumeration part_enum = this.findCIParts(name).elements(); JavaCode ret = null; if(part_enum.hasMoreElements()) { ClassMethod pcp = (ClassMethod)part_enum.nextElement(); ret = pcp.long_get_body(); if(ret==null) Err.err("Could not find method body of "+ name.long_get_methodident()+"."); } if(part_enum.hasMoreElements()) Err.err("Found multiple method bodies of "+ name.long_get_methodident()+". Please disambiguate."); return ret; }} FixPackage findPackage(ClassName name) via {AddClass,AddInterface} to Pack { // null return val is ok {{FixPackage ret = null;}} around {AddClass,AddInterface} {{ if(host.get_name().get_ident().equals(name.get_ident())) subtraversal.apply(); }} before Pack {{ try { ret = (FixPackage)host; } catch(ClassCastException e) { Err.err("Could not find package of "+name.get_ident()+"."); } }} return {{ ret }} } }