Message reporting if indexable value does not exist

This commit is contained in:
Deukhoofd 2018-11-20 17:33:51 +01:00
parent 2f8c295675
commit fe4a8d25ad
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
9 changed files with 61 additions and 27 deletions

View File

@ -1,11 +1,12 @@
using Upsilon.Evaluator; using Upsilon.Evaluator;
using Upsilon.Text;
namespace Upsilon.BaseTypes namespace Upsilon.BaseTypes
{ {
internal interface IIndexable internal interface IIndexable
{ {
LuaType Get(string s, EvaluationScope scope); LuaType Get(Diagnostics diagnostics, TextSpan span, string s, EvaluationScope scope);
void Set(string s, LuaType value); void Set(Diagnostics diagnostics, TextSpan span, string s, LuaType value);
} }
internal interface IScopeOwner internal interface IScopeOwner

View File

@ -1,6 +1,7 @@
using System; using System;
using Upsilon.BaseTypes.Number; using Upsilon.BaseTypes.Number;
using Upsilon.Evaluator; using Upsilon.Evaluator;
using Upsilon.Text;
namespace Upsilon.BaseTypes namespace Upsilon.BaseTypes
{ {
@ -78,13 +79,13 @@ namespace Upsilon.BaseTypes
return Value; return Value;
} }
public LuaType Get(string s, EvaluationScope scope) public LuaType Get(Diagnostics diagnostics, TextSpan span, string s, EvaluationScope scope)
{ {
var i = int.Parse(s); var i = int.Parse(s);
return new LuaString(Value[i - 1].ToString()); return new LuaString(Value[i - 1].ToString());
} }
public void Set(string s, LuaType value) public void Set(Diagnostics diagnostics, TextSpan span, string s, LuaType value)
{ {
throw new NotSupportedException(); throw new NotSupportedException();
} }

View File

@ -1,6 +1,7 @@
using System.Linq; using System.Linq;
using Upsilon.Binder; using Upsilon.Binder;
using Upsilon.Evaluator; using Upsilon.Evaluator;
using Upsilon.Text;
namespace Upsilon.BaseTypes namespace Upsilon.BaseTypes
{ {
@ -20,19 +21,19 @@ namespace Upsilon.BaseTypes
return EvaluationScope.Variables.ToDictionary(x => x.Key, x => x.Value.ToCSharpObject()); return EvaluationScope.Variables.ToDictionary(x => x.Key, x => x.Value.ToCSharpObject());
} }
public LuaType Get(Diagnostics diagnostics, TextSpan span, string s, EvaluationScope scope)
public LuaType Get(string s, EvaluationScope scope)
{ {
if (EvaluationScope.TryGet(s, out var o)) if (EvaluationScope.TryGet(s, out var o))
{ {
return o; return o;
} }
diagnostics.LogError("Cannot find member 's' on Table", span);
return new LuaNull(); return new LuaNull();
} }
public void Set(string s, LuaType obj) public void Set(Diagnostics diagnostics, TextSpan span, string s, LuaType value)
{ {
EvaluationScope.Set(new VariableSymbol(s, obj.Type, false), obj); EvaluationScope.Set(new VariableSymbol(s, value.Type, false), value);
} }
} }
} }

View File

@ -1,4 +1,5 @@
using Upsilon.Evaluator; using Upsilon.Evaluator;
using Upsilon.Text;
namespace Upsilon.BaseTypes.UserData namespace Upsilon.BaseTypes.UserData
{ {
@ -19,14 +20,23 @@ namespace Upsilon.BaseTypes.UserData
return Value; return Value;
} }
public LuaType Get(string s, EvaluationScope scope) public LuaType Get(Diagnostics diagnostics, TextSpan span, string s, EvaluationScope scope)
{ {
return _typeInfo.Get(Value, s); var (type, failed) = _typeInfo.Get(Value, s);
if (failed)
{
diagnostics.LogError($"Cannot find member '{s}' on type '{Value.GetType()}'", span);
}
return type;
} }
public void Set(string s, LuaType value) public void Set(Diagnostics diagnostics, TextSpan span, string s, LuaType value)
{ {
_typeInfo.Set(Value, s, value); var failed = _typeInfo.Set(Value, s, value);
if (failed)
{
diagnostics.LogError($"Cannot find member '{s}' on type '{Value.GetType()}'", span);
}
} }
} }
} }

View File

@ -19,40 +19,43 @@ namespace Upsilon.BaseTypes.UserData
private Dictionary<string, PropertyInfo> Properties { get; } private Dictionary<string, PropertyInfo> Properties { get; }
private Dictionary<string, MethodInfo> Methods { get; } private Dictionary<string, MethodInfo> Methods { get; }
public LuaType Get(object value, string member) public (LuaType Type, bool Failed) Get(object value, string member)
{ {
if (value.GetType() != Type) if (value.GetType() != Type)
return null; return (null, true);
member = member.ToLowerInvariant(); member = member.ToLowerInvariant();
if (Variables.TryGetValue(member, out var info)) if (Variables.TryGetValue(member, out var info))
{ {
return info.GetValue(value).ToLuaType(); return (info.GetValue(value).ToLuaType(), false);
} }
if (Properties.TryGetValue(member, out var property)) if (Properties.TryGetValue(member, out var property))
{ {
return property.GetValue(value).ToLuaType(); return (property.GetValue(value).ToLuaType(), false);
} }
if (Methods.TryGetValue(member, out var method)) if (Methods.TryGetValue(member, out var method))
{ {
return new LuaMethodInfoFunction(method, value); return (new LuaMethodInfoFunction(method, value), false);
} }
return (null, true);
return null;
} }
public void Set(object value, string member, LuaType newValue) public bool Set(object value, string member, LuaType newValue)
{ {
member = member.ToLowerInvariant(); member = member.ToLowerInvariant();
if (value.GetType() != Type) if (value.GetType() != Type)
return; return true;
if (Variables.TryGetValue(member, out var info)) if (Variables.TryGetValue(member, out var info))
{ {
info.SetValue(value, newValue.ToCSharpObject()); info.SetValue(value, newValue.ToCSharpObject());
return false;
} }
if (Properties.TryGetValue(member, out var property)) if (Properties.TryGetValue(member, out var property))
{ {
property.SetValue(value, newValue.ToCSharpObject()); property.SetValue(value, newValue.ToCSharpObject());
return false;
} }
return true;
} }
} }
} }

View File

@ -1,7 +1,10 @@
using Upsilon.Text;
namespace Upsilon.Binder namespace Upsilon.Binder
{ {
public abstract class BoundNode public abstract class BoundNode
{ {
public abstract BoundKind Kind { get; } public abstract BoundKind Kind { get; }
public TextSpan Span { get; protected set; }
} }
} }

View File

@ -304,7 +304,6 @@ namespace Upsilon.Evaluator
private LuaType EvaluateTableExpression(BoundTableExpression e) private LuaType EvaluateTableExpression(BoundTableExpression e)
{ {
var dic = new Dictionary<VariableSymbol, LuaType>();
var tableScope = EvaluationScope.CreateWithGetOnlyParent(Scope); var tableScope = EvaluationScope.CreateWithGetOnlyParent(Scope);
var innerEvaluator = new Evaluator(_diagnostics, tableScope); var innerEvaluator = new Evaluator(_diagnostics, tableScope);
var currentPos = 1; var currentPos = 1;
@ -347,7 +346,7 @@ namespace Upsilon.Evaluator
scope = scopeOwner.EvaluationScope; scope = scopeOwner.EvaluationScope;
} }
var indexer = EvaluateExpression(e.Index); var indexer = EvaluateExpression(e.Index);
return indexable.Get(indexer.ToString(), scope); return indexable.Get(_diagnostics, e.Span, indexer.ToString(), scope);
} }
private LuaType EvaluateFullStopIndexExpression(BoundFullStopIndexExpression e) private LuaType EvaluateFullStopIndexExpression(BoundFullStopIndexExpression e)
{ {
@ -363,7 +362,7 @@ namespace Upsilon.Evaluator
scope = scopeOwner.EvaluationScope; scope = scopeOwner.EvaluationScope;
} }
return indexable.Get(e.Index, scope); return indexable.Get(_diagnostics, e.Span, e.Index, scope);
} }
private void EvaluateTableAssignmentStatement(BoundTableAssigmentStatement e) private void EvaluateTableAssignmentStatement(BoundTableAssigmentStatement e)
@ -386,7 +385,7 @@ namespace Upsilon.Evaluator
{ {
throw new Exception("Cant assign to that"); throw new Exception("Cant assign to that");
} }
indexable.Set(index.ToString(), value); indexable.Set(_diagnostics, e.Span, index.ToString(), value);
} }
} }
} }

View File

@ -54,8 +54,7 @@ return table[""test""]
var script = new Script(input); var script = new Script(input);
Assert.Empty(script.Diagnostics.Messages); Assert.Empty(script.Diagnostics.Messages);
var evaluated = script.Evaluate(); var evaluated = script.Evaluate();
Assert.Empty(script.Diagnostics.Messages); Assert.Single(script.Diagnostics.Messages);
Assert.Null(evaluated);
} }
[Fact] [Fact]

View File

@ -25,6 +25,7 @@ namespace UpsilonTests
{ {
public string FieldString = "TestField"; public string FieldString = "TestField";
public string FieldStringSet; public string FieldStringSet;
private string _privateTestField = "hidden";
public bool TestMethodHasRun { get; private set; } public bool TestMethodHasRun { get; private set; }
public void TestMethod() public void TestMethod()
@ -104,5 +105,21 @@ end
Assert.Empty(script.Diagnostics.Messages); Assert.Empty(script.Diagnostics.Messages);
Assert.Equal(result, 120); Assert.Equal(result, 120);
} }
[Fact]
public void CantAccessHiddenFields()
{
var obj = new UserDataHelper();
const string input = @"
function test(o)
return o._privateTestField
end
";
var script = new Script(input);
Assert.Empty(script.Diagnostics.Messages);
script.EvaluateFunction("test", new[] {obj});
Assert.Single(script.Diagnostics.Messages);
}
} }
} }