Skip to content

Commit

Permalink
Score overloads to get best match
Browse files Browse the repository at this point in the history
  • Loading branch information
praeclarum committed Aug 3, 2018
1 parent 0fff35f commit e553bdc
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 9 deletions.
14 changes: 13 additions & 1 deletion CLanguage/Interpreter/FunctionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,23 @@ public override ResolvedVariable ResolveVariable (string name, CType[] argTypes)
//
// Look for global functions
//
BaseFunction ff = null;
var fi = -1;
var fs = 0;
for (var i = 0; i < exe.Functions.Count; i++) {
var f = exe.Functions[i];
if (f.Name == name && string.IsNullOrEmpty (f.NameContext)) {
return new ResolvedVariable (f, i);
var score = f.FunctionType.ScoreParameterTypesMatches (argTypes);
if (score > fs) {
ff = f;
fi = i;
fs = score;
}
}
}
if (ff != null) {
return new ResolvedVariable (ff, fi);
}

context.Report.Error (103, "The name '" + name + "' does not exist in the current context");
return null;
Expand All @@ -88,6 +99,7 @@ public override ResolvedVariable ResolveMethodFunction (CStructType structType,

var nameContext = structType.Name;

var funcs = exe.Functions.Select ((f, i) => (f, i)).Where (x => x.Item1.NameContext == nameContext && x.Item1.Name == method.Name);
for (var i = 0; i < exe.Functions.Count; i++) {
var f = exe.Functions[i];
if (f.NameContext == nameContext && f.Name == method.Name && f.FunctionType.ParameterTypesEqual (ftype)) {
Expand Down
5 changes: 4 additions & 1 deletion CLanguage/Syntax/FuncallExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ Overload ResolveOverload (Expression function, CType[] argTypes, EmitContext ec)
else {
var methodq = from m in methods
let mt = m.MemberType as CFunctionType
where mt != null && mt.ParameterTypesMatchArgs (argTypes)
where mt != null
let score = mt.ScoreParameterTypesMatches (argTypes)
where score > 0
orderby score descending
select m;
var method = methodq.FirstOrDefault ();
if (method == null) {
Expand Down
23 changes: 16 additions & 7 deletions CLanguage/Types/CFunctionType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,30 @@ public override string ToString()
return s;
}

public bool ParameterTypesMatchArgs (CType[] argTypes)
public int ScoreParameterTypesMatches (CType[] argTypes)
{
if (argTypes == null)
return 1;

if (Parameters.Count != argTypes.Length)
return false;
return 0;

var score = 1;

for (var i = 0; i < Parameters.Count; i++) {
var ft = argTypes[i];
var tt = Parameters[i].ParameterType;

if (!ft.CanCastTo (tt))
return false;
if (ft.Equals (tt)) {
score += 100;
}
else if (ft.CanCastTo (tt)) {
score += 50;
}
}

return true;
}

return score;
}

public bool ParameterTypesEqual (CFunctionType otherType)
{
Expand Down
8 changes: 8 additions & 0 deletions CLanguageTests/ArduinoTestMachineInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Xml.Linq;

namespace CLanguage.Tests
{
Expand Down Expand Up @@ -51,6 +52,11 @@ struct SerialClass {
void println(int value);
void println(const char *value);
};
struct MemberTest {
int f(int testme);
int f(double testme);
};
struct MemberTest test;
struct SerialClass Serial;
";

Expand All @@ -74,6 +80,8 @@ struct SerialClass Serial;
AddInternalFunction ("void SerialClass::println (int value, int base)", Arduino.SerialPrintlnII);
AddInternalFunction ("void SerialClass::println (int value)", Arduino.SerialPrintlnI);
AddInternalFunction ("void SerialClass::println (const char *value)", Arduino.SerialPrintlnS);
AddInternalFunction ("int MemberTest::f (int)", x => x.Push (1));
AddInternalFunction ("int MemberTest::f (double)", x => x.Push (2));
}

static void AssertAreEqual (CInterpreter state)
Expand Down
42 changes: 42 additions & 0 deletions CLanguageTests/OverloadTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;

using Microsoft.VisualStudio.TestTools.UnitTesting;
using CLanguage.Interpreter;

namespace CLanguage.Tests
{
[TestClass]
public class OverloadTests
{
CInterpreter Run (string code)
{
var fullCode = "void start() { __cinit(); main(); } " + code;
var i = CLanguageService.CreateInterpreter (fullCode, new ArduinoTestMachineInfo (), printer: new TestPrinter ());
i.Reset ("start");
i.Step ();
return i;
}

[TestMethod]
public void GlobalScoring ()
{
var i = Run (@"
int f(int x) { return 1; }
int f(double x) { return 2; }
void main () {
assertAreEqual (1, f(0));
assertAreEqual (2, f(0.0));
}");
}

[TestMethod]
public void MemberScoring ()
{
var i = Run (@"
void main () {
assertAreEqual (1, test.f(0));
assertAreEqual (2, test.f(0.0));
}");
}
}
}

0 comments on commit e553bdc

Please sign in to comment.