From fe4a8d25ad789e67f3557f1469a846123d35b11e Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Tue, 20 Nov 2018 17:33:51 +0100 Subject: [PATCH] Message reporting if indexable value does not exist --- Upsilon/BaseTypes/IIndexable.cs | 5 +++-- Upsilon/BaseTypes/LuaString.cs | 5 +++-- Upsilon/BaseTypes/LuaTable.cs | 9 +++++---- Upsilon/BaseTypes/UserData/UserData.cs | 18 ++++++++++++++---- Upsilon/BaseTypes/UserData/UserDataType.cs | 21 ++++++++++++--------- Upsilon/Binder/BoundNode.cs | 3 +++ Upsilon/Evaluator/Evaluator.cs | 7 +++---- UpsilonTests/TableTests.cs | 3 +-- UpsilonTests/UserDataTests.cs | 17 +++++++++++++++++ 9 files changed, 61 insertions(+), 27 deletions(-) diff --git a/Upsilon/BaseTypes/IIndexable.cs b/Upsilon/BaseTypes/IIndexable.cs index 45ea7d3..6dc6062 100644 --- a/Upsilon/BaseTypes/IIndexable.cs +++ b/Upsilon/BaseTypes/IIndexable.cs @@ -1,11 +1,12 @@ using Upsilon.Evaluator; +using Upsilon.Text; namespace Upsilon.BaseTypes { internal interface IIndexable { - LuaType Get(string s, EvaluationScope scope); - void Set(string s, LuaType value); + LuaType Get(Diagnostics diagnostics, TextSpan span, string s, EvaluationScope scope); + void Set(Diagnostics diagnostics, TextSpan span, string s, LuaType value); } internal interface IScopeOwner diff --git a/Upsilon/BaseTypes/LuaString.cs b/Upsilon/BaseTypes/LuaString.cs index 386c9e5..cf794da 100644 --- a/Upsilon/BaseTypes/LuaString.cs +++ b/Upsilon/BaseTypes/LuaString.cs @@ -1,6 +1,7 @@ using System; using Upsilon.BaseTypes.Number; using Upsilon.Evaluator; +using Upsilon.Text; namespace Upsilon.BaseTypes { @@ -78,13 +79,13 @@ namespace Upsilon.BaseTypes 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); 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(); } diff --git a/Upsilon/BaseTypes/LuaTable.cs b/Upsilon/BaseTypes/LuaTable.cs index 06d1fd3..34c9192 100644 --- a/Upsilon/BaseTypes/LuaTable.cs +++ b/Upsilon/BaseTypes/LuaTable.cs @@ -1,6 +1,7 @@ using System.Linq; using Upsilon.Binder; using Upsilon.Evaluator; +using Upsilon.Text; namespace Upsilon.BaseTypes { @@ -20,19 +21,19 @@ namespace Upsilon.BaseTypes return EvaluationScope.Variables.ToDictionary(x => x.Key, x => x.Value.ToCSharpObject()); } - - public LuaType Get(string s, EvaluationScope scope) + public LuaType Get(Diagnostics diagnostics, TextSpan span, string s, EvaluationScope scope) { if (EvaluationScope.TryGet(s, out var o)) { return o; } + diagnostics.LogError("Cannot find member 's' on Table", span); 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); } } } \ No newline at end of file diff --git a/Upsilon/BaseTypes/UserData/UserData.cs b/Upsilon/BaseTypes/UserData/UserData.cs index 5a28bcc..22fc877 100644 --- a/Upsilon/BaseTypes/UserData/UserData.cs +++ b/Upsilon/BaseTypes/UserData/UserData.cs @@ -1,4 +1,5 @@ using Upsilon.Evaluator; +using Upsilon.Text; namespace Upsilon.BaseTypes.UserData { @@ -19,14 +20,23 @@ namespace Upsilon.BaseTypes.UserData 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); + } } } } \ No newline at end of file diff --git a/Upsilon/BaseTypes/UserData/UserDataType.cs b/Upsilon/BaseTypes/UserData/UserDataType.cs index a6814da..5a4b267 100644 --- a/Upsilon/BaseTypes/UserData/UserDataType.cs +++ b/Upsilon/BaseTypes/UserData/UserDataType.cs @@ -19,40 +19,43 @@ namespace Upsilon.BaseTypes.UserData private Dictionary Properties { get; } private Dictionary Methods { get; } - public LuaType Get(object value, string member) + public (LuaType Type, bool Failed) Get(object value, string member) { if (value.GetType() != Type) - return null; + return (null, true); member = member.ToLowerInvariant(); 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)) { - return property.GetValue(value).ToLuaType(); + return (property.GetValue(value).ToLuaType(), false); } if (Methods.TryGetValue(member, out var method)) { - return new LuaMethodInfoFunction(method, value); + return (new LuaMethodInfoFunction(method, value), false); } - - return null; + return (null, true); } - public void Set(object value, string member, LuaType newValue) + public bool Set(object value, string member, LuaType newValue) { member = member.ToLowerInvariant(); if (value.GetType() != Type) - return; + return true; if (Variables.TryGetValue(member, out var info)) { info.SetValue(value, newValue.ToCSharpObject()); + return false; } if (Properties.TryGetValue(member, out var property)) { property.SetValue(value, newValue.ToCSharpObject()); + return false; } + + return true; } } } \ No newline at end of file diff --git a/Upsilon/Binder/BoundNode.cs b/Upsilon/Binder/BoundNode.cs index 87639d6..40ddcfa 100644 --- a/Upsilon/Binder/BoundNode.cs +++ b/Upsilon/Binder/BoundNode.cs @@ -1,7 +1,10 @@ +using Upsilon.Text; + namespace Upsilon.Binder { public abstract class BoundNode { public abstract BoundKind Kind { get; } + public TextSpan Span { get; protected set; } } } \ No newline at end of file diff --git a/Upsilon/Evaluator/Evaluator.cs b/Upsilon/Evaluator/Evaluator.cs index 7c074c6..e55df56 100644 --- a/Upsilon/Evaluator/Evaluator.cs +++ b/Upsilon/Evaluator/Evaluator.cs @@ -304,7 +304,6 @@ namespace Upsilon.Evaluator private LuaType EvaluateTableExpression(BoundTableExpression e) { - var dic = new Dictionary(); var tableScope = EvaluationScope.CreateWithGetOnlyParent(Scope); var innerEvaluator = new Evaluator(_diagnostics, tableScope); var currentPos = 1; @@ -347,7 +346,7 @@ namespace Upsilon.Evaluator scope = scopeOwner.EvaluationScope; } 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) { @@ -363,7 +362,7 @@ namespace Upsilon.Evaluator scope = scopeOwner.EvaluationScope; } - return indexable.Get(e.Index, scope); + return indexable.Get(_diagnostics, e.Span, e.Index, scope); } private void EvaluateTableAssignmentStatement(BoundTableAssigmentStatement e) @@ -386,7 +385,7 @@ namespace Upsilon.Evaluator { throw new Exception("Cant assign to that"); } - indexable.Set(index.ToString(), value); + indexable.Set(_diagnostics, e.Span, index.ToString(), value); } } } \ No newline at end of file diff --git a/UpsilonTests/TableTests.cs b/UpsilonTests/TableTests.cs index fc8d149..a75d507 100644 --- a/UpsilonTests/TableTests.cs +++ b/UpsilonTests/TableTests.cs @@ -54,8 +54,7 @@ return table[""test""] var script = new Script(input); Assert.Empty(script.Diagnostics.Messages); var evaluated = script.Evaluate(); - Assert.Empty(script.Diagnostics.Messages); - Assert.Null(evaluated); + Assert.Single(script.Diagnostics.Messages); } [Fact] diff --git a/UpsilonTests/UserDataTests.cs b/UpsilonTests/UserDataTests.cs index d5542a6..a191a77 100644 --- a/UpsilonTests/UserDataTests.cs +++ b/UpsilonTests/UserDataTests.cs @@ -25,6 +25,7 @@ namespace UpsilonTests { public string FieldString = "TestField"; public string FieldStringSet; + private string _privateTestField = "hidden"; public bool TestMethodHasRun { get; private set; } public void TestMethod() @@ -104,5 +105,21 @@ end Assert.Empty(script.Diagnostics.Messages); 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); + } + } } \ No newline at end of file