/// <summary> /// Ensure the structs have byte alignments calculated, and that every /// member variable type that's referenced is known. /// </summary> /// <returns></returns> public virtual TypeConsolidate ResolveStaticTypeAlignments() { // contained by value. int alreadyDet = 0; int newlyDet = 0; foreach (KeyValuePair <string, SynType> kvp in this.typesDefs) { TypeConsolidate tc = kvp.Value.ResolveStaticTypeAlignments(); if (tc == TypeConsolidate.AllDetermined) { ++alreadyDet; } else if (tc == TypeConsolidate.UndeterminedProgress) { ++newlyDet; } } if (alreadyDet + newlyDet == this.typesDefs.Count) { return(TypeConsolidate.AllDetermined); } else if (newlyDet > 0) { return(TypeConsolidate.UndeterminedProgress); } else { return(TypeConsolidate.UndeterminedNoChange); } }
public override TypeConsolidate ResolveStaticTypeAlignments() { if (resolvedAlignments == true) { return(TypeConsolidate.AllDetermined); } int alreadyAligned = 0; int newlyAligned = 0; foreach (var v in this.varDefs) { if (v.type == null) { if (string.IsNullOrEmpty(v.typeName) == true) { throw new System.Exception("Unknown type."); } v.type = this.GetType(v.typeName); } if (v.type.Aligned() == false) { ++alreadyAligned; continue; } TypeConsolidate tc = v.type.ResolveStaticTypeAlignments(); if (tc == TypeConsolidate.AllDetermined) { ++newlyAligned; continue; } if (tc == TypeConsolidate.UndeterminedProgress) { return(TypeConsolidate.UndeterminedProgress); } } if (alreadyAligned + newlyAligned < this.varDefs.Count) { if (newlyAligned == 0) { return(TypeConsolidate.UndeterminedNoChange); } else { return(TypeConsolidate.UndeterminedProgress); } } // All the Type references should now be set - so before we // lookup the offsets, we're going to make sure the struct isn't // containing itself, or a child member that's containing // itself. HashSet <string> typesOfChildren = new HashSet <string>(); this.RegisterContainedValueTypes(typesOfChildren); if (typesOfChildren.Contains(this.typeName) == true) { throw new SynthExceptionCompile($"Datatype {this.typeName} found to contain recursive instances of itself as a child member."); } int alignment = 0; foreach (var v in this.varDefs) { v.alignmentOffset = alignment; alignment += v.type.GetByteSize(); } this.byteSize = alignment; this.resolvedAlignments = true; return(TypeConsolidate.AllDetermined); }
public void ParseContext(List <Token> tokens) { SynLog.LogHeader("Starting Parse Content"); SynLog.Log("\tTokens:"); SynLog.Log(tokens); // Get param globals first // ////////////////////////////////////////////////// while (tokens.Count > 0) { SynVarValue parsedParam = SynVarValue.ParseExposedParam(tokens); if (parsedParam == null) { break; } this.AddVariable(parsedParam); } // Parse Sections // ////////////////////////////////////////////////// int idx = 0; while (tokens.Count > 0) { // Get rid of stray parenthesis if (tokens[idx].Matches(TokenType.tySymbol, ";") == true) { tokens.RemoveAt(0); continue; } // Struct parsing if (tokens[0].Matches(TokenType.tyWord, "struct") == true) { SynStruct sst = SynStruct.Parse(this, tokens); if (sst != null) { this.AddType(sst); continue; } } // Function parsing if (tokens[0].Matches(TokenType.tyWord, "entry") == true) { SynFuncDecl sfd = SynFuncDecl.Parse(this, tokens, "", true, SynFuncDecl.ParseType.Entry); sfd.callType = SynFuncDecl.CallType.Entry; if (sfd != null) { this.AddFunction(sfd); continue; } else { throw new System.Exception("entry keyword not part of valid function."); } } SynFuncDecl synthFn = SynFuncDecl.Parse( this, tokens, "", true, SynFuncDecl.ParseType.RootContext); if (synthFn != null) { this.AddFunction(synthFn); continue; } SynVarValue synthVar = SynVarValue.ParseBodyVar(tokens, SynVarValue.OuterScope.Global); if (synthVar != null) { this.AddVariable(synthVar); continue; } throw new System.Exception("Unknown token while parsing root context."); } // Verify Structs // ////////////////////////////////////////////////// SynLog.LogHeader("Verifying types"); while (true) { TypeConsolidate tc = this.ResolveStaticTypeAlignments(); if (tc == TypeConsolidate.UndeterminedNoChange) { throw new System.Exception("Could not resolve all types"); } if (tc == TypeConsolidate.AllDetermined) { break; } } SynLog.Log("Finished verifying struct successfully."); // Gathering globals // ////////////////////////////////////////////////// SynLog.LogHeader("Gathering globals"); List <SynVarValue> globals = new List <SynVarValue>(); foreach (SynScope s in this.EnumerateScopes()) { s.RegisterGlobals(globals); } this.totalGlobalBytes = 0; foreach (SynVarValue svv in globals) { svv.alignmentOffset = this.totalGlobalBytes; int byteSz = svv.type.GetByteSize(); if (byteSz <= 0) { throw new SynthExceptionImpossible("Data type for global variable is zero in size."); } SynLog.Log($"Added {svv.varName} to globals at offset {svv.alignmentOffset}"); this.totalGlobalBytes += byteSz; } SynLog.Log($"Total global variable space is {this.totalGlobalBytes}."); // Verify Functions // ////////////////////////////////////////////////// SynLog.LogHeader("Verifying After function and variable collection pass."); this.Validate_AfterTypeAlignment(0); SynLog.Log("Finished verifying functions successfully."); }