/// <summary> /// Creates a signature from a CallExpression object /// </summary> /// <param name="callExpr">CallExpresion object</param> public Signature(CallExpression callExpr) { // Set fully qualified name and return type name = callExpr.methodName; returnType = callExpr.returnType; arguments = new List<BaseType>(); // Populate argument list foreach (Expression expr in callExpr.arguments) { arguments.Add(expr.returnType); } }
void UnaryExpr(out Expression expr) { expr = null; switch (la.kind) { case 40: { Get(); expr = new UnaryExpression(UnaryOperator.UMinus); expr.t = t; UnaryExpr(out (expr as UnaryExpression).operand); break; } case 41: { Get(); expr = new UnaryExpression(UnaryOperator.Not); expr.t = t; UnaryExpr(out (expr as UnaryExpression).operand); break; } case 2: case 3: case 4: case 26: case 27: { ConstantExpression(out expr); break; } case 36: { Get(); Expect(21); expr = new CastExpression(PrimitiveType.INT); expr.t = t; Expect(43); UnaryExpr(out (expr as CastExpression).operand); break; } case 1: { Get(); expr = new VariableReferenceExpression(t.val); expr.t = t; while (la.kind == 32) { Get(); Expect(1); (expr as VariableReferenceExpression).name += "." + t.val; } if (la.kind == 38) { Get(); expr = new CallExpression((expr as VariableReferenceExpression).name, expr.t); Expression argument; if (StartOf(3)) { Expression(out argument); (expr as CallExpression).AddArgument(argument); while (la.kind == 31) { Get(); Expression(out argument); (expr as CallExpression).AddArgument(argument); } } Expect(45); } if (la.kind == 37) { Get(); expr = new IndexerExpression(expr); Expression indexer; Expression(out indexer); (expr as IndexerExpression).AddIndexer(indexer); while (la.kind == 31) { Get(); Expression(out indexer); (expr as IndexerExpression).AddIndexer(indexer); } Expect(44); } break; } case 38: { Get(); Expression(out expr); Expect(45); break; } default: SynErr(56); break; } }
/// <summary> /// Retrieves a function MethodInfo from a given call expression /// </summary> /// <param name="callExpr">CallExpression object</param> /// <returns>MethodInfo of closest matching function or null if no matching function /// is found</returns> public override MethodInfo GetMethodInfo(CallExpression callExpr) { // Convert call expression to signature Signature sig = new Signature(callExpr); // Candidates to best match List<Signature> candidates = new List<Signature>(); List<MethodInfo> candidatesMethodInfo = new List<MethodInfo>(); // For each function in function list foreach (FunctionDeclaration decl in functions) { // Create signature Signature testSig = decl.ToSignature(); // If name is different, continue to next function if (sig.name != testSig.name) { continue; } // If an exact match is found, return it if (sig.IsExactMatch(testSig)) { return decl.mb; } // If signatures are incompatible, continue to next function if (!sig.IsCompatible(testSig)) { continue; } bool add = false, brk = false; // Check current signature against each other candidate foreach (Signature candSig in candidates) { // Pick best signature from current signature and candidate switch (sig.BestSignature(candSig, testSig)) { // If neither is better, mark add to add this function to the list of candidates case Match.Ambiguos: add = true; break; // If this is better, remove the candidate from the list and mark add case Match.SecondBest: candidatesMethodInfo.RemoveAt(candidates.IndexOf(candSig)); candidates.Remove(candSig); add = true; break; // If candidate is better, stop evaluating case Match.FirstBest: brk = true; break; } // If brk is true, stop evaluating if (brk) { break; } } // If add is true, add this function to the candidate list if (add) { candidates.Add(testSig); } } // Check if candidate list is empty if (candidates.Count == 0) { // If no match was found, delegate request to parent scope return parentScope.GetMethodInfo(callExpr); } // Check if a single match was found else if (candidates.Count == 1) { // Return match return candidatesMethodInfo[0]; } // More than one match - ambiguos else { // Cannot determine which function to call return null; } }
/// <summary> /// Retrieves an external function signature from a given call expression /// </summary> /// <param name="callExpr">CallExpression object</param> /// <returns>Closest matching signature or null if no matching function is found</returns> public override Signature GetFunction(CallExpression callExpr) { // Convert call expression to signature Signature sig = new Signature(callExpr); // Candidates to best match List<Signature> candidates = new List<Signature>(); List<MethodInfo> candidatesMethodInfo = new List<MethodInfo>(); // If signature was already found, return it if (signatureLookup.ContainsKey(sig.ToString())) { return signatureLookup[sig.ToString()]; } // If we got to global scope and function doesn't have an FQN, // it means the function doesn't exist if (!sig.name.Contains(".")) { return null; } // Split function FQN into type name and function name string typeName = sig.name.Substring(0, sig.name.LastIndexOf(".")); string methodName = sig.name.Substring(sig.name.LastIndexOf(".") + 1); // For each assembly reference foreach (Assembly asm in references) { Type type = null; // Get type (from FQN type) foreach (Type t in asm.GetTypes()) { if (t.FullName == typeName) { type = t; } } // If type is not found step to next assembly if (type == null) { continue; } // Retrieve function list of the given type foreach (MethodInfo mi in type.GetMethods()) { // If name differs, step to next function if (mi.Name != methodName) { continue; } // Create Signature object to test against Signature testSig = new Signature(mi); // Check if there is an exact match if (sig.IsExactMatch(testSig)) { // Add to dictionary signatureLookup.Add(testSig.ToString(), testSig); methodInfoLookup.Add(testSig.ToString(), mi); return testSig; } // If signatures are incompatible, step to next function if (!sig.IsCompatible(testSig)) { continue; } bool add = false, brk = false; // Check current signature against each other candidate foreach (Signature candSig in candidates) { // Pick best signature from current signature and candidate switch (sig.BestSignature(candSig, testSig)) { // If neither is better, mark add to add this function to the list of candidates case Match.Ambiguos: add = true; break; // If this is better than the candidate case Match.SecondBest: // Remove candidate and mark add to add this function to the list candidatesMethodInfo.RemoveAt(candidates.IndexOf(candSig)); candidates.Remove(candSig); add = true; break; // If the candidate is better than this function there is no need to evaluate // against other candidates - there is a better match than this one already found case Match.FirstBest: brk = true; break; } // Stop evaluation if brk is true if (brk) { break; } } // Add function to the list of candidates if add is true if (add) { candidates.Add(testSig); candidatesMethodInfo.Add(mi); } } } // Check if candidate list is empty if (candidates.Count == 0) { // No match was found return null; } // Check if a single candidate is in the list else if (candidates.Count == 1) { // Add to dictionaries signatureLookup.Add(candidates[0].ToString(), candidates[0]); methodInfoLookup.Add(candidates[0].ToString(), candidatesMethodInfo[0]); return candidates[0]; } // If more candidates are in the list else { // Ambiguos call - cannot determine which candidate is the best return null; } }
/// <summary> /// Retrieves a function signature from a given call expression /// </summary> /// <param name="callExpr">CallExpression object</param> /// <returns></returns> public override Signature GetFunction(CallExpression callExpr) { // Delegate request to parent scope since functions cannot be declared inside other functions return parentScope.GetFunction(callExpr); }
/// <summary> /// Retrieves metadata information for a function /// </summary> /// <param name="callExpr">CallExpression for the function</param> /// <returns></returns> public override MethodInfo GetMethodInfo(CallExpression callExpr) { // Delegate request to parent scope since functions cannot be declared inside other functions return parentScope.GetMethodInfo(callExpr); }
/// <summary> /// Retrieves metadata information for a function /// </summary> /// <param name="callExpr">CallExpression for the function</param> /// <returns></returns> public override MethodInfo GetMethodInfo(CallExpression callExpr) { // Since signatures are always searched during the evaluation step, // a MethodInfo must exist in the dictionary return methodInfoLookup[new Signature(callExpr).ToString()]; }
/// <summary> /// Retrieves metadata information for a function /// </summary> /// <param name="callExpr">CallExpression for the function</param> /// <returns></returns> public abstract MethodInfo GetMethodInfo(CallExpression callExpr);
/// <summary> /// Retrieves the signature of a function /// </summary> /// <param name="callExpr">CallExpression for the function</param> /// <returns></returns> public abstract Signature GetFunction(CallExpression callExpr);
/// <summary> /// Evaluates this node and all of its children /// </summary> /// <param name="scope">The scope of this statement</param> /// <returns></returns> public override Statement Evaluate(Scope scope) { // Just evaluate inner call expression expr = expr.Evaluate(scope) as CallExpression; return this; }
/// <summary> /// Creates a new CallStatement given a CallExpression /// </summary> /// <param name="expr">CallExpression object</param> public CallStatement(Expression expr) : base() { this.expr = expr as CallExpression; }