General fixes tweaks and things

This commit is contained in:
Deukhoofd 2018-12-03 18:32:27 +01:00
parent 6ba3860e84
commit 5b0ce2e52c
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
20 changed files with 240 additions and 28 deletions

View File

@ -44,7 +44,7 @@ namespace Upsilon.BaseTypes.Number
public static ScriptNumber operator / (ScriptNumber a, ScriptNumber b)
{
if (!a.IsFloat && !b.IsFloat)
return new ScriptNumberLong(((ScriptNumberLong) a).Value / ((ScriptNumberLong) b).Value);
return new ScriptNumberDouble(((ScriptNumberLong) a).Value / (double)((ScriptNumberLong) b).Value);
if (a.IsFloat && b.IsFloat)
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value / ((ScriptNumberDouble) b).Value);
if (a.IsFloat)

View File

@ -15,6 +15,6 @@ namespace Upsilon.BaseTypes.ScriptFunction
return null;
}
public abstract ScriptType Run(Diagnostics diagnostics, ScriptType[] variables, Script script);
public abstract ScriptType Run(Diagnostics diagnostics, ScriptType[] variables, Script script, EvaluationScope scope);
}
}

View File

@ -9,12 +9,15 @@ namespace Upsilon.BaseTypes.ScriptFunction
{
internal class ScriptMethodInfoFunction : ScriptFunction
{
public ScriptMethodInfoFunction(UserDataMethod method, object o, bool directTypeManipulation, bool passScriptReference = false)
public ScriptMethodInfoFunction(UserDataMethod method, object o, bool directTypeManipulation,
bool passScriptReference = false, bool passScopeReference = false)
{
_method = method;
_object = o;
_directTypeManipulation = directTypeManipulation;
_passScriptReference = passScriptReference;
_passScopeReference = passScopeReference;
ReturnType = _method.ReturnType;
}
@ -22,6 +25,7 @@ namespace Upsilon.BaseTypes.ScriptFunction
private readonly object _object;
private readonly bool _directTypeManipulation;
private readonly bool _passScriptReference;
private readonly bool _passScopeReference;
public System.Type ReturnType { get; }
public IEnumerable<UserDataMethod.UserDataMethodParameter> GetParameterInfo()
@ -29,7 +33,7 @@ namespace Upsilon.BaseTypes.ScriptFunction
return _method.GetMethods().First().Parameters;
}
public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables, Script script)
public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables, Script script, EvaluationScope scope)
{
var types = _directTypeManipulation
? variables.Select(x => x.GetType()).ToArray()
@ -44,6 +48,8 @@ namespace Upsilon.BaseTypes.ScriptFunction
var objects = new List<object>();
if (_passScriptReference)
objects.Add(script);
if (_passScopeReference)
objects.Add(scope);
objects.AddRange(_directTypeManipulation
? variables.Select(x => (object) x).ToList()
: variables.Select(x => x.ToCSharpObject()).ToList());

View File

@ -19,7 +19,7 @@ namespace Upsilon.BaseTypes.ScriptFunction
EvaluationScope = evaluationScope;
}
public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables, Script script)
public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables, Script script, EvaluationScope scope)
{
var innerEvaluator = new Evaluator.Evaluator(diagnostics, EvaluationScope, script);
for (var i = 0; i < Parameters.Length; i++)

View File

@ -100,9 +100,10 @@ namespace Upsilon.BaseTypes
return Type.Table;
if (t == typeof(IIterable))
return Type.Nil;
if (t == typeof(ScriptType))
return Type.Unknown;
throw new ArgumentException(t.ToString());
return Type.UserData;
}
}

View File

@ -267,10 +267,26 @@ namespace Upsilon.Binder
if (indexerVariable.Type == Type.UserData)
{
var bDefProperty = ((UserDataBoundTypeDefinition) ((FunctionParameterSymbol) indexerVariable)
.BoundTypeDefinition).Properties[fullStopIndexExpression.Index];
.BoundTypeDefinition).Properties[fullStopIndexExpression.Index.ToLowerInvariant()];
var boundDef = BoundTypeHandler.GetTypeDefinition(bDefProperty.ActualType);
return new FunctionParameterSymbol(fullStopIndexExpression.Index, boundDef);
}
if (indexerVariable.Type == Type.Unknown)
{
if (indexerVariable is FunctionParameterSymbol funcSymbol)
{
var boundProp = funcSymbol.BoundTypeDefinition;
if (boundProp is UserDataBoundTypeDefinition bProp)
{
var property = bProp.Properties[fullStopIndexExpression.Index.ToLowerInvariant()];
var boundDef = BoundTypeHandler.GetTypeDefinition(property.ActualType);
return new FunctionParameterSymbol(fullStopIndexExpression.Index, boundDef);
}
}
return new VariableSymbol(fullStopIndexExpression.Index, Type.Unknown, true);
}
}
return null;
}
@ -699,7 +715,7 @@ namespace Upsilon.Binder
{
var functionParameter = (FunctionParameterSymbol) variableSymbol;
var udBoundDef = (UserDataBoundTypeDefinition)functionParameter.BoundTypeDefinition;
if (udBoundDef.Properties.TryGetValue(index, out var property))
if (udBoundDef.Properties.TryGetValue(index.ToLowerInvariant(), out var property))
{
return new BoundFullStopIndexExpression(expression, index, property.Type, e.Span);
}

View File

@ -67,6 +67,16 @@ namespace Upsilon.Binder
// String equality
new BoundBinaryOperator(OperatorKind.Equality, Type.String, Type.String, Type.Boolean),
new BoundBinaryOperator(OperatorKind.Inequality, Type.String, Type.String, Type.Boolean),
// general nil checks
new BoundBinaryOperator(OperatorKind.Equality, Type.String, Type.Nil, Type.Boolean),
new BoundBinaryOperator(OperatorKind.Inequality, Type.String, Type.Nil, Type.Boolean),
new BoundBinaryOperator(OperatorKind.Equality, Type.UserData, Type.Nil, Type.Boolean),
new BoundBinaryOperator(OperatorKind.Inequality, Type.UserData, Type.Nil, Type.Boolean),
new BoundBinaryOperator(OperatorKind.Equality, Type.Table, Type.Nil, Type.Boolean),
new BoundBinaryOperator(OperatorKind.Inequality, Type.Table, Type.Nil, Type.Boolean),
new BoundBinaryOperator(OperatorKind.Equality, Type.Unknown, Type.Nil, Type.Boolean),
new BoundBinaryOperator(OperatorKind.Inequality, Type.Unknown, Type.Nil, Type.Boolean),
};
public static BoundBinaryOperator Bind(SyntaxKind operatorToken, Type left, Type right)

View File

@ -1,5 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Upsilon.BaseTypes;
namespace Upsilon.BoundTypes
@ -38,6 +39,10 @@ namespace Upsilon.BoundTypes
}
return null;
}
public static BoundTypeDefinition GetTypeDefinition(System.Type type)
{
return _typeDefinitions.Values.FirstOrDefault(x => x.ValidInternalTypes.Contains(type));
}
public static void LoadUserDataTypeDefinition(UserDataBoundTypeDefinition def)
{

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using Upsilon.BaseTypes;
namespace Upsilon.BoundTypes
@ -12,6 +13,38 @@ namespace Upsilon.BoundTypes
: base(Type.UserData, backingType)
{
Name = backingType.Name;
Properties = new Dictionary<string, UserDataBoundProperty>();
var fields = backingType.GetFields().Select(x => new UserDataBoundProperty()
{
Name = x.Name,
ActualType = x.FieldType.Name,
Type = x.FieldType.GetScriptType(),
});
foreach (var f in fields)
{
Properties.Add(f.Name.ToLowerInvariant(), f);
}
var properties = backingType.GetProperties().Select(x => new UserDataBoundProperty()
{
Name = x.Name,
ActualType = x.PropertyType.Name,
Type = x.PropertyType.GetScriptType(),
});
foreach (var f in properties)
{
Properties.Add(f.Name.ToLowerInvariant(), f);
}
var methods = backingType.GetMethods().Select(x => new UserDataBoundMethod()
{
Name = x.Name,
Type = Type.Function,
ResultType = x.ReturnType.GetScriptType()
});
foreach (var f in methods)
{
Properties.Add(f.Name.ToLowerInvariant(), f);
}
}
public UserDataBoundTypeDefinition(string name, Dictionary<string, UserDataBoundProperty> properties)
@ -26,7 +59,14 @@ namespace Upsilon.BoundTypes
{
public string Name { get; set; }
public Type Type { get; set; }
public string ActualType { get; set; }
public virtual string ActualType { get; set; }
public string Comment { get; set; }
}
public class UserDataBoundMethod: UserDataBoundProperty
{
public override string ActualType => "Function";
public Type ResultType { get; set; }
}
}

View File

@ -484,7 +484,7 @@ namespace Upsilon.Evaluator
ls.Add(evaluate);
}
var val = function.Run(_diagnostics, ls.ToArray(), _script);
var val = function.Run(_diagnostics, ls.ToArray(), _script, Scope);
return val;
}

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Upsilon.BaseTypes;
using Upsilon.Binder;
@ -49,6 +50,17 @@ namespace Upsilon.Evaluator
Scope = Evaluator.Scope;
}
private Script(BoundScript boundScript, Binder.Binder binder, Evaluator evaluator, ScriptOptions options)
{
Options = options;
_bound = boundScript;
Diagnostics = new Diagnostics(ScriptString, options.ThrowExceptionOnError);
Binder = Upsilon.Binder.Binder.CreateWithSetScope(Diagnostics, binder.Scope);
Evaluator = Evaluator.CreateWithSetScope(Diagnostics, evaluator.Scope, this);
Scope = Evaluator.Scope;
}
internal static Script ContinueWith(Script previousScript, string scriptString)
{
@ -56,6 +68,12 @@ namespace Upsilon.Evaluator
return s;
}
internal static Script ContinueWith(Script previousScript, BoundScript boundScript)
{
var s = new Script(boundScript, previousScript.Binder, previousScript.Evaluator, previousScript.Options);
return s;
}
internal void Parse()
{
_parsed = Parser.Parser.Parse(_scriptString, Diagnostics, Options.SaveDataComments);
@ -103,6 +121,11 @@ namespace Upsilon.Evaluator
return Convert<T>(Evaluator.Evaluate(Bind(), functionName, parameters));
}
public Dictionary<string, ScriptType> GetVariables()
{
return Evaluator.Scope.Variables;
}
public T GetVariable<T>(string variableName)
{
if (!Scope.TryGet(variableName, out var variable))

View File

@ -0,0 +1,55 @@
using System.IO;
namespace Upsilon.Evaluator
{
public class ScriptLoader
{
public virtual string FilePath { get; } = "./";
public virtual string ModulesPath { get; } = "./modules/";
public virtual string LoadFile(string fileName)
{
var path = FilePath;
var resolvedName = ResolveFileName(FilePath, fileName);
if (File.Exists(resolvedName))
{
return File.ReadAllText(resolvedName);
}
else if (File.Exists(resolvedName + ".yup"))
{
return File.ReadAllText(resolvedName + ".yup");
}
else if (File.Exists(resolvedName + ".lua"))
{
return File.ReadAllText(resolvedName + ".lua");
}
return null;
}
public virtual string LoadModule(string fileName)
{
var resolvedName = ResolveFileName(ModulesPath, fileName);
string text = null;
if (File.Exists(resolvedName))
{
text = File.ReadAllText(resolvedName);
}
else if (File.Exists(resolvedName + ".yup"))
{
text = File.ReadAllText(resolvedName + ".yup");
}
else if (File.Exists(resolvedName + ".lua"))
{
text = File.ReadAllText(resolvedName + ".lua");
}
return text;
}
public virtual string ResolveFileName(string path, string fileName)
{
return Path.Combine(path, fileName);
}
}
}

View File

@ -1,3 +1,4 @@
using Upsilon.Binder;
using Upsilon.Evaluator;
namespace Upsilon
@ -14,6 +15,15 @@ namespace Upsilon
return script;
}
public static Script ParseFile(string fileName, ScriptOptions options = null)
{
if (options == null) options = DefaultOptions;
var input = options.ScriptLoader.LoadFile(fileName);
var script = new Script(input, options);
script.Parse();
return script;
}
public static Script ParseInputAndEvaluate(string input, ScriptOptions options = null)
{
if (options == null) options = DefaultOptions;
@ -23,6 +33,16 @@ namespace Upsilon
return script;
}
public static Script ParseFileAndEvaluate(string fileName, ScriptOptions options = null)
{
if (options == null) options = DefaultOptions;
var input = options.ScriptLoader.LoadFile(fileName);
var script = new Script(input, options);
script.Parse();
script.Evaluate();
return script;
}
public static Script ContinueWith(Script script, string input)
{
var s = Script.ContinueWith(script, input);
@ -30,6 +50,13 @@ namespace Upsilon
return s;
}
public static Script ContinueWith(Script script, BoundScript bound)
{
var s = Script.ContinueWith(script, bound);
s.Parse();
return s;
}
public static T EvaluateScript<T>(string input, ScriptOptions options = null)
{
var script = ParseInput(input, options);

View File

@ -70,10 +70,6 @@ namespace Upsilon.Parser
{
return ParseAssignmentExpression();
}
if (Current.Kind == SyntaxKind.Identifier && Next.Kind == SyntaxKind.Comma)
{
return ParseAssignmentExpression();
}
if (Current.Kind == SyntaxKind.IfKeyword)
{
return ParseIfStatement(SyntaxKind.IfKeyword);

View File

@ -20,5 +20,6 @@ namespace Upsilon
public BoundScope OverrideStaticBoundScope { get; set; } = null;
public EvaluationScope OverrideStaticScope { get; set; } = null;
public ScriptLoader ScriptLoader { get; set; } = null;
}
}

View File

@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using Upsilon.BaseTypes;
using Upsilon.BaseTypes.Number;
using Upsilon.BaseTypes.ScriptTypeInterfaces;
using Upsilon.Binder;
using Upsilon.Evaluator;
// ReSharper disable UnusedMember.Global
@ -39,10 +41,29 @@ namespace Upsilon.StandardLibraries
return new PairsScriptIterator(table);
}
[StandardLibraryScriptFunction("require", "Loads a module from the module path, using the given script loader.", true)]
public void Require(Script script, string file)
{
private static readonly Dictionary<string, BoundScript> CachedBoundModules = new Dictionary<string, BoundScript>();
[StandardLibraryScriptFunction("require", "Loads a module from the module path, using the given script loader.",
true)]
public ScriptType Require(Script script, string file)
{
var loader = script.Options.ScriptLoader;
if (loader != null)
{
if (!CachedBoundModules.TryGetValue(file, out var boundScript))
{
var loadedScript = loader.LoadModule(file);
boundScript = Executor.ParseInput(loadedScript).Bind();
CachedBoundModules.Add(file, boundScript);
}
var s = Executor.ContinueWith(script, boundScript);
var val = s.Evaluate();
if (val != null)
{
return val.ToScriptType();
}
}
return new ScriptNull();
}

View File

@ -19,7 +19,8 @@ namespace Upsilon.StandardLibraries
{
dictionary.Add(attr.Name, new LoadedStandardFunction()
{
MethodInfoFunction = new ScriptMethodInfoFunction(new UserDataMethod(methodInfo), this, true),
MethodInfoFunction = new ScriptMethodInfoFunction(new UserDataMethod(methodInfo),
this, true, attr.PassScriptReference, attr.PassScopeReference),
CommentValue = attr.Comment
});
}

View File

@ -5,15 +5,18 @@ namespace Upsilon.StandardLibraries
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class StandardLibraryScriptFunctionAttribute : Attribute
{
public StandardLibraryScriptFunctionAttribute(string name, string comment = null, bool passScriptReference = false)
public StandardLibraryScriptFunctionAttribute(string name, string comment = null,
bool passScriptReference = false, bool passScopeReference = false)
{
Name = name;
Comment = comment;
PassScriptReference = passScriptReference;
PassScopeReference = passScopeReference;
}
public string Name { get; }
public string Comment { get; }
public bool PassScriptReference { get; }
public bool PassScopeReference { get; }
}
}

View File

@ -6,6 +6,7 @@ using Upsilon.BaseTypes.Number;
using Upsilon.BaseTypes.ScriptTypeInterfaces;
using Upsilon.Binder;
using Upsilon.Binder.VariableSymbols;
using Upsilon.BoundTypes;
using Upsilon.Evaluator;
using Type = Upsilon.BaseTypes.Type;
@ -73,7 +74,8 @@ namespace Upsilon.StandardLibraries
public static void RegisterStaticVariable(string name, object value)
{
var luaVariable = value.ToScriptType();
var varSymbol = new VariableSymbol(name, luaVariable.Type, false);
var ubDef = BoundTypeHandler.GetTypeDefinition(value.GetType());
var varSymbol = new FunctionParameterSymbol(name, ubDef);
BoundScope.AssignToNearest(varSymbol);
Scope.AssignToNearest(varSymbol, luaVariable);
}

View File

@ -10,6 +10,11 @@ namespace Upsilon.Text
public SourceText(string text)
{
_text = text;
if (string.IsNullOrEmpty(text))
{
_lines = new SourceTextLine[0];
return;
}
var lines = text.Split(new[] {Environment.NewLine}, StringSplitOptions.None);
_lines = new SourceTextLine[lines.Length];
var linePos = 0;