/// <summary> /// Creates a hierarchical structure from the given namespaces. /// </summary> /// <param name="namespaces">The namespaces.</param> public static List <StructuredNamespace> StructureNamespaces(Namespace[] namespaces) { List <StructuredNamespace> list = new List <StructuredNamespace>(); foreach (var ns in namespaces) { var currentNsLevel = list; for (int i = 0; i < ns.Path.Length; i++) { var pathAnalogon = currentNsLevel.Find(x => x.Name == ns.Path[i]); if (pathAnalogon == null) { if (i == ns.Path.Length - 1) { pathAnalogon = new StructuredNamespace(ns); } else { pathAnalogon = new StructuredNamespace(ns.Path[i]); } currentNsLevel.Add(pathAnalogon); } else if (i == ns.Path.Length - 1) { pathAnalogon.UserFunctions.AddRange(ns.Functions); foreach (var kv in ns.TypeDefinitions) { pathAnalogon.TypeDefinitions[kv.Key] = kv.Value; } } currentNsLevel = pathAnalogon.Children; } } return(list); }
/// <summary> /// Adds a built-in function to this compiler instance. /// </summary> /// <param name="func"> /// The function description. /// The `IsBuiltin` and `Index` fields are ignored and overwritten. /// </param> public void AddBuiltinFunction(FunctionSignature func) { if (object.ReferenceEquals(null, func.Arguments) || string.IsNullOrEmpty(func.Name) || object.ReferenceEquals(null, func.Namespace)) { throw new ArgumentNullException("func"); } // Find (or create) associated namespace StructuredNamespace ptr = _rootNamespace; foreach (string nsPart in func.Namespace) { var ns = ptr.Children.Find(x => x.Name == nsPart); if (ns == null) { ptr.Children.Add(ns = new StructuredNamespace(nsPart)); } ptr = ns; } // Make sure function has valid properties func.IsBuiltin = true; func.Index = ptr.BuiltinFunctions.Where(x => x.Name == func.Name).Count(); // Add the function ptr.BuiltinFunctions.Add(func); }
/// <summary> /// Initializes a new compiler. /// </summary> /// <param name="appName">The name of the application.</param> /// <param name="namespaces">The namespaces containing the operations to be compiled.</param> /// <param name="typeTable">The type look-up table.</param> public CompilerBase(string appName, Namespace[] namespaces, ITypeTable builtinTypes) { if (object.ReferenceEquals(null, appName)) { throw new ArgumentNullException("appName"); } if (object.ReferenceEquals(null, namespaces)) { throw new ArgumentNullException("namespaces"); } if (object.ReferenceEquals(null, builtinTypes)) { throw new ArgumentNullException("builtinTypes"); } _appName = appName; _rootNamespace = StructuredNamespace.CreateRoot(); _rootNamespace.Children = StructuredNamespace.StructureNamespaces(namespaces); _builtinTypes = builtinTypes; }
/// <summary> /// Resolves the given function in the specified context. /// </summary> /// <param name="funcPath">The (absolute or relative) path to the function.</param> /// <param name="namespaceContext">The namespace in which the function is called.</param> /// <param name="scope">The scope in which the function is called.</param> /// <param name="arguments">The arguments with which the function is called.</param> /// <returns>the function if it was found, an empty element with .Index == -1 otherwise.</returns> protected FunctionSignature ResolveFunction(string[] funcPath, string[] namespaceContext, Scope scope, IType[] arguments) { // List all potential functions List <FunctionSignature> potentialFunctions = new List <FunctionSignature>(); string funcName = funcPath[funcPath.Length - 1]; // `funcPath` can be relative to any part of `namespaceContext` for (int context = namespaceContext.Length; context >= 0; context--) { StructuredNamespace ptr = _rootNamespace; // pointer to the current namespace in the search process for (int i = 0; ptr != null && i < context + funcPath.Length - 1; i++) { string token = i < context ? namespaceContext[i] : funcPath[i - context]; ptr = ptr.Children.Find(x => x.Name == token); } if (ptr != null) { potentialFunctions.AddRange(ptr.BuiltinFunctions. Concat(ptr.UserFunctions.Select(f => f.Signature)). Where(f => f.Name == funcName)); } } // `funcPath` can be relative to any imported namespace foreach (var ns in scope.GetImportedNamespaces()) { StructuredNamespace ptr = _rootNamespace; // pointer to the current namespace in the search process for (int i = 0; ptr != null && i < ns.Length + funcPath.Length - 1; i++) { string token = i < ns.Length ? ns[i] : funcPath[i - ns.Length]; ptr = ptr.Children.Find(x => x.Name == token); } if (ptr != null) { potentialFunctions.AddRange(ptr.BuiltinFunctions. Concat(ptr.UserFunctions.Select(f => f.Signature)). Where(f => f.Name == funcName)); } } // Search for the first function which matches the signature foreach (var f in potentialFunctions) { if (f.Arguments.Length != arguments.Length) { continue; } bool signatureMatch = true; for (int i = 0; i < f.Arguments.Length; i++) { if (!arguments[i].CanCastTo(f.Arguments[i].Type)) { signatureMatch = false; break; } } if (signatureMatch) { return(f); } } return(new FunctionSignature { Index = -1 }); }