public override void BreakApartParsedTokens() { SynLog.Log($"Breaking apart type {this.typeName}."); SynLog.LogFragments(this.declarationTokens); // For struct structname { ... }, remove everything except the ... this.declarationTokens.RemoveRange(0, 3); int lastIdx = this.declarationTokens.Count - 1; if (this.declarationTokens[lastIdx].MatchesSymbol(";")) { this.declarationTokens.RemoveRange(lastIdx - 1, 2); } else { this.declarationTokens.RemoveRange(lastIdx, 1); } while (this.declarationTokens.Count > 0) { if (this.declarationTokens[0].MatchesSymbol(";") == true) { this.declarationTokens.RemoveAt(0); continue; } SynRegion rgn = SynRegion.Parse(this, this.declarationTokens); if (rgn != null) { this.regions.Add(rgn.name, rgn); continue; } SynFuncDecl fnParse = SynFuncDecl.Parse( this, this.declarationTokens, this.typeName, false, SynFuncDecl.ParseType.StructContext); if (fnParse != null) { this.AddFunction(fnParse); continue; } SynVarValue varParse = SynVarValue.ParseBodyVar(this.declarationTokens, SynVarValue.OuterScope.Struct); if (varParse != null) { this.AddVariable(varParse); continue; } } }
public SynVarValue AddVariable(string varName, string tyName, VarDst dst, SynVarValue.VarLocation varLoc) { SynVarValue newVar = new SynVarValue(); newVar.varLoc = varLoc; newVar.varName = varName; newVar.typeName = tyName; this.AddVariable(newVar, dst); return(newVar); }
public void AddVariable(SynVarValue var) { if (var.varLoc == SynVarValue.VarLocation.Static) { this.AddGlobalVar(var); } else { this.AddLocalVariable(var); } }
SynVarValue GetParamPhrase(List <Token> tokens) { int idx = 0; if (tokens[idx].Matches(TokenType.tyWord, "param") == false) { return(null); } if ( tokens[idx + 1].Matches(TokenType.tyWord) == false || tokens[idx + 2].Matches(TokenType.tyWord) == false) { throw new System.Exception($"Error parsing param on line {tokens[idx].line}"); } string typename = tokens[idx + 1].fragment; string varname = tokens[idx + 2].fragment; if (this.varLookups.ContainsKey(varname) == true) { throw new System.Exception($"Redefining variable {varname} on line {tokens[idx].line}."); } SynVarValue newParam = new SynVarValue(); newParam.typeName = typename; newParam.varName = varname; newParam.varLoc = SynVarValue.VarLocation.Parameter; idx = 3; if (tokens[idx].Matches(TokenType.tySymbol, "=") == true) { ++idx; Parser.MovePastScopeTSemi(ref idx, tokens); } else if (tokens[idx].Matches(TokenType.tySymbol, ";") == false) { throw new System.Exception($"Unexpected end to param {varname} on line {tokens[idx].line}."); } List <Token> declPhrase = tokens.GetRange(0, idx); tokens.RemoveRange(0, idx); newParam.declPhrase = declPhrase; this.AddVariable(newParam); return(newParam); }
public void AddVariable(SynVarValue var, VarDst dst) { if (dst == VarDst.Global) { this.globalLookups.Add(var.varName, var); this.globalDefs.Add(var); } else if (dst == VarDst.Local) { this.varLookups.Add(var.varName, var); this.varDefs.Add(var); } else { throw new SynthExceptionImpossible("Attemping to add variable to unknown destination"); } }
public void AddGlobalVar(SynVarValue var) { this.AddVariable(var, VarDst.Global); }
public void AddLocalVariable(SynVarValue var) { this.AddVariable(var, VarDst.Local); }
/// <summary> /// This function is expected to be called during AST construction /// (of whatever needs the copy constructor). This means struct /// processing and alignment should have already occured. This also /// means the function will be queued for being constructed into /// WASM binary like all other functions in a later pass. /// </summary> /// <param name="autocreate">If the function doesn't exist, auto /// create a default copy constructor and register it with the struct. /// </param> /// <returns>The found, or created, copy constructor for the struct.</returns> public override SynFuncDecl GetCopyConstructor(bool autocreate, SynNestingBuilder scb) { List <SynFuncDecl> lstFns; if (this.functions.TryGetValue(this.typeName, out lstFns) == false) { if (autocreate == false) { return(null); } // If we're autocreating, prepare a list for it to be registered in. lstFns = new List <SynFuncDecl>(); this.functions.Add(this.typeName, lstFns); } else { foreach (SynFuncDecl fns in lstFns) { if (fns.returnType != null) { continue; } if (fns.parameterSet.Count != 2) { continue; } if ( fns.parameterSet.Get(0).type != this || fns.parameterSet.Get(1).type != this) { continue; } return(fns); } if (autocreate == false) { return(null); } } SynFuncDecl sfdCC = new SynFuncDecl(this); // SynVarValue svvDst = new SynVarValue(); svvDst.varLoc = SynVarValue.VarLocation.ThisRef; svvDst.dataType = SynVarValue.VarValueDataType.Pointer; // SynVarValue svvSrc = new SynVarValue(); svvSrc.varLoc = SynVarValue.VarLocation.Parameter; svvSrc.dataType = SynVarValue.VarValueDataType.Reference; sfdCC.parameterSet.AddParameter(svvDst); sfdCC.parameterSet.AddParameter(svvSrc); // TODO: Do explicit alignment here? // Add this ahead of time lstFns.Add(sfdCC); // Go through each variable in order and copy them by producing the proper AST for (int i = 0; i < this.varDefs.Count; ++i) { SynVarValue svv = this.varDefs[i]; // The member to copy if (svv.type.intrinsic == true) { AST astSrcDeref = new AST(new Token(-1, svv.varName, TokenType.tyWord), scb, ASTOp.DerefName, null, svv.type, false, AST.DataManifest.Procedural, 0); AST astSrcGetMember = new AST(new Token(), scb, ASTOp.GetMemberVar, svvSrc, this, false, AST.DataManifest.Procedural, 0, astSrcDeref); AST astDstDeref = new AST(new Token(-1, svv.varName, TokenType.tyWord), scb, ASTOp.DerefName, null, svv.type, false, AST.DataManifest.Procedural, 0); AST astDstGetMember = new AST(new Token(), scb, ASTOp.GetMemberVar, svvSrc, this, false, AST.DataManifest.Procedural, 0, astSrcDeref); AST astSetVar = new AST(new Token(), scb, ASTOp.SetValue, null, null, false, AST.DataManifest.NoData, 0, astSrcDeref, astSrcGetMember); sfdCC.ast.branches.Add(astSetVar); } else { // Else, it's a sub-struct, and we use GetCopyConstructor() recursively // to copy it. throw new SynthExceptionCompile("Class copy constructors are not supported."); } } return(sfdCC); }
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."); }