Upsilon/Upsilon/StandardLibraries/StaticScope.cs

153 lines
6.0 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
2018-12-05 16:20:28 +00:00
using System.Collections.Immutable;
2018-11-23 12:28:11 +00:00
using System.Linq;
using Upsilon.BaseTypes;
using Upsilon.BaseTypes.Number;
using Upsilon.BaseTypes.ScriptTypeInterfaces;
2018-11-23 12:28:11 +00:00
using Upsilon.Binder;
using Upsilon.Binder.VariableSymbols;
2018-12-03 17:32:27 +00:00
using Upsilon.BoundTypes;
2018-11-23 12:28:11 +00:00
using Upsilon.Evaluator;
using Type = Upsilon.BaseTypes.Type;
2018-11-23 12:28:11 +00:00
namespace Upsilon.StandardLibraries
{
public static class StaticScope
{
private static EvaluationScope _staticScope;
private static BoundScope _staticBoundScope;
public static EvaluationScope Scope
{
get
{
if (_staticScope != null)
return _staticScope;
var (evaluationScope, boundScope) = CreateStandardLibrary();
_staticScope = evaluationScope;
_staticBoundScope = boundScope;
return _staticScope;
}
}
public static BoundScope BoundScope
{
get
{
if (_staticBoundScope != null)
return _staticBoundScope;
var (evaluationScope, boundScope) = CreateStandardLibrary();
_staticScope = evaluationScope;
_staticBoundScope = boundScope;
return _staticBoundScope;
}
}
public static (EvaluationScope, BoundScope) CreateStandardLibrary()
{
var basicFunctions = new BasicFunctions().LoadMethods();
var funcs = new Dictionary<string, ScriptType>();
var boundFuncs = new Dictionary<string, VariableSymbol>();
foreach (var func in basicFunctions)
{
funcs.Add(func.Key, func.Value.MethodInfoFunction);
var functionSymbol = new InternalFunctionVariableSymbol(func.Key, true,
func.Value.MethodInfoFunction.ReturnType.GetScriptType(),
func.Value.MethodInfoFunction.GetParameterInfo().Select(typeInfo =>
{
var derivedType = DeriveValidTypes(typeInfo.Type);
return new InternalFunctionVariableSymbol.InternalFunctionParameter(derivedType,
typeInfo.IsOptional);
}).ToArray())
{
CommentValue = func.Value.CommentValue?.Split('\n')
};
boundFuncs.Add(func.Key, functionSymbol);
}
var scope = new EvaluationScope(funcs);
var boundScope = new BoundScope(boundFuncs, null);
2018-11-23 12:28:11 +00:00
return (scope, boundScope);
}
public static void RegisterStaticVariable(string name, object value)
{
var luaVariable = value.ToScriptType();
2018-12-03 17:32:27 +00:00
var ubDef = BoundTypeHandler.GetTypeDefinition(value.GetType());
2018-12-05 16:20:28 +00:00
VariableSymbol varSymbol = null;
if (ubDef != null)
{
varSymbol = new FunctionParameterSymbol(name, ubDef);
}
else
{
var type = value.GetType();
if (type.IsGenericType)
{
var generic = type.GetGenericTypeDefinition();
2018-12-06 14:45:19 +00:00
if (generic.FullName != null && generic.FullName.StartsWith("System.Func"))
2018-12-05 16:20:28 +00:00
{
varSymbol = BuildFunctionVariableSymbol(name, type);
}
2018-12-06 14:45:19 +00:00
else if (generic.FullName != null && generic.FullName.StartsWith("System.Action"))
{
varSymbol = BuildActionVariableSymbol(name, type);
}
2018-12-05 16:20:28 +00:00
}
if (varSymbol == null)
throw new Exception("Unknown type: " + type);
}
2018-11-24 11:42:54 +00:00
BoundScope.AssignToNearest(varSymbol);
Scope.AssignToNearest(varSymbol, luaVariable);
2018-11-23 12:28:11 +00:00
}
2018-12-05 16:20:28 +00:00
private static VariableSymbol BuildFunctionVariableSymbol(string name, System.Type type)
{
var genericParameters = type.GetGenericArguments();
2018-12-06 14:45:19 +00:00
var parameters = new List<InternalFunctionVariableSymbol.InternalFunctionParameter>();
2018-12-05 16:20:28 +00:00
for (var i = 0; i < genericParameters.Length - 1; i++)
{
var t = genericParameters[i].GetScriptType();
parameters.Add(new InternalFunctionVariableSymbol.InternalFunctionParameter(t, false));
}
var result = genericParameters[parameters.Count - 1].GetScriptType();
return new InternalFunctionVariableSymbol(name, true, result, parameters.ToArray());
}
2018-12-06 14:45:19 +00:00
private static VariableSymbol BuildActionVariableSymbol(string name, System.Type type)
{
var genericParameters = type.GetGenericArguments();
var parameters = new List<InternalFunctionVariableSymbol.InternalFunctionParameter>();
for (var i = 0; i < genericParameters.Length; i++)
{
var t = genericParameters[i].GetScriptType();
parameters.Add(new InternalFunctionVariableSymbol.InternalFunctionParameter(t, false));
}
return new InternalFunctionVariableSymbol(name, true, Type.Nil, parameters.ToArray());
}
private static Type DeriveValidTypes(System.Type type)
{
if (type == typeof(ScriptString))
return Type.String;
if (typeof(ScriptNumber).IsAssignableFrom(type))
return Type.Number;
if (type == typeof(ScriptBoolean))
return Type.Boolean;
if (type == typeof(IIterable))
return Type.Table | Type.UserData;
if (typeof(ScriptTable).IsAssignableFrom(type))
return Type.Table;
2018-11-30 15:51:18 +00:00
if (type == typeof(ScriptType))
// allows every type
return (Type) 255;
2018-12-05 14:14:31 +00:00
if (type.IsEnum)
return Type.Number;
return Type.UserData;
}
2018-11-23 12:28:11 +00:00
}
}