Unverified Commit e51e3598 authored by Vinicius Jarina's avatar Vinicius Jarina Committed by GitHub
Browse files

Lua integer support (#290)

* Added support to Lua integers.

* Operator [] and `GetNumber` will still return the `double` regardless of the value for backward compatibility
LuaTable.GetObject may have breaks if your code is assuming the value will be always a double boxed.
To get long from Lua object use `GetLong` and to get an integer `GetInteger`.
parent bfd869ef
###############################
# Core EditorConfig Options #
###############################
root = true
# All files
[*]
indent_style = space
# Code files
[*.{cs,csx,vb,vbx}]
indent_size = 4
insert_final_newline = true
charset = utf-8-bom
###############################
# .NET Coding Conventions #
###############################
[*.{cs,vb}]
# Organize usings
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = false
# this. preferences
dotnet_style_qualification_for_field = false:none
dotnet_style_qualification_for_property = false:none
dotnet_style_qualification_for_method = false:none
dotnet_style_qualification_for_event = false:none
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:none
dotnet_style_predefined_type_for_member_access = true:none
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:none
dotnet_style_readonly_field = true:suggestion
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
###############################
# Naming Conventions #
###############################
# Style Definitions
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# Use PascalCase for constant fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
dotnet_naming_symbols.constant_fields.required_modifiers = const
###############################
# C# Code Style Rules #
###############################
[*.cs]
# var preferences
csharp_style_var_for_built_in_types = false:none
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = false:none
# Expression-bodied members
csharp_style_expression_bodied_methods = false:none
csharp_style_expression_bodied_constructors = false:none
csharp_style_expression_bodied_operators = false:none
csharp_style_expression_bodied_properties = true:none
csharp_style_expression_bodied_indexers = true:none
csharp_style_expression_bodied_accessors = true:none
# Pattern-matching preferences
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
# Null-checking preferences
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Modifier preferences
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
# Expression-level preferences
csharp_prefer_braces = true:none
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
###############################
# C# Formatting Rules #
###############################
# New line preferences
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
# Space preferences
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
# Wrapping preferences
csharp_preserve_single_line_statements = true
csharp_preserve_single_line_blocks = true
##################################
# Visual Basic Code Style Rules #
##################################
[*.vb]
# Modifier preferences
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion
\ No newline at end of file
......@@ -37,6 +37,11 @@ Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "NLuaTest.Shared.Scripts", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NLuaTest.Core", "tests\build\netcore\NLuaTest.Core.csproj", "{C3B8FC88-E476-4D34-874E-A0FE67FA0CBC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D432F663-23CC-48B1-A413-935E5393493C}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
tests\src\NLuaTest.Shared.projitems*{20225b34-18f0-477b-ae89-1c95b788c55d}*SharedItemsImports = 4
......
......@@ -297,8 +297,6 @@ namespace NLua
return luaState.ToBoolean(stackPos);
}
private object GetAsCharArray(LuaState luaState, int stackPos)
{
if (!luaState.IsString(stackPos))
......
using System;
using System;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
......@@ -543,13 +543,7 @@ namespace NLua
}
}
/*
* Indexer for global variables from the LuaInterpreter
* Supports navigation of tables by using . operator
*/
public object this[string fullPath] {
get
public object GetObjectFromPath(string fullPath)
{
int oldTop = _luaState.GetTop();
string[] path = FullPathToArray(fullPath);
......@@ -562,17 +556,18 @@ namespace NLua
string[] remainingPath = new string[path.Length - 1];
Array.Copy(path, 1, remainingPath, 0, path.Length - 1);
returnValue = GetObject(remainingPath);
if (dispose != null)
dispose.Dispose();
dispose?.Dispose();
}
_luaState.SetTop(oldTop);
return returnValue;
}
set
public void SetObjectToPath(string fullPath, object value)
{
int oldTop = _luaState.GetTop();
string[] path = FullPathToArray(fullPath);
if (path.Length == 1)
{
_translator.Push(_luaState, value);
......@@ -601,6 +596,23 @@ namespace NLua
RegisterGlobal(fullPath, value.GetType(), 0);
}
}
/*
* Indexer for global variables from the LuaInterpreter
* Supports navigation of tables by using . operator
*/
public object this[string fullPath] {
get
{
// Silently convert Lua integer to double for backward compatibility with index[] operator
object obj = GetObjectFromPath(fullPath);
if (obj is long l)
return (double)l;
return obj;
}
set
{
SetObjectToPath(fullPath, value);
}
}
#region Globals auto-complete
......@@ -712,7 +724,21 @@ namespace NLua
*/
public double GetNumber(string fullPath)
{
return (double)this[fullPath];
// Silently convert Lua integer to double for backward compatibility with GetNumber method
object obj = GetObjectFromPath(fullPath);
if (obj is long l)
return l;
return (double)obj;
}
public int GetInteger(string fullPath)
{
return (int)(long)GetObjectFromPath(fullPath);
}
public long GetLong(string fullPath)
{
return (long)GetObjectFromPath(fullPath);
}
/*
......@@ -720,7 +746,8 @@ namespace NLua
*/
public string GetString(string fullPath)
{
return this[fullPath].ToString();
object obj = GetObjectFromPath(fullPath);
return obj.ToString();
}
/*
......@@ -728,7 +755,7 @@ namespace NLua
*/
public LuaTable GetTable(string fullPath)
{
return (LuaTable)this[fullPath];
return (LuaTable)GetObjectFromPath(fullPath);
}
/*
......@@ -745,8 +772,8 @@ namespace NLua
*/
public LuaFunction GetFunction(string fullPath)
{
object obj = this[fullPath];
LuaFunction luaFunction = obj as LuaFunction;
object obj = GetObjectFromPath(fullPath);
var luaFunction = obj as LuaFunction;
if (luaFunction != null)
return luaFunction;
......@@ -1177,9 +1204,13 @@ namespace NLua
// We leave nothing on the stack when we are done
int oldTop = _luaState.GetTop();
var wrapper = new LuaMethodWrapper(_translator, target, new ProxyType(function.DeclaringType), function);
_translator.Push(_luaState, new LuaNativeFunction(wrapper.InvokeFunction));
this[path] = _translator.GetObject(_luaState, -1);
var f = GetFunction(path);
object value = _translator.GetObject(_luaState, -1);
SetObjectToPath(path, value);
LuaFunction f = GetFunction(path);
_luaState.SetTop(oldTop);
return f;
}
......
......@@ -78,7 +78,7 @@ namespace NLua
if (lua == null)
throw new ArgumentNullException(nameof(lua));
var type = typeof(T);
Type type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException("The type must be an enumeration!");
......@@ -91,7 +91,7 @@ namespace NLua
for (int i = 0; i < names.Length; i++)
{
string path = type.Name + "." + names[i];
lua[path] = values[i];
lua.SetObjectToPath(path, values[i]);
}
}
}
......
using System;
using System;
using System.Linq;
using System.Collections;
using System.Reflection;
......@@ -373,45 +373,66 @@ namespace NLua
return 2;
}
private int GetMethodFallback
(LuaState luaState,
private bool TryAccessByArray(LuaState luaState,
Type objType,
object obj,
object index,
string methodName)
object index)
{
// Try to access by array if the type is right and index is an int (lua numbers always come across as double)
if (objType.IsArray && index is double)
{
int intIndex = (int)(double)index;
if (!objType.IsArray)
return false;
int intIndex = -1;
if (index is long l)
intIndex = (int)l;
else if (index is double d)
intIndex = (int)d;
if (intIndex == -1)
return false;
Type type = objType.UnderlyingSystemType;
if (type == typeof(long[]))
{
long[] arr = (long[])obj;
_translator.Push(luaState, arr[intIndex]);
return true;
}
if (type == typeof(float[]))
{
float[] arr = (float[])obj;
_translator.Push(luaState, arr[intIndex]);
return 0;
return true;
}
if (type == typeof(double[]))
{
double[] arr = (double[])obj;
_translator.Push(luaState, arr[intIndex]);
return 0;
return true;
}
if (type == typeof(int[]))
{
int[] arr = (int[])obj;
_translator.Push(luaState, arr[intIndex]);
return 0;
return true;
}
object[] arrObj = (object[])obj;
_translator.Push(luaState, arrObj[intIndex]);
return 0;
return true;
}
private int GetMethodFallback
(LuaState luaState,
Type objType,
object obj,
object index,
string methodName)
{
// Try to access by array if the type is right and index is an int (lua numbers always come across as double)
if (TryAccessByArray(luaState, objType, obj, index))
return 0;
object method;
if (!string.IsNullOrEmpty(methodName) && TryGetExtensionMethod(objType, methodName, out method))
{
......
using System;
using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
......@@ -825,12 +825,17 @@ namespace NLua
*/
internal object GetObject(LuaState luaState, int index)
{
var type = luaState.Type(index);
LuaType type = luaState.Type(index);
switch (type)
{
case LuaType.Number:
{
if (luaState.IsInteger(index))
return luaState.ToInteger(index);
return luaState.ToNumber(index);
}
case LuaType.String:
return luaState.ToString(index, false);
case LuaType.Boolean:
......@@ -984,36 +989,42 @@ namespace NLua
{
if (o == null)
luaState.PushNil();
else if (o is sbyte || o is byte || o is short || o is ushort ||
o is int || o is uint || o is long || o is float ||
o is ulong || o is decimal || o is double)
{
double d = Convert.ToDouble(o);
luaState.PushNumber(d);
}
else if (o is char)
{
double d = (char)o;
luaState.PushNumber(d);
}
else if (o is string)
{
string str = (string)o;
else if (o is sbyte sb)
luaState.PushInteger(sb);
else if(o is byte bt)
luaState.PushInteger(bt);
else if(o is short s)
luaState.PushInteger(s);
else if (o is ushort us)
luaState.PushInteger(us);
else if (o is int i)
luaState.PushInteger(i);
else if (o is uint ui)
luaState.PushInteger(ui);
else if (o is long l)
luaState.PushInteger(l);
else if (o is ulong ul)
luaState.PushInteger((long)ul);
else if (o is char ch)
luaState.PushInteger(ch);
else if (o is float fl)
luaState.PushNumber(fl);
else if(o is decimal dc)
luaState.PushNumber((double)dc);
else if(o is double db)
luaState.PushNumber(db);
else if (o is string str)
luaState.PushString(str);
}
else if (o is bool)
{
bool b = (bool)o;
else if (o is bool b)
luaState.PushBoolean(b);
}
else if (IsILua(o))
((ILuaGeneratedType)o).LuaInterfaceGetLuaTable().Push(luaState);
else if (o is LuaTable)
((LuaTable)o).Push(luaState);
else if (o is LuaNativeFunction)
PushFunction(luaState, (LuaNativeFunction)o);
else if (o is LuaFunction)
((LuaFunction)o).Push(luaState);
else if (o is LuaTable table)
table.Push(luaState);
else if (o is LuaNativeFunction nativeFunction)
PushFunction(luaState, nativeFunction);
else if (o is LuaFunction luaFunction)
luaFunction.Push(luaState);
else
PushObject(luaState, o, "luaNet_metatable");
}
......
using System;
using System;
using System.Text;
using System.Collections.Generic;
......@@ -34,7 +34,7 @@ namespace NLuaTest
lua.DoString("function func(x,y) return x+y; end");
lua.DoString("test=TestClass()");
lua.DoString("a=test:callDelegate1(func)");
int a = (int)lua.GetNumber("a");
int a = (int)lua.GetInteger("a");
Assert.AreEqual(5, a);
//Console.WriteLine("delegate returned: "+a);
}
......@@ -54,7 +54,7 @@ namespace NLuaTest
lua.DoString("function func(x) return x,x*2; end");
lua.DoString("test=TestClass()");
lua.DoString("a=test:callDelegate2(func)");
int a = (int)lua.GetNumber("a");
int a = lua.GetInteger("a");
Assert.AreEqual(6, a);
//Console.WriteLine("delegate returned: "+a);
}
......@@ -74,7 +74,7 @@ namespace NLuaTest
lua.DoString("function func(x,y) return x+y; end");
lua.DoString("test=TestClass()");
lua.DoString("a=test:callDelegate3(func)");
int a = (int)lua.GetNumber("a");
int a = lua.GetInteger("a");
Assert.AreEqual(5, a);
//Console.WriteLine("delegate returned: "+a);
}
......@@ -94,7 +94,7 @@ namespace NLuaTest
lua.DoString("function func(x,y) return TestClass(x+y); end");
lua.DoString("test=TestClass()");
lua.DoString("a=test:callDelegate4(func)");
int a = (int)lua.GetNumber("a");
int a = lua.GetInteger("a");
Assert.AreEqual(5, a);
//Console.WriteLine("delegate returned: "+a);
}
......@@ -113,7 +113,7 @@ namespace NLuaTest
lua.DoString("test=TestClass()");
lua.DoString("function func(x,y) return x.testval+y.testval; end");
lua.DoString("a=test:callDelegate5(func)");
int a = (int)lua.GetNumber("a");
int a = lua.GetInteger("a");
Assert.AreEqual(5, a);
//Console.WriteLine("delegate returned: "+a);
}
......@@ -133,7 +133,7 @@ namespace NLuaTest
lua.DoString("function func(x) return x,TestClass(x*2); end");
lua.DoString("test=TestClass()");
lua.DoString("a=test:callDelegate6(func)");
int a = (int)lua.GetNumber("a");
int a = lua.GetInteger("a");
Assert.AreEqual(6, a);
//Console.WriteLine("delegate returned: "+a);
}
......@@ -152,7 +152,7 @@ namespace NLuaTest
lua.DoString("test=TestClass()");
lua.DoString("function func(x,y) return TestClass(x+y.testval); end");
lua.DoString("a=test:callDelegate7(func)");
int a = (int)lua.GetNumber("a");
int a = lua.GetInteger("a");
Assert.AreEqual(5, a);
//Console.WriteLine("delegate returned: "+a);
}
......@@ -175,7 +175,7 @@ namespace NLuaTest
lua.DoString("function itest:test1(x,y) return x+y; end");
lua.DoString("test=TestClass()");
lua.DoString("a=test:callInterface1(itest)");
int a = (int)lua.GetNumber("a");
int a = lua.GetInteger("a");
Assert.AreEqual(5, a);
//Console.WriteLine("interface returned: "+a);
}
......@@ -196,7 +196,7 @@ namespace NLuaTest
lua.DoString("function test:overridableMethod(x,y) print(self[base]); return 6 end");
lua.DoString("luanet.make_object(test,'NLuaTest.TestTypes.TestClass')");
lua.DoString("a=TestClass.callOverridable(test,2,3)");
int a = (int)lua.GetNumber("a");
int a = lua.GetInteger("a");
lua.DoString("luanet.free_object(test)");
Assert.AreEqual(6, a);
}
......
using System;
using System;
using System.IO;
using NLua;
......@@ -45,8 +45,8 @@ namespace LoadFileTests
int color_g = (int)(double)lua["color.g"];
var func = (LuaFunction)lua["func"];
object[] res = func.Call(12, 34);
int x = (int)(double)res[0];
int y = (int)(double)res[1];
int x = (int)(long)res[0];
int y = (int)(long)res[1];
//function func(x,y)
// return x,x+y
//end
......@@ -82,9 +82,8 @@ namespace LoadFileTests
int color_g = (int)(double)lua["color.g"];
var func = (LuaFunction)lua["func"];
object[] res = func.Call(12, 34);
int x = (int)(double)res[0];
int y = (int)(double)res[1];
int x = (int)(long)res[0];
int y = (int)(long)res[1];
Assert.AreEqual(100, width);
Assert.AreEqual(200, height);
......
......@@ -755,8 +755,8 @@ namespace NLuaTest
{
lua.DoString("a={b={c=2}}");
LuaTable tab = lua.GetTable("a.b");
double num = (double)tab["c"];
Assert.AreEqual(num, 2d);
long num = (long)tab["c"];
Assert.AreEqual(2L, num);
}
}
/*
......@@ -770,8 +770,8 @@ namespace NLuaTest
{
lua.DoString("a={b={c=2}}");
LuaTable tab = lua.GetTable("a");
double num = (double)tab["b.c"];
Assert.AreEqual(num, 2d);
long num = (long)tab["b.c"];
Assert.AreEqual(2L, num);
}
}
/*
......@@ -875,8 +875,8 @@ namespace NLuaTest
{
lua.DoString("a=2\nfunction f()\na=3\nend");
lua.GetFunction("f").Call();
double num = lua.GetNumber("a");
Assert.AreEqual(num, 3d);
int num = lua.GetInteger("a");
Assert.AreEqual(num, 3);
}
}
/*
......@@ -919,7 +919,7 @@ namespace NLuaTest
object[] ret = lua.GetFunction("f").Call(3);
Assert.AreEqual(1, ret.Length);
Assert.AreEqual(5, (double)ret[0]);
Assert.AreEqual(5, ret[0]);
}
}
/*
......@@ -931,11 +931,11 @@ namespace NLuaTest
using (Lua lua = new Lua())
{
lua.DoString("function f(x,y)\nreturn x,x+y\nend");
object[] ret = lua.GetFunction("f").Call(3, 2);
object[] ret = lua.GetFunction("f").Call(3, 2.5);
Assert.AreEqual(2, ret.Length);
Assert.AreEqual(3, (double)ret[0]);
Assert.AreEqual(5, (double)ret[1]);
Assert.AreEqual(3, (long)ret[0]);
Assert.AreEqual(5.5, (double)ret[1]);
}
}
/*
......@@ -950,8 +950,8 @@ namespace NLuaTest
object[] ret = lua.GetFunction("a.f").Call(3, 2);
Assert.AreEqual(2, ret.Length);
Assert.AreEqual(3, (double)ret[0]);
Assert.AreEqual(5, (double)ret[1]);
Assert.AreEqual(3, ret[0]);
Assert.AreEqual(5, ret[1]);
}
}
/*
......@@ -2425,6 +2425,21 @@ namespace NLuaTest
}
}
[Test]
public void PassIntegerToLua()
{
long x = 0x70DEC0DEC0DEC0DE;
using (var lua = new Lua())
{
lua["x"] = x;
long l = lua.GetLong("x");
Assert.AreEqual(x, l);
}
}
static Lua m_lua;
......
......@@ -53,7 +53,7 @@
<Link>scripts\test_32.luac</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)..\scripts\test_64.luac" >
<None Include="$(MSBuildThisFileDirectory)..\scripts\test_64.luac">
<Link>scripts\test_64.luac</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
......
......@@ -6,5 +6,10 @@
{
return 1;
}
public T GetValue<T>()
{
return default(T);
}
}
}
\ No newline at end of file
......@@ -94,7 +94,8 @@ namespace NLuaTest.TestTypes
{
if (func != null)
{
return func.Call(1, 2);
object[] result = func.Call(1, 2);
return result;
}
return null;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment