Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
NLua
Commits
45b0e721
Commit
45b0e721
authored
Aug 06, 2014
by
Vinicius Jarina
Browse files
[NLua] Fixed #100 HasOpertator extensions throwing AmbiguousMatchException
parent
7817d0d0
Changes
5
Hide whitespace changes
Inline
Side-by-side
ConsoleTest/Program.cs
View file @
45b0e721
...
...
@@ -8,21 +8,26 @@ using NLuaTest.Mock;
namespace
ConsoleTest
{
struct
Sub2
{
int
someval
;
}
struct
Sub
{
public
Sub2
z
;
}
public
class
Vector
{
public
double
x
;
public
double
y
;
public
static
Vector
operator
*(
float
k
,
Vector
v
)
{
var
r
=
new
Vector
();
r
.
x
=
v
.
x
*
k
;
r
.
y
=
v
.
y
*
k
;
return
r
;
}
struct
Top
{
public
Sub
y
;
public
static
Vector
operator
*
(
Vector
v
,
float
k
)
{
var
r
=
new
Vector
();
r
.
x
=
v
.
x
*
k
;
r
.
y
=
v
.
y
*
k
;
return
r
;
}
}
public
class
Program
{
...
...
@@ -41,22 +46,22 @@ namespace ConsoleTest
using
(
Lua
lua
=
new
Lua
())
{
lua
.
DebugHook
+=
DebugHook
;
lua
.
LoadCLRPackage
();
lua
.
SetDebugHook
(
NLua
.
Event
.
EventMasks
.
LUA_MASKLINE
,
0
);
lua
.
DoString
(
@" import ('System.Numerics')
c = Complex (10, 5)
c = -c "
);
var
a
=
new
System
.
Numerics
.
Complex
(
10
,
0
);
var
b
=
new
System
.
Numerics
.
Complex
(
10
,
0
);
var
c
=
lua
[
"c"
];
var
x
=
a
+
b
;
lua
.
DoString
(
@" import ('ConsoleTest')
v = Vector()
v.x = 10
v.y = 3
v = v*2
v = 3 * v
"
);
var
v
=
lua
[
"v"
];
// lua.LoadCLRPackage ();
lua
[
"a"
]
=
a
;
lua
[
"b"
]
=
b
;
var
res
=
lua
.
DoString
(
@"return a ~= b"
)[
0
];
}
...
...
Core/NLua/Extensions/GeneralExtensions.cs
View file @
45b0e721
...
...
@@ -23,7 +23,9 @@
* THE SOFTWARE.
*/
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Collections.Generic
;
using
System.Reflection
;
namespace
NLua.Extensions
{
...
...
@@ -57,13 +59,18 @@ namespace NLua.Extensions
static
class
TypeExtensions
{
public
static
bool
HasMethod
(
this
Type
t
,
string
name
)
{
var
op
=
t
.
GetMethods
(
BindingFlags
.
Public
|
BindingFlags
.
Instance
|
BindingFlags
.
Static
);
return
op
.
Count
(
m
=>
m
.
Name
==
name
)
>
0
;
}
public
static
bool
HasAdditionOpertator
(
this
Type
t
)
{
if
(
t
.
IsPrimitive
)
return
true
;
var
op_add
=
t
.
GetMethod
(
"op_Addition"
);
return
op_add
!=
null
;
return
t
.
HasMethod
(
"op_Addition"
);
}
public
static
bool
HasSubtractionOpertator
(
this
Type
t
)
...
...
@@ -71,8 +78,7 @@ namespace NLua.Extensions
if
(
t
.
IsPrimitive
)
return
true
;
var
op_add
=
t
.
GetMethod
(
"op_Subtraction"
);
return
op_add
!=
null
;
return
t
.
HasMethod
(
"op_Subtraction"
);
}
public
static
bool
HasMultiplyOpertator
(
this
Type
t
)
...
...
@@ -80,8 +86,7 @@ namespace NLua.Extensions
if
(
t
.
IsPrimitive
)
return
true
;
var
op_add
=
t
.
GetMethod
(
"op_Multiply"
);
return
op_add
!=
null
;
return
t
.
HasMethod
(
"op_Multiply"
);
}
public
static
bool
HasDivisionOpertator
(
this
Type
t
)
...
...
@@ -89,8 +94,7 @@ namespace NLua.Extensions
if
(
t
.
IsPrimitive
)
return
true
;
var
op_add
=
t
.
GetMethod
(
"op_Division"
);
return
op_add
!=
null
;
return
t
.
HasMethod
(
"op_Division"
);
}
public
static
bool
HasModulusOpertator
(
this
Type
t
)
...
...
@@ -98,26 +102,23 @@ namespace NLua.Extensions
if
(
t
.
IsPrimitive
)
return
true
;
var
op_add
=
t
.
GetMethod
(
"op_Modulus"
);
return
op_add
!=
null
;
return
t
.
HasMethod
(
"op_Modulus"
);
}
public
static
bool
HasUnaryNegationOpertator
(
this
Type
t
)
{
if
(
t
.
IsPrimitive
)
return
true
;
var
op
_add
=
t
.
GetMethod
(
"op_UnaryNegation"
);
return
op
_add
!=
null
;
// Unary - will always have only one version.
var
op
=
t
.
GetMethod
(
"op_UnaryNegation"
,
BindingFlags
.
Public
|
BindingFlags
.
Instance
|
BindingFlags
.
Static
);
return
op
!=
null
;
}
public
static
bool
HasEqualityOpertator
(
this
Type
t
)
{
if
(
t
.
IsPrimitive
)
return
true
;
var
op_add
=
t
.
GetMethod
(
"op_Equality"
);
return
op_add
!=
null
;
return
t
.
HasMethod
(
"op_Equality"
);
}
public
static
bool
HasLessThanOpertator
(
this
Type
t
)
...
...
@@ -125,17 +126,19 @@ namespace NLua.Extensions
if
(
t
.
IsPrimitive
)
return
true
;
var
op_add
=
t
.
GetMethod
(
"op_LessThan"
);
return
op_add
!=
null
;
return
t
.
HasMethod
(
"op_LessThan"
);
}
public
static
bool
HasLessThanOrEqualOpertator
(
this
Type
t
)
{
if
(
t
.
IsPrimitive
)
return
true
;
return
t
.
HasMethod
(
"op_LessThanOrEqual"
);
}
var
op_add
=
t
.
GetMethod
(
"op_LessThanOrEqual"
);
return
op_add
!=
null
;
public
static
IEnumerable
<
MethodInfo
>
GetMethods
(
this
Type
t
,
string
name
,
BindingFlags
flags
)
{
return
t
.
GetMethods
(
flags
).
Where
(
m
=>
m
.
Name
==
name
);
}
}
...
...
Core/NLua/Metatables.cs
View file @
45b0e721
...
...
@@ -22,7 +22,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using
System
;
using
System
;
using
System.Linq
;
using
System.IO
;
using
System.Collections
;
using
System.Reflection
;
...
...
@@ -187,6 +188,7 @@ namespace NLua
return
1
;
}
/*
* __add metafunction of CLR objects.
*/
...
...
@@ -197,32 +199,9 @@ namespace NLua
static
int
AddLua
(
LuaState
luaState
)
{
var
translator
=
ObjectTranslatorPool
.
Instance
.
Find
(
luaState
);
return
AddLua
(
luaState
,
translator
);
return
MatchOperator
(
luaState
,
"op_Addition"
,
translator
);
}
static
int
AddLua
(
LuaState
luaState
,
ObjectTranslator
translator
)
{
object
obj1
=
translator
.
GetRawNetObject
(
luaState
,
1
);
object
obj2
=
translator
.
GetRawNetObject
(
luaState
,
2
);
if
(
obj1
==
null
||
obj2
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot add a nil object"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
Type
type
=
obj1
.
GetType
();
MethodInfo
opAddition
=
type
.
GetMethod
(
"op_Addition"
);
if
(
opAddition
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot add object ("
+
type
.
Name
+
" does not overload the operator +)"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
obj1
=
opAddition
.
Invoke
(
obj1
,
new
object
[]
{
obj1
,
obj2
});
translator
.
Push
(
luaState
,
obj1
);
return
1
;
}
/*
* __sub metafunction of CLR objects.
*/
...
...
@@ -233,30 +212,7 @@ namespace NLua
static
int
SubtractLua
(
LuaState
luaState
)
{
var
translator
=
ObjectTranslatorPool
.
Instance
.
Find
(
luaState
);
return
SubtractLua
(
luaState
,
translator
);
}
static
int
SubtractLua
(
LuaState
luaState
,
ObjectTranslator
translator
)
{
object
obj1
=
translator
.
GetRawNetObject
(
luaState
,
1
);
object
obj2
=
translator
.
GetRawNetObject
(
luaState
,
2
);
if
(
obj1
==
null
||
obj2
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot subtract a nil object"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
Type
type
=
obj1
.
GetType
();
MethodInfo
opSubtract
=
type
.
GetMethod
(
"op_Subtraction"
);
if
(
opSubtract
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot subtract object ("
+
type
.
Name
+
" does not overload the operator -)"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
obj1
=
opSubtract
.
Invoke
(
obj1
,
new
object
[]
{
obj1
,
obj2
});
translator
.
Push
(
luaState
,
obj1
);
return
1
;
return
MatchOperator
(
luaState
,
"op_Multiply"
,
translator
);
}
/*
...
...
@@ -269,32 +225,9 @@ namespace NLua
static
int
MultiplyLua
(
LuaState
luaState
)
{
var
translator
=
ObjectTranslatorPool
.
Instance
.
Find
(
luaState
);
return
M
ultiplyLua
(
luaState
,
translator
);
return
M
atchOperator
(
luaState
,
"op_Multiply"
,
translator
);
}
static
int
MultiplyLua
(
LuaState
luaState
,
ObjectTranslator
translator
)
{
object
obj1
=
translator
.
GetRawNetObject
(
luaState
,
1
);
object
obj2
=
translator
.
GetRawNetObject
(
luaState
,
2
);
if
(
obj1
==
null
||
obj2
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot multiply a nil object"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
Type
type
=
obj1
.
GetType
();
MethodInfo
opMultiply
=
type
.
GetMethod
(
"op_Multiply"
);
if
(
opMultiply
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot multiply object ("
+
type
.
Name
+
" does not overload the operator *)"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
obj1
=
opMultiply
.
Invoke
(
obj1
,
new
object
[]
{
obj1
,
obj2
});
translator
.
Push
(
luaState
,
obj1
);
return
1
;
}
/*
* __div metafunction of CLR objects.
*/
...
...
@@ -305,30 +238,7 @@ namespace NLua
static
int
DivideLua
(
LuaState
luaState
)
{
var
translator
=
ObjectTranslatorPool
.
Instance
.
Find
(
luaState
);
return
DivideLua
(
luaState
,
translator
);
}
static
int
DivideLua
(
LuaState
luaState
,
ObjectTranslator
translator
)
{
object
obj1
=
translator
.
GetRawNetObject
(
luaState
,
1
);
object
obj2
=
translator
.
GetRawNetObject
(
luaState
,
2
);
if
(
obj1
==
null
||
obj2
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot divide a nil object"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
Type
type
=
obj1
.
GetType
();
MethodInfo
opDivide
=
type
.
GetMethod
(
"op_Division"
);
if
(
opDivide
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot divide object ("
+
type
.
Name
+
" does not overload the operator /)"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
obj1
=
opDivide
.
Invoke
(
obj1
,
new
object
[]
{
obj1
,
obj2
});
translator
.
Push
(
luaState
,
obj1
);
return
1
;
return
MatchOperator
(
luaState
,
"op_Division"
,
translator
);
}
/*
...
...
@@ -341,32 +251,9 @@ namespace NLua
static
int
ModLua
(
LuaState
luaState
)
{
var
translator
=
ObjectTranslatorPool
.
Instance
.
Find
(
luaState
);
return
M
odLua
(
luaState
,
translator
);
return
M
atchOperator
(
luaState
,
"op_Modulus"
,
translator
);
}
static
int
ModLua
(
LuaState
luaState
,
ObjectTranslator
translator
)
{
object
obj1
=
translator
.
GetRawNetObject
(
luaState
,
1
);
object
obj2
=
translator
.
GetRawNetObject
(
luaState
,
2
);
if
(
obj1
==
null
||
obj2
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot mod a nil object"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
Type
type
=
obj1
.
GetType
();
MethodInfo
opMod
=
type
.
GetMethod
(
"op_Modulus"
);
if
(
opMod
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot mod object ("
+
type
.
Name
+
" does not overload the operator %)"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
obj1
=
opMod
.
Invoke
(
obj1
,
new
object
[]
{
obj1
,
obj2
});
translator
.
Push
(
luaState
,
obj1
);
return
1
;
}
/*
* __unm metafunction of CLR objects.
*/
...
...
@@ -413,33 +300,9 @@ namespace NLua
static
int
EqualLua
(
LuaState
luaState
)
{
var
translator
=
ObjectTranslatorPool
.
Instance
.
Find
(
luaState
);
return
EqualLua
(
luaState
,
translator
);
}
static
int
EqualLua
(
LuaState
luaState
,
ObjectTranslator
translator
)
{
object
obj1
=
translator
.
GetRawNetObject
(
luaState
,
1
);
object
obj2
=
translator
.
GetRawNetObject
(
luaState
,
2
);
if
(
obj1
==
null
||
obj2
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot compare a nil object"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
Type
type
=
obj1
.
GetType
();
MethodInfo
opEqual
=
type
.
GetMethod
(
"op_Equality"
);
if
(
opEqual
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot compare object ("
+
type
.
Name
+
" does not overload the operator =)"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
obj1
=
opEqual
.
Invoke
(
obj1
,
new
object
[]
{
obj1
,
obj2
});
translator
.
Push
(
luaState
,
obj1
);
return
1
;
return
MatchOperator
(
luaState
,
"op_Equality"
,
translator
);
}
/*
* __lt metafunction of CLR objects.
*/
...
...
@@ -450,32 +313,9 @@ namespace NLua
static
int
LessThanLua
(
LuaState
luaState
)
{
var
translator
=
ObjectTranslatorPool
.
Instance
.
Find
(
luaState
);
return
LessThanLua
(
luaState
,
translator
);
}
static
int
LessThanLua
(
LuaState
luaState
,
ObjectTranslator
translator
)
{
object
obj1
=
translator
.
GetRawNetObject
(
luaState
,
1
);
object
obj2
=
translator
.
GetRawNetObject
(
luaState
,
2
);
if
(
obj1
==
null
||
obj2
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot compare a nil object"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
Type
type
=
obj1
.
GetType
();
MethodInfo
opLessThan
=
type
.
GetMethod
(
"op_LessThan"
);
if
(
opLessThan
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot compare object ("
+
type
.
Name
+
" does not overload the operator <)"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
obj1
=
opLessThan
.
Invoke
(
obj1
,
new
object
[]
{
obj1
,
obj2
});
translator
.
Push
(
luaState
,
obj1
);
return
1
;
return
MatchOperator
(
luaState
,
"op_LessThan"
,
translator
);
}
/*
* __le metafunction of CLR objects.
*/
...
...
@@ -486,31 +326,8 @@ namespace NLua
static
int
LessThanOrEqualLua
(
LuaState
luaState
)
{
var
translator
=
ObjectTranslatorPool
.
Instance
.
Find
(
luaState
);
return
LessThanOrEqualLua
(
luaState
,
translator
);
}
static
int
LessThanOrEqualLua
(
LuaState
luaState
,
ObjectTranslator
translator
)
{
object
obj1
=
translator
.
GetRawNetObject
(
luaState
,
1
);
object
obj2
=
translator
.
GetRawNetObject
(
luaState
,
2
);
if
(
obj1
==
null
||
obj2
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot compare a nil object"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
Type
type
=
obj1
.
GetType
();
MethodInfo
opLessThanOrEqual
=
type
.
GetMethod
(
"op_LessThanOrEqual"
);
if
(
opLessThanOrEqual
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot compare object ("
+
type
.
Name
+
" does not overload the operator <=)"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
obj1
=
opLessThanOrEqual
.
Invoke
(
obj1
,
new
object
[]
{
obj1
,
obj2
});
translator
.
Push
(
luaState
,
obj1
);
return
1
;
}
return
MatchOperator
(
luaState
,
"op_LessThanOrEqual"
,
translator
);
}
/// <summary>
/// Debug tool to dump the lua stack
...
...
@@ -1170,10 +987,64 @@ namespace NLua
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
private
static
bool
IsInteger
(
double
x
)
{
static
bool
IsInteger
(
double
x
)
{
return
Math
.
Ceiling
(
x
)
==
x
;
}
static
object
GetTargetObject
(
LuaState
luaState
,
string
operation
,
ObjectTranslator
translator
)
{
Type
t
;
object
target
=
translator
.
GetRawNetObject
(
luaState
,
1
);
if
(
target
!=
null
)
{
t
=
target
.
GetType
();
if
(
t
.
HasMethod
(
operation
))
return
target
;
}
target
=
translator
.
GetRawNetObject
(
luaState
,
2
);
if
(
target
!=
null
)
{
t
=
target
.
GetType
();
if
(
t
.
HasMethod
(
operation
))
return
target
;
}
return
null
;
}
static
int
MatchOperator
(
LuaState
luaState
,
string
operation
,
ObjectTranslator
translator
)
{
var
validOperator
=
new
MethodCache
();
object
target
=
GetTargetObject
(
luaState
,
operation
,
translator
);
if
(
target
==
null
)
{
translator
.
ThrowError
(
luaState
,
"Cannot call "
+
operation
+
" on a nil object"
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
Type
type
=
target
.
GetType
();
var
operators
=
type
.
GetMethods
(
operation
,
BindingFlags
.
Public
|
BindingFlags
.
Instance
|
BindingFlags
.
Static
);
foreach
(
var
op
in
operators
)
{
bool
isOk
=
translator
.
MatchParameters
(
luaState
,
op
,
ref
validOperator
);
if
(!
isOk
)
continue
;
object
result
;
if
(
op
.
IsStatic
)
result
=
op
.
Invoke
(
null
,
validOperator
.
args
);
else
result
=
op
.
Invoke
(
target
,
validOperator
.
args
);
translator
.
Push
(
luaState
,
result
);
return
1
;
}
translator
.
ThrowError
(
luaState
,
"Cannot call ("
+
operation
+
") on object type "
+
type
.
Name
);
LuaLib
.
LuaPushNil
(
luaState
);
return
1
;
}
internal
Array
TableToArray
(
Func
<
int
,
object
>
luaParamValueExtractor
,
Type
paramArrayType
,
int
startIndex
,
int
count
)
{
...
...
@@ -1226,7 +1097,7 @@ namespace NLua
/*
* Matches a method against its arguments in the Lua stack. Returns
* if the match was succesful. It it was also returns the information
* if the match was succes
s
ful. It it was also returns the information
* necessary to invoke the method.
*/
internal
bool
MatchParameters
(
LuaState
luaState
,
MethodBase
method
,
ref
MethodCache
methodCache
)
...
...
@@ -1306,7 +1177,6 @@ namespace NLua
methodCache
.
outList
=
outList
.
ToArray
();
methodCache
.
argTypes
=
argTypes
.
ToArray
();
}
return
isMethod
;
}
...
...
Core/NLua/ObjectTranslator.cs
View file @
45b0e721
...
...
@@ -938,7 +938,7 @@ namespace NLua
internal
bool
MatchParameters
(
LuaState
luaState
,
MethodBase
method
,
ref
MethodCache
methodCache
)
{
return
metaFunctions
.
MatchParameters
(
luaState
,
method
,
ref
methodCache
);
}
}
internal
Array
TableToArray
(
Func
<
int
,
object
>
luaParamValue
,
Type
paramArrayType
,
int
startIndex
,
int
count
)
{
return
metaFunctions
.
TableToArray
(
luaParamValue
,
paramArrayType
,
startIndex
,
count
);
...
...
tests/LuaTests.cs
View file @
45b0e721
...
...
@@ -33,6 +33,30 @@ namespace NLuaTest
}
}
}
#if MONOTOUCH
[
Preserve
(
AllMembers
=
true
)]
#endif
public
class
Vector
{
public
double
x
;
public
double
y
;
public
static
Vector
operator
*
(
float
k
,
Vector
v
)
{
var
r
=
new
Vector
();
r
.
x
=
v
.
x
*
k
;
r
.
y
=
v
.
y
*
k
;
return
r
;
}
public
static
Vector
operator
*
(
Vector
v
,
float
k
)
{
var
r
=
new
Vector
();
r
.
x
=
v
.
x
*
k
;
r
.
y
=
v
.
y
*
k
;
return
r
;
}
}
[
TestFixture
]
#
if
MONOTOUCH
...
...
@@ -2047,6 +2071,31 @@ namespace NLuaTest
}
}
[
Test
]
public
void
TestStaticOperators
()
{
using
(
Lua
lua
=
new
Lua
())
{
lua
.
LoadCLRPackage
();
lua
.
DoString
(
@" import ('NLuaTest')
v = Vector()
v.x = 10
v.y = 3
v = v*2 "
);
var
v
=
(
Vector
)
lua
[
"v"
];
Assert
.
AreEqual
(
20
,
v
.
x
,
"#1"
);
Assert
.
AreEqual
(
6
,
v
.
y
,
"#2"
);
lua
.
DoString
(
@" x = 2 * v"
);
var
x
=
(
Vector
)
lua
[
"x"
];
Assert
.
AreEqual
(
40
,
x
.
x
,
"#3"
);
Assert
.
AreEqual
(
12
,
x
.
y
,
"#4"
);
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment