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) public static ScriptNumber operator / (ScriptNumber a, ScriptNumber b)
{ {
if (!a.IsFloat && !b.IsFloat) 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) if (a.IsFloat && b.IsFloat)
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value / ((ScriptNumberDouble) b).Value); return new ScriptNumberDouble(((ScriptNumberDouble) a).Value / ((ScriptNumberDouble) b).Value);
if (a.IsFloat) if (a.IsFloat)

View File

@ -15,6 +15,6 @@ namespace Upsilon.BaseTypes.ScriptFunction
return null; 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 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; _method = method;
_object = o; _object = o;
_directTypeManipulation = directTypeManipulation; _directTypeManipulation = directTypeManipulation;
_passScriptReference = passScriptReference; _passScriptReference = passScriptReference;
_passScopeReference = passScopeReference;
ReturnType = _method.ReturnType; ReturnType = _method.ReturnType;
} }
@ -22,6 +25,7 @@ namespace Upsilon.BaseTypes.ScriptFunction
private readonly object _object; private readonly object _object;
private readonly bool _directTypeManipulation; private readonly bool _directTypeManipulation;
private readonly bool _passScriptReference; private readonly bool _passScriptReference;
private readonly bool _passScopeReference;
public System.Type ReturnType { get; } public System.Type ReturnType { get; }
public IEnumerable<UserDataMethod.UserDataMethodParameter> GetParameterInfo() public IEnumerable<UserDataMethod.UserDataMethodParameter> GetParameterInfo()
@ -29,7 +33,7 @@ namespace Upsilon.BaseTypes.ScriptFunction
return _method.GetMethods().First().Parameters; 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 var types = _directTypeManipulation
? variables.Select(x => x.GetType()).ToArray() ? variables.Select(x => x.GetType()).ToArray()
@ -44,6 +48,8 @@ namespace Upsilon.BaseTypes.ScriptFunction
var objects = new List<object>(); var objects = new List<object>();
if (_passScriptReference) if (_passScriptReference)
objects.Add(script); objects.Add(script);
if (_passScopeReference)
objects.Add(scope);
objects.AddRange(_directTypeManipulation objects.AddRange(_directTypeManipulation
? variables.Select(x => (object) x).ToList() ? variables.Select(x => (object) x).ToList()
: variables.Select(x => x.ToCSharpObject()).ToList()); : variables.Select(x => x.ToCSharpObject()).ToList());

View File

@ -19,7 +19,7 @@ namespace Upsilon.BaseTypes.ScriptFunction
EvaluationScope = evaluationScope; 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); var innerEvaluator = new Evaluator.Evaluator(diagnostics, EvaluationScope, script);
for (var i = 0; i < Parameters.Length; i++) for (var i = 0; i < Parameters.Length; i++)

View File

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

View File

@ -267,10 +267,26 @@ namespace Upsilon.Binder
if (indexerVariable.Type == Type.UserData) if (indexerVariable.Type == Type.UserData)
{ {
var bDefProperty = ((UserDataBoundTypeDefinition) ((FunctionParameterSymbol) indexerVariable) var bDefProperty = ((UserDataBoundTypeDefinition) ((FunctionParameterSymbol) indexerVariable)
.BoundTypeDefinition).Properties[fullStopIndexExpression.Index]; .BoundTypeDefinition).Properties[fullStopIndexExpression.Index.ToLowerInvariant()];
var boundDef = BoundTypeHandler.GetTypeDefinition(bDefProperty.ActualType); var boundDef = BoundTypeHandler.GetTypeDefinition(bDefProperty.ActualType);
return new FunctionParameterSymbol(fullStopIndexExpression.Index, boundDef); 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; return null;
} }
@ -699,7 +715,7 @@ namespace Upsilon.Binder
{ {
var functionParameter = (FunctionParameterSymbol) variableSymbol; var functionParameter = (FunctionParameterSymbol) variableSymbol;
var udBoundDef = (UserDataBoundTypeDefinition)functionParameter.BoundTypeDefinition; 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); return new BoundFullStopIndexExpression(expression, index, property.Type, e.Span);
} }

View File

@ -67,6 +67,16 @@ namespace Upsilon.Binder
// String equality // String equality
new BoundBinaryOperator(OperatorKind.Equality, Type.String, Type.String, Type.Boolean), new BoundBinaryOperator(OperatorKind.Equality, Type.String, Type.String, Type.Boolean),
new BoundBinaryOperator(OperatorKind.Inequality, 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) public static BoundBinaryOperator Bind(SyntaxKind operatorToken, Type left, Type right)

View File

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

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Upsilon.BaseTypes; using Upsilon.BaseTypes;
namespace Upsilon.BoundTypes namespace Upsilon.BoundTypes
@ -12,6 +13,38 @@ namespace Upsilon.BoundTypes
: base(Type.UserData, backingType) : base(Type.UserData, backingType)
{ {
Name = backingType.Name; 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) public UserDataBoundTypeDefinition(string name, Dictionary<string, UserDataBoundProperty> properties)
@ -26,7 +59,14 @@ namespace Upsilon.BoundTypes
{ {
public string Name { get; set; } public string Name { get; set; }
public Type Type { get; set; } public Type Type { get; set; }
public string ActualType { get; set; } public virtual string ActualType { get; set; }
public string Comment { 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); ls.Add(evaluate);
} }
var val = function.Run(_diagnostics, ls.ToArray(), _script); var val = function.Run(_diagnostics, ls.ToArray(), _script, Scope);
return val; return val;
} }

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using Upsilon.BaseTypes; using Upsilon.BaseTypes;
using Upsilon.Binder; using Upsilon.Binder;
@ -49,6 +50,17 @@ namespace Upsilon.Evaluator
Scope = Evaluator.Scope; 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) internal static Script ContinueWith(Script previousScript, string scriptString)
{ {
@ -56,6 +68,12 @@ namespace Upsilon.Evaluator
return s; 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() internal void Parse()
{ {
_parsed = Parser.Parser.Parse(_scriptString, Diagnostics, Options.SaveDataComments); _parsed = Parser.Parser.Parse(_scriptString, Diagnostics, Options.SaveDataComments);
@ -103,6 +121,11 @@ namespace Upsilon.Evaluator
return Convert<T>(Evaluator.Evaluate(Bind(), functionName, parameters)); return Convert<T>(Evaluator.Evaluate(Bind(), functionName, parameters));
} }
public Dictionary<string, ScriptType> GetVariables()
{
return Evaluator.Scope.Variables;
}
public T GetVariable<T>(string variableName) public T GetVariable<T>(string variableName)
{ {
if (!Scope.TryGet(variableName, out var variable)) 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; using Upsilon.Evaluator;
namespace Upsilon namespace Upsilon
@ -14,6 +15,15 @@ namespace Upsilon
return script; 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) public static Script ParseInputAndEvaluate(string input, ScriptOptions options = null)
{ {
if (options == null) options = DefaultOptions; if (options == null) options = DefaultOptions;
@ -23,6 +33,16 @@ namespace Upsilon
return script; 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) public static Script ContinueWith(Script script, string input)
{ {
var s = Script.ContinueWith(script, input); var s = Script.ContinueWith(script, input);
@ -30,6 +50,13 @@ namespace Upsilon
return s; 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) public static T EvaluateScript<T>(string input, ScriptOptions options = null)
{ {
var script = ParseInput(input, options); var script = ParseInput(input, options);

View File

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

View File

@ -20,5 +20,6 @@ namespace Upsilon
public BoundScope OverrideStaticBoundScope { get; set; } = null; public BoundScope OverrideStaticBoundScope { get; set; } = null;
public EvaluationScope OverrideStaticScope { 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;
using System.Collections.Generic;
using Upsilon.BaseTypes; using Upsilon.BaseTypes;
using Upsilon.BaseTypes.Number; using Upsilon.BaseTypes.Number;
using Upsilon.BaseTypes.ScriptTypeInterfaces; using Upsilon.BaseTypes.ScriptTypeInterfaces;
using Upsilon.Binder;
using Upsilon.Evaluator; using Upsilon.Evaluator;
// ReSharper disable UnusedMember.Global // ReSharper disable UnusedMember.Global
@ -39,10 +41,29 @@ namespace Upsilon.StandardLibraries
return new PairsScriptIterator(table); return new PairsScriptIterator(table);
} }
[StandardLibraryScriptFunction("require", "Loads a module from the module path, using the given script loader.", true)] private static readonly Dictionary<string, BoundScript> CachedBoundModules = new Dictionary<string, BoundScript>();
public void Require(Script script, string file)
{
[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() 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 CommentValue = attr.Comment
}); });
} }

View File

@ -5,15 +5,18 @@ namespace Upsilon.StandardLibraries
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class StandardLibraryScriptFunctionAttribute : Attribute 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; Name = name;
Comment = comment; Comment = comment;
PassScriptReference = passScriptReference; PassScriptReference = passScriptReference;
PassScopeReference = passScopeReference;
} }
public string Name { get; } public string Name { get; }
public string Comment { get; } public string Comment { get; }
public bool PassScriptReference { 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.BaseTypes.ScriptTypeInterfaces;
using Upsilon.Binder; using Upsilon.Binder;
using Upsilon.Binder.VariableSymbols; using Upsilon.Binder.VariableSymbols;
using Upsilon.BoundTypes;
using Upsilon.Evaluator; using Upsilon.Evaluator;
using Type = Upsilon.BaseTypes.Type; using Type = Upsilon.BaseTypes.Type;
@ -73,7 +74,8 @@ namespace Upsilon.StandardLibraries
public static void RegisterStaticVariable(string name, object value) public static void RegisterStaticVariable(string name, object value)
{ {
var luaVariable = value.ToScriptType(); 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); BoundScope.AssignToNearest(varSymbol);
Scope.AssignToNearest(varSymbol, luaVariable); Scope.AssignToNearest(varSymbol, luaVariable);
} }

View File

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