public Node Instantiate(string guid) { var parserNode = ParserNodes.FirstOrDefault(p => p.Guid == guid); if (parserNode == null) { var error = new BuildError { Message = $"Could not find a node with GUID: {guid}." }; Errors.Add(error); return(null); } // Uses a depth first loop instead of recursion to avoid potential stack overflows. var root = parserNode.CreateInstance(TypeDefMap, Errors); var n = new InstantiationNode { Instance = root, Parser = parserNode }; var open = new Stack <InstantiationNode>(); open.Push(n); while (open.Count > 0) { var next = open.Pop(); var children = next.Parser.IsDerivedFromTypeDef ? TypeDefMap[next.Parser.Tag].Children : next.Parser.Children; foreach (var parserChild in children) { var instance = parserChild.CreateInstance(TypeDefMap, Errors); if (instance == null) { continue; } var c = new InstantiationNode { Instance = instance, Parser = parserChild }; if (next.Instance.Children == null) { next.Instance.Children = new List <Node>(); } next.Instance.Children.Add(instance); open.Push(c); } } foreach (var node in root.DepthFirstIterate()) { node?.Initialize(); } return(root); }
public static BuildError FileMissing(string file) { var error = new BuildError(); error.IsCritical = false; error.Message = $"File does not exit: {file}"; return(error); }
public static BuildError MissingTypeDefInstance(string typeDef, string file) { var error = new BuildError(); error.IsCritical = true; error.Message = $"Could not find node type or TypeDef during instantiation: {typeDef}"; error.Data.Add($"File: {file}"); return(error); }
public static BuildError CannotCastToNode(string type, string file) { var error = new BuildError(); error.IsCritical = true; error.Message = $"Could not cast {type} into {nameof(Node)}."; error.Data.Add($"File: {file}"); return(error); }
public static BuildError CannotLoadReference(string exception) { var error = new BuildError(); error.IsCritical = true; error.Message = "Could not load reference assembly."; error.Data.Add(exception); return(error); }
public static BuildError UnableToInstantiate(string type, string file, string exception) { var error = new BuildError(); error.IsCritical = true; error.Message = $"Could not instantiate node of type: {type}"; error.Data.Add(exception); error.Data.Add($"File: {file}"); return(error); }
public static BuildError FileLoad(string file, string exception) { var error = new BuildError(); error.IsCritical = false; error.Message = "Could not load file."; error.Data.Add($"File: {file}"); error.Data.Add(exception); return(error); }
public static BuildError RepeatedNodeGuid(string guid, params string[] files) { var error = new BuildError(); error.IsCritical = true; error.Message = $"Repeated node GUID: {guid}"; foreach (var file in files) { error.Data.Add($"File: {file}"); } return(error); }
public static BuildError MissingTypeDef(string typeDef, params string[] files) { var error = new BuildError(); error.IsCritical = true; error.Message = $"Missing TypeDef: {typeDef}"; foreach (var file in files) { error.Data.Add($"File: {file}"); } return(error); }
public static BuildError TypeDefsUnresolved(IEnumerable <string> typeDefs) { var error = new BuildError(); error.IsCritical = true; error.Message = "Some TypeDefs could not be resolved."; foreach (var typeDef in typeDefs) { error.Data.Add(typeDef); } return(error); }
public static BuildError UnsupportedScriptFunctionType(string guid, string declaringType, string propertyType, string genericDefinitionType, string functionText) { var error = new BuildError(); error.IsCritical = true; error.Message = "Unsupported function type."; error.Data.Add($"Guid: {guid}"); error.Data.Add($"Declaring Type: {declaringType}"); error.Data.Add($"Property Type: {propertyType}"); error.Data.Add($"Generic Type Definition: {genericDefinitionType}"); error.Data.Add(functionText); return(error); }
public YggCompilation Compile <TState>(IEnumerable <string> namespaces, IEnumerable <string> referenceAssemblyPaths, List <ScriptedFunctionDefinition> definitions) { var compilation = new YggCompilation(); var builderClassText = new StringBuilder(); var usings = new List <string>(namespaces.Distinct().Select(s => $"using {s};\n")); var referencePaths = new HashSet <string>(referenceAssemblyPaths); // Add dynamic using if necessary. if (definitions.Any(d => d.ReplaceObjectWithDynamic)) { usings.Add("using System.Dynamic;"); } foreach (var u in usings) { builderClassText.Append(u); } builderClassText.Append("public class FunctionBuilder\n{"); foreach (var definition in definitions) { var sf = CreateScriptedFunction <TState>(definition.Guid, definition.FunctionProperty, definition.FunctionText, definition.ReplaceObjectWithDynamic, compilation.Errors); if (sf == null) { continue; } if (!compilation.GuidFunctionMap.TryGetValue(sf.Guid, out var functions)) { functions = new List <ScriptedFunction>(); compilation.GuidFunctionMap[sf.Guid] = functions; } functions.Add(sf); builderClassText.Append(sf.ScriptText); foreach (var reference in sf.References) { referencePaths.Add(reference); } } builderClassText.Append("\n}"); List <PortableExecutableReference> references; try { references = referencePaths .Select(p => MetadataReference.CreateFromFile(p)) .ToList(); } catch (Exception e) { compilation.Errors.Add(ParserErrorHelper.CannotLoadReference(e.Message)); return(compilation); } var options = ScriptOptions.Default.AddReferences(references); var script = CSharpScript.Create(builderClassText.ToString(), options); var comp = script.GetCompilation(); byte[] compiledAssembly; using (var output = new MemoryStream()) { var emitResult = comp.Emit(output); if (!emitResult.Success) { var error = new BuildError { Message = "Emit compilation error.", IsCritical = true }; foreach (var diag in emitResult.Diagnostics) { error.Diagnostics.Add(diag); } compilation.Errors.Add(error); return(compilation); } compiledAssembly = output.ToArray(); } var assembly = Assembly.Load(compiledAssembly); var entryType = assembly.GetTypes().First(t => t.Name == "FunctionBuilder"); var builder = Activator.CreateInstance(entryType); foreach (var sf in compilation.GuidFunctionMap.Values.SelectMany(g => g)) { sf.Builder = builder; sf.BuilderMethod = entryType.GetMethod(sf.BuilderMethodName); } return(compilation); }