public CSTranslationClass TranslateBHAV(StructuredBHAV bhav) { var csClass = new CSTranslationClass(); csClass.ClassName = CSTranslationContext.FormatName(bhav.Source.ChunkLabel) + "_" + bhav.Source.ChunkID; csClass.Structure = bhav; csClass.InlineFunction = !bhav.Yields; csClass.ArgCount = Math.Max(4, (int)bhav.Source.Args); //possible to make this tighter by analysing func Context.CurrentBHAV = bhav.Source; Context.CurrentClass = csClass; csClass.Instructions = bhav.Instructions.ToDictionary(x => x.Key, x => { var inst = x.Value; return(new CSTranslationInstruction(inst.Translator.CodeGen(Context), inst.ReturnType, inst.Yields)); }); return(csClass); }
public string TranslateIff(IffFile file) { Context.Filename = CSTranslationContext.FormatName(file.Filename.Replace(".iff", "")); Context.ModuleName = Context.Filename + "Module"; Context.NamespaceName = "FSO.Scripts." + Context.Filename; Context.CurrentFile = file; var bhavs = file.List <BHAV>() ?? new List <BHAV>(); foreach (var bhav in bhavs) { Context.CurrentBHAV = bhav; var sbhav = new StructuredBHAV(bhav); sbhav.Analyse(Context); Context.BHAVInfo[bhav.ChunkID] = sbhav; } foreach (var bhav in Context.BHAVInfo.Values) { PropagateYieldFromCalls(bhav); } foreach (var bhav in Context.BHAVInfo.Values) { foreach (var inst in bhav.Instructions.Values) { (inst.Translator as CSSubroutinePrimitive)?.InitInfo(Context); } } foreach (var bhav in Context.BHAVInfo.Values) { bhav.BuildStructure(); } foreach (var bhav in Context.BHAVInfo.Values) { Context.AllClasses.Add(TranslateBHAV(bhav)); } return(BuildCSFile()); }
private bool PropagateYieldFromCalls(StructuredBHAV bhav) { bhav.VisitCount++; if (bhav.Yields) { return(true); } bool yields = false; foreach (var call in bhav.Calls) { SimAnticsModule module; CSTranslationContext ctx2; //find the bhav. if (call < 4096) { //global module = Context.GlobalModule; ctx2 = (CSTranslationContext)Context.GlobalContext; } else if (call < 8192) { //local (can only be us) module = null; ctx2 = null; } else { //semiglobal module = Context.SemiGlobalModule; ctx2 = (CSTranslationContext)Context.SemiGlobalContext; } if (ctx2 != null) { //in previously compiled context StructuredBHAV newBHAV; if (ctx2.BHAVInfo.TryGetValue(call, out newBHAV)) { if (newBHAV.Yields) { yields = true; break; } } else { yields = true; //if we don't know if it yields, err on the side of caution. break; } } else if (module != null) { if (module.FunctionYields(call) != false) { yields = true; //also true if we're missing the function break; } } else { StructuredBHAV newBHAV; if (Context.BHAVInfo.TryGetValue(call, out newBHAV)) { if (newBHAV.VisitCount == 0) { if (PropagateYieldFromCalls(newBHAV)) { yields = true; break; } } else { //already evaluated (or is being evaluated), take its word for it. if (newBHAV.Yields) { yields = true; break; } } } else { yields = true; //if we don't know if it yields, err on the side of caution. break; } } } bhav.Yields = yields; return(yields); }