diff --git a/README.md b/README.md index 6f6b718..8424ee2 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,12 @@ namespace TestSLThree ### LANG and REPL compatibility +Starting from language version 0.8.0, REPL no longer supports multiple versions at once and is built for each language update. + | REPL version | LANG version | |-----------------|-----------------| -| 2.0.0 | 0.7.0+ | +| 2.0.0 | 0.7.0 | | 1.* | 0.2.0 — 0.6.0 | ### Download -[![stable](https://img.shields.io/badge/REPL_stable-2.0.0-00cc00)](https://github.com/AIexandrKotov/SLThree/releases/tag/0.7.0) [![stable](https://img.shields.io/badge/LANG_exp-0.7.0-ccaa00)](https://github.com/AIexandrKotov/SLThree/releases/tag/0.7.0) \ No newline at end of file +[![stable](https://img.shields.io/badge/stable-0.8.0-00cc00)](https://github.com/AIexandrKotov/SLThree/releases/tag/0.8.0) \ No newline at end of file diff --git a/SLThree.HTMLCreator/HTMLCreator.cs b/SLThree.HTMLCreator/HTMLCreator.cs index cb17b79..fa4a25e 100644 --- a/SLThree.HTMLCreator/HTMLCreator.cs +++ b/SLThree.HTMLCreator/HTMLCreator.cs @@ -114,42 +114,7 @@ public override void VisitExpression(TypenameExpression expression) CurrentString.Append(Replace(">")); } } - public void VisitExpression(CreatorContext expression, bool newline, bool hasnew) - { - if (hasnew) - CurrentString.Append(GetKeyword1("new context ")); - else - CurrentString.Append(GetKeyword1("context ")); - if (expression.HasName) - { - CurrentString.Append(expression.Name + " "); - } - if (expression.HasCast) - { - CurrentString.Append(": "); - VisitExpression(expression.Typecast); - CurrentString.Append(" "); - } - if (expression.HasBody) - { - CurrentString.Append("{ "); - CurrentTab += 1; - foreach (var x in expression.Body) - { - if (newline) Newline(); - else CurrentString.Append(" "); - VisitStatement(x); - } - CurrentTab -= 1; - if (newline) Newline(); - else CurrentString.Append(" "); - CurrentString.Append("}"); - } - } - public override void VisitExpression(CreatorContext expression) - { - VisitExpression(expression, ContextElementNewLine, true); - } + public override void VisitExpression(MemberAccess expression) { VisitExpression(expression.Left); @@ -167,7 +132,7 @@ public override void VisitExpression(InvokeExpression expression) if (memberAccess.Right is NameExpression nameExpression1) CurrentString.Append(GetCall(nameExpression1.Name)); } - else if (expression.Left is LambdaExpression lambda) + else if (expression.Left is FunctionDefinition lambda) { CurrentString.Append("("); VisitExpression(lambda); @@ -420,7 +385,8 @@ public override void VisitExpression(NameExpression expression) VisitExpression(expression.TypeHint); CurrentString.Append(" "); } - CurrentString.Append(expression.Name); + if (expression.Name == "constructor") CurrentString.Append(GetKeyword1("constructor")); + else CurrentString.Append(expression.Name); } public override void VisitExpression(UnaryOperator expression) { @@ -479,18 +445,32 @@ public override void VisitExpression(InterpolatedString expression) CurrentString = sb; CurrentString.Append(GetString("$\"" + string.Format(expression.Value, arr) + "\"")); } - public override void VisitExpression(LambdaExpression expression) + public override void VisitExpression(FunctionDefinition expression) { foreach (var x in expression.Modificators) { CurrentString.Append(GetKeyword1(x)); - CurrentString.Append(" "); + } + if (expression.FunctionName != null) + { + if (expression.Modificators.Length > 0) CurrentString.Append(" "); + VisitExpression(expression.FunctionName); + } + if (expression.GenericArguments.Length > 0) + { + CurrentString.Append(Replace("<")); + for (var i = 0; i < expression.GenericArguments.Length; i++) + { + CurrentString.Append(GetTypeSpan(expression.GenericArguments[i].Name)); + if (i != expression.GenericArguments.Length - 1) CurrentString.Append(", "); + } + CurrentString.Append(Replace(">")); } CurrentString.Append("("); - for (var i = 0; i < expression.Left.Arguments.Length; i++) + for (var i = 0; i < expression.Arguments.Length; i++) { - VisitExpression(expression.Left.Arguments[i]); - if (i != expression.Left.Arguments.Length - 1) CurrentString.Append(", "); + VisitExpression(expression.Arguments[i]); + if (i != expression.Arguments.Length - 1) CurrentString.Append(", "); } CurrentString.Append(")"); if (expression.ReturnTypeHint != null) @@ -498,16 +478,16 @@ public override void VisitExpression(LambdaExpression expression) CurrentString.Append(": "); VisitExpression(expression.ReturnTypeHint); } - CurrentString.Append(Replace(" => ")); - if (expression.Right.Statements.Length == 1 && expression.Right.Statements[0] is ReturnStatement ret && ret.Expression != null) + if (expression.FunctionBody.Statements.Length == 1 && expression.FunctionBody.Statements[0] is ReturnStatement ret && ret.Expression != null) { + CurrentString.Append(Replace(" => ")); VisitExpression(ret.Expression); } else { CurrentString.Append(" {"); CurrentTab += 1; - foreach (var x in expression.Right.Statements) + foreach (var x in expression.FunctionBody.Statements) { Newline(); VisitStatement(x); @@ -517,42 +497,40 @@ public override void VisitExpression(LambdaExpression expression) CurrentString.Append("}"); } } - public override void VisitExpression(LambdaGenericExpression expression) + + public void VisitExpression(CreatorUsing expression, bool hasnew) { - foreach (var x in expression.Modificators) + if (hasnew) + CurrentString.Append(GetKeyword1("new ")); + CurrentString.Append(GetKeyword1("using ")); + VisitExpression(expression.Type); + } + public override void VisitExpression(CreatorContext expression) + { + CurrentString.Append(GetKeyword1(expression.CreatorBody == null || expression.CreatorBody.Statements.Length == 0 ? "new context" : "context")); + if (expression.HasName) { - CurrentString.Append(GetKeyword1(x)); CurrentString.Append(" "); + VisitExpression(expression.Name); } - CurrentString.Append(Replace("<")); - for (var i = 0; i < expression.Generics.Length; i++) - { - CurrentString.Append(GetTypeSpan(expression.Generics[i].Name)); - if (i != expression.Generics.Length - 1) CurrentString.Append(", "); - } - CurrentString.Append(Replace(">")); - CurrentString.Append("("); - for (var i = 0; i < expression.Left.Arguments.Length; i++) - { - VisitExpression(expression.Left.Arguments[i]); - if (i != expression.Left.Arguments.Length - 1) CurrentString.Append(", "); - } - CurrentString.Append(")"); - if (expression.ReturnTypeHint != null) + RestOfContext(expression); + } + public void RestOfContext(CreatorContext expression) + { + if (expression.Ancestors.Length > 0) { CurrentString.Append(": "); - VisitExpression(expression.ReturnTypeHint); - } - CurrentString.Append(Replace(" => ")); - if (expression.Right.Statements.Length == 1 && expression.Right.Statements[0] is ReturnStatement ret) - { - VisitExpression(ret.Expression); + for (var i = 0; i < expression.Ancestors.Length; i++) + { + VisitExpression(expression.Ancestors[i]); + if (i != expression.Ancestors.Length - 1) CurrentString.Append(", "); + } } - else + if (expression.CreatorBody != null && expression.CreatorBody.Statements.Length > 0) { - CurrentString.Append(" {"); + CurrentString.Append(" {\n"); CurrentTab += 1; - foreach (var x in expression.Right.Statements) + foreach (var x in (expression.CreatorBody).Statements) { Newline(); VisitStatement(x); @@ -562,28 +540,31 @@ public override void VisitExpression(LambdaGenericExpression expression) CurrentString.Append("}"); } } - public void VisitExpression(CreatorUsing expression, bool hasnew) - { - if (hasnew) - CurrentString.Append(GetKeyword1("new ")); - CurrentString.Append(GetKeyword1("using ")); - VisitExpression(expression.Type); - } public override void VisitExpression(CreatorUsing expression) { VisitExpression(expression, true); } - public override void VisitExpression(NewExpression expression) + public override void VisitExpression(CreatorInstance expression) { CurrentString.Append(GetKeyword1("new ")); - VisitExpression(expression.Typename); - CurrentString.Append("("); - for (var i = 0; i < expression.Arguments.Length; i++) + VisitExpression(expression.Type); + if (expression.Arguments.Length > 0) { - VisitExpression(expression.Arguments[i]); - if (i < expression.Arguments.Length - 1) CurrentString.Append(", "); + CurrentString.Append("("); + for (var i = 0; i < expression.Arguments.Length; i++) + { + VisitExpression(expression.Arguments[i]); + if (i < expression.Arguments.Length - 1) CurrentString.Append(", "); + } + CurrentString.Append(")"); } - CurrentString.Append(")"); + if (expression.Name != null) + { + CurrentString.Append(" "); + VisitExpression(expression.Name); + } + if (expression.CreatorContext != null) + RestOfContext(expression.CreatorContext); } public override void VisitExpression(ReflectionExpression expression) { @@ -592,13 +573,13 @@ public override void VisitExpression(ReflectionExpression expression) VisitExpression(expression.Right); if (expression.MethodGenericArguments?.Length > 0) { - CurrentString.Append("<"); + CurrentString.Append(Replace("<")); for (var i = 0; i < expression.MethodGenericArguments.Length; i++) { VisitExpression(expression.MethodGenericArguments[i]); if (i < expression.MethodGenericArguments.Length - 1) CurrentString.Append(", "); } - CurrentString.Append(">"); + CurrentString.Append(Replace(">")); } if (expression.MethodArguments?.Length > 0) { @@ -612,11 +593,12 @@ public override void VisitExpression(ReflectionExpression expression) CurrentString.Append(")"); } } - - public override void VisitStatement(ContextStatement statement) + public override void VisitExpression(StaticExpression expression) { - VisitExpression(statement.Creator, ContextElementNewLine, false); + CurrentString.Append(GetKeyword1("static ")); + VisitExpression(expression.Right); } + public override void VisitStatement(BreakStatement statement) { CurrentString.Append(GetKeyword2("break") + ";"); @@ -625,13 +607,13 @@ public override void VisitStatement(ContinueStatement statement) { CurrentString.Append(GetKeyword2("continue") + ";"); } - public override void VisitStatement(UsingStatement statement) + public override void VisitExpression(UsingExpression statement) { VisitExpression(statement.Using, false); if (statement.Alias != null) { CurrentString.Append(GetKeyword1( " as ")); - CurrentString.Append(statement.Alias.Name); + VisitExpression(statement.Alias); } CurrentString.Append(";"); } @@ -736,13 +718,13 @@ public override void VisitStatement(ForeachLoopStatement statement) CurrentString.Append("}"); } } - public override void VisitStatement(ConditionStatement statement) + public override void VisitExpression(ConditionExpression expression) { CurrentString.Append(GetKeyword2("if") + " ("); - VisitExpression(statement.Condition); + VisitExpression(expression.Condition); CurrentString.Append(")"); - var ifbody = statement.IfBody; + var ifbody = expression.IfBody; if (ifbody.Length < 2) { CurrentTab += 1; @@ -765,7 +747,7 @@ public override void VisitStatement(ConditionStatement statement) } - var elsebody = statement.ElseBody; + var elsebody = expression.ElseBody; if (elsebody.Length == 0) return; Newline(); CurrentString.Append(GetKeyword2("else ")); @@ -821,6 +803,14 @@ public override void VisitStatement(WhileLoopStatement statement) public override void VisitStatement(ExpressionStatement statement) { base.VisitExpression(statement.Expression); + if (statement.Expression is ConditionExpression + || (statement.Expression is CreatorContext cont && (cont.CreatorBody != null && cont.CreatorBody.Statements.Length > 0)) + || (statement.Expression is CreatorInstance inst && inst.CreatorContext?.CreatorBody != null) + || statement.Expression is MatchExpression + || (statement.Expression is FunctionDefinition func && !(func.FunctionBody.Statements.Length == 1 && func.FunctionBody.Statements[0] is ReturnStatement ret && !ret.VoidReturn))) + { + return; + } CurrentString.Append(";"); } diff --git a/SLThree.HTMLCreator/slthree.css b/SLThree.HTMLCreator/slthree.css.txt similarity index 100% rename from SLThree.HTMLCreator/slthree.css rename to SLThree.HTMLCreator/slthree.css.txt diff --git a/SLThree/.msbump b/SLThree/.msbump deleted file mode 100644 index b6e665a..0000000 --- a/SLThree/.msbump +++ /dev/null @@ -1,3 +0,0 @@ -{ - BumpRevision: true -} \ No newline at end of file diff --git a/SLThree/ContextWrap.cs b/SLThree/ContextWrap.cs index 7e07687..5449852 100644 --- a/SLThree/ContextWrap.cs +++ b/SLThree/ContextWrap.cs @@ -26,15 +26,16 @@ public string ToDetailedString(int index, List outed_contexts) sb.AppendLine($"context {Context.Name} {{"); foreach (var x in Context.LocalVariables.GetAsDictionary()) { - - sb.Append($"{(index == 0 ? "" : new string(' ', index * 4))}{x.Key} = "); + sb.Append($"{(index == 0 ? "" : new string(' ', index * 4))}"); if (x.Value is ContextWrap wrap) { + if (wrap.Context.Name != x.Key) sb.Append($"{x.Key} = "); if (outed_contexts.Contains(wrap)) sb.AppendLine($"context {wrap.Context.Name}; //already printed"); else sb.AppendLine(wrap.ToDetailedString(index + 1, outed_contexts) + ";"); } else if (x.Value is ClassAccess ca) { + sb.Append($"{x.Key} = "); var first = false; foreach (var line in ca.ToString().Split(new string[1] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) { @@ -43,7 +44,14 @@ public string ToDetailedString(int index, List outed_contexts) first = true; } } - else sb.AppendLine(Decoration(x.Value)?.ToString() ?? "null" + ";"); + else + { + if (!(x.Value is Method m && m.Name == x.Key)) + { + sb.Append($"{x.Key} = "); + } + sb.AppendLine(Decoration(x.Value)?.ToString() ?? "null" + ";"); + } } index -= 1; sb.Append($"{(index == 0 ? "" : new string(' ', index * 4))}}}"); @@ -60,11 +68,25 @@ public string ToShortString() sb.AppendLine($"context {Context.Name} {{"); foreach (var x in Context.LocalVariables.GetAsDictionary()) { - - sb.Append($"{(index == 0 ? "" : new string(' ', index * 4))}{x.Key} = "); - if (x.Value is ContextWrap wrap) sb.AppendLine($"context {wrap.Context.Name};"); - else if (x.Value is ClassAccess maca) sb.AppendLine($"access to {maca.Name.GetTypeString()};"); - else sb.AppendLine((Decoration(x.Value)?.ToString() ?? "null") + ";"); + sb.Append($"{(index == 0 ? "" : new string(' ', index * 4))}"); + if (x.Value is ContextWrap wrap) + { + if (wrap.Context.Name != x.Key) sb.Append($"{x.Key} = "); + sb.AppendLine($"context {wrap.Context.Name};"); + } + else if (x.Value is ClassAccess maca) + { + sb.Append($"{x.Key} = "); + sb.AppendLine($"access to {maca.Name.GetTypeString()};"); + } + else + { + if (!(x.Value is Method m && m.Name == x.Key)) + { + sb.Append($"{x.Key} = "); + } + sb.AppendLine((Decoration(x.Value)?.ToString() ?? "null") + ";"); + } } index -= 1; sb.Append($"{(index == 0 ? "" : new string(' ', index * 4))}}}"); diff --git a/SLThree/Embedding/EmbeddingExtensions.cs b/SLThree/Embedding/EmbeddingExtensions.cs index c8bb210..c10c646 100644 --- a/SLThree/Embedding/EmbeddingExtensions.cs +++ b/SLThree/Embedding/EmbeddingExtensions.cs @@ -16,18 +16,5 @@ public static ExecutionContext RunScript(this ExecutionContext context, string c { return Parser.This.RunScript(code, null, context); } - - public static T Unwrap(this ExecutionContext context) => Wrapper.Unwrap(context); - public static void UnwrapStatic(this ExecutionContext context) => Wrapper.UnwrapStatic(context); - public static ExecutionContext Wrap(this T obj) => Wrapper.Wrap(obj); - public static ExecutionContext WrapStatic() => Wrapper.WrapStatic(); - public static void UnwrapStaticClass(this ExecutionContext context, Type type) => NonGenericWrapper.GetWrapper(type).UnwrapStaticClass(context); - public static void UnwrapStaticClass(this Type type, ExecutionContext context) => NonGenericWrapper.GetWrapper(type).UnwrapStaticClass(context); - public static ExecutionContext WrapStaticClass(this Type type) => NonGenericWrapper.GetWrapper(type).WrapStaticClass(); - - public static T SafeUnwrap(this ExecutionContext context) => Wrapper.SafeUnwrap(context); - public static void SafeUnwrapStatic(this ExecutionContext context) => Wrapper.SafeUnwrapStatic(context); - public static void SafeUnwrapStaticClass(this ExecutionContext context, Type type) => NonGenericWrapper.GetWrapper(type).SafeUnwrapStaticClass(context); - public static void SafeUnwrapStaticClass(this Type type, ExecutionContext context) => NonGenericWrapper.GetWrapper(type).SafeUnwrapStaticClass(context); } } diff --git a/SLThree/Exceptions/SpecificErrors.cs b/SLThree/Exceptions/SpecificErrors.cs new file mode 100644 index 0000000..3d0d9a7 --- /dev/null +++ b/SLThree/Exceptions/SpecificErrors.cs @@ -0,0 +1,19 @@ +using System; + +namespace SLThree +{ + /// + /// Исключения во время работы программы + /// + [Serializable] + public class AbstractInvokation : RuntimeError + { + public AbstractInvokation() : base() { } + public AbstractInvokation(SourceContext context) : base(GetErrorText(), context) { } + + public static string GetErrorText() + { + return $"Trying to invoke abstract method"; + } + } +} diff --git a/SLThree/ExecutionContext.cs b/SLThree/ExecutionContext.cs index 83b0eec..1442a4c 100644 --- a/SLThree/ExecutionContext.cs +++ b/SLThree/ExecutionContext.cs @@ -1,4 +1,5 @@ using SLThree.Extensions; +using SLThree.Extensions.Cloning; using System; using System.Collections; using System.Collections.Generic; @@ -9,6 +10,7 @@ namespace SLThree { +#pragma warning disable IDE1006 // Стили именования public class ExecutionContext { public interface IExecutable @@ -32,6 +34,7 @@ public interface IExecutable internal bool Returned; internal bool Broken; internal bool Continued; + internal int Creations = 0; public object ReturnedValue; @@ -44,33 +47,34 @@ static ExecutionContext() } - public ExecutionContext(bool assign_to_global, bool create_private = true) + public ExecutionContext(bool assign_to_global, bool create_private = true, LocalVariablesContainer localVariables = null) { + LocalVariables = localVariables ?? new LocalVariablesContainer(); @this = new ContextWrap(this); wrap = new ContextWrap(this); if (create_private) @private = new ContextWrap(new ExecutionContext(this, false)); if (assign_to_global) SuperContext = global.Context; } - - public ExecutionContext(ExecutionContext context, bool create_private = true) + public ExecutionContext(ExecutionContext context, bool create_private = true, LocalVariablesContainer localVariables = null) { + LocalVariables = localVariables ?? new LocalVariablesContainer(); @this = new ContextWrap(this); wrap = new ContextWrap(this); if (create_private) @private = new ContextWrap(new ExecutionContext(this, false)); if (context != null) SuperContext = context; } - - public ExecutionContext() : this(true, true) { } + public ExecutionContext() : this(true, true, null) { } public ContextWrap @this; internal ExecutionContext PreviousContext; //public ContextWrap pred => new ContextWrap(PreviousContext); public readonly ContextWrap wrap; - internal ContextWrap super; - public readonly ContextWrap @private; + public ContextWrap super; + public ContextWrap @private; + public ContextWrap parent; internal ExecutionContext SuperContext { get => super?.Context; set => super = new ContextWrap(value); } public IEnumerable GetHierarchy() @@ -112,6 +116,76 @@ public void DefaultEnvironment() } - public readonly LocalVariablesContainer LocalVariables = new LocalVariablesContainer(); + public ExecutionContext CreateInstance(ExecutionContext definitioncontext, Method constructor, object[] args) + { + var ret = new ExecutionContext(definitioncontext); + ret.Name = $"{Name}@{Convert.ToString(Creations++, 16).ToUpper().PadLeft(4, '0')}"; + ret.parent = wrap; + constructor.@this = ret.wrap; + constructor.GetValue(ret, args); + return ret; + } + public ExecutionContext CreateInstance(object[] args, SourceContext sourceContext) + { + var ret = new ExecutionContext(super.Context); + ret.Name = $"{Name}@{Convert.ToString(Creations++, 16).ToUpper().PadLeft(4, '0')}"; + ret.parent = wrap; + if (LocalVariables.GetValue("constructor").Item1 is Method constructor) + { + if (constructor.ParamNames.Length != args.Length) + throw new RuntimeError("Call constructor with wrong arguments count", sourceContext); + constructor.@this = ret.wrap; + constructor.GetValue(ret, args); + } + return ret; + } + public void Implementation(ExecutionContext ret, Method constructor, object[] args) + { + constructor.@this = ret.wrap; + constructor.GetValue(ret, args); + } + public void Implementation(ExecutionContext ret, object[] args, SourceContext sourceContext) + { + if (LocalVariables.GetValue("constructor").Item1 is Method constructor) + { + if (constructor.ParamNames.Length != args.Length) + throw new RuntimeError("Call constructor with wrong arguments count", sourceContext); + constructor.@this = ret.wrap; + constructor.GetValue(ret, args); + } + } + + public readonly LocalVariablesContainer LocalVariables; + + internal ExecutionContext copy(ExecutionContext context) + { + LocalVariables.FillOther(context.LocalVariables); + //if (context.@private != null && @private != null) + // @private.Context.LocalVariables.FillOther(context.@private.Context.LocalVariables); + return this; + } + + public static object virtualize(object o, ExecutionContext context) + { + if (o is Method method) + { + method = method.CloneWithNewName(method.Name); + method.identity(context.wrap); + return method; + } + return o; + } + + internal ExecutionContext implement(ExecutionContext context) + { + var vars = context.LocalVariables.Variables; + foreach (var x in context.LocalVariables.NamedIdentificators) + { + var o = vars[x.Value]; + LocalVariables.SetValue(x.Key, virtualize(o, this)); + } + return this; + } } +#pragma warning restore IDE1006 // Стили именования } diff --git a/SLThree/Expressions/CastExpression.cs b/SLThree/Expressions/CastExpression.cs index 4e4a7a4..94ada7b 100644 --- a/SLThree/Expressions/CastExpression.cs +++ b/SLThree/Expressions/CastExpression.cs @@ -24,7 +24,7 @@ public CastExpression(BaseExpression left, TypenameExpression type, SourceContex public override object GetValue(ExecutionContext context) { - if (normal) return WrappersTypeSetting.UnwrapCast(Type.GetValue(context).Cast(), Left.GetValue(context)); + if (normal) return Wrapper.UnwrapCast(Type.GetValue(context).Cast(), Left.GetValue(context)); else return Left.DropPriority(); } diff --git a/SLThree/Statements/ConditionStatement.cs b/SLThree/Expressions/ConditionExpression.cs similarity index 71% rename from SLThree/Statements/ConditionStatement.cs rename to SLThree/Expressions/ConditionExpression.cs index d920f0b..5d8f025 100644 --- a/SLThree/Statements/ConditionStatement.cs +++ b/SLThree/Expressions/ConditionExpression.cs @@ -3,13 +3,13 @@ namespace SLThree { - public class ConditionStatement : BaseStatement + public class ConditionExpression : BaseExpression { public BaseExpression Condition { get; set; } public BaseStatement[] Body { get; set; } - public ConditionStatement() { } - public ConditionStatement(BaseExpression condition, BaseStatement[] body, int falsestart, SourceContext context) : base(context) + public ConditionExpression() { } + public ConditionExpression(BaseExpression condition, BaseStatement[] body, int falsestart, SourceContext context) : base(context) { Condition = condition; Body = body; @@ -17,7 +17,7 @@ public ConditionStatement(BaseExpression condition, BaseStatement[] body, int fa this.falsestart = falsestart; } - public ConditionStatement(BaseExpression condition, StatementList trueBlock, StatementList falseBlock, SourceContext context) : base(context) + public ConditionExpression(BaseExpression condition, StatementList trueBlock, StatementList falseBlock, SourceContext context) : base(context) { Condition = condition; count = trueBlock.Statements.Length + falseBlock.Statements.Length; @@ -32,7 +32,7 @@ public ConditionStatement(BaseExpression condition, StatementList trueBlock, Sta public BaseStatement[] IfBody => Body.Take(falsestart).ToArray(); public BaseStatement[] ElseBody => Body.Skip(falsestart).ToArray(); - public override string ToString() => $"if ({Condition}) {{{Body}}}"; + public override string ExpressionToString() => $"if ({Condition}) {{{Body}}}"; public override object GetValue(ExecutionContext context) { @@ -50,7 +50,7 @@ public override object GetValue(ExecutionContext context) public override object Clone() { - return new ConditionStatement(Condition.CloneCast(), Body.CloneArray(), falsestart, SourceContext.CloneCast()); + return new ConditionExpression(Condition.CloneCast(), Body.CloneArray(), falsestart, SourceContext.CloneCast()); } } } diff --git a/SLThree/Expressions/Creators/CreatorContext.cs b/SLThree/Expressions/Creators/CreatorContext.cs index 3b28066..8b025f2 100644 --- a/SLThree/Expressions/Creators/CreatorContext.cs +++ b/SLThree/Expressions/Creators/CreatorContext.cs @@ -1,61 +1,88 @@ using SLThree.Extensions; using SLThree.Extensions.Cloning; -using System; using System.Linq; namespace SLThree { public class CreatorContext : BaseExpression { - public NameExpression Name; - public TypenameExpression Typecast; - public BaseStatement[] Body; + /* + ---Creating instances--- + new context Name: TBase + new context Name + new context: TBase + new context - public bool HasCast => Typecast != null; - public bool HasName => Name != null; - public bool HasBody => Body.Length > 0; - - public CreatorContext(SourceContext context) : this(null, null, new BaseStatement[0], context) { } - - public CreatorContext(NameExpression name, SourceContext context) : this(name, null, new BaseStatement[0], context) { } - - public CreatorContext(NameExpression name, TypenameExpression typecast, SourceContext context) : this(name, typecast, new BaseStatement[0], context) { } - - public CreatorContext(BaseStatement[] body, SourceContext context) : this(null, null, body, context) { } + context Name: TBase {} + context Name {} + context: TBase {} + context {} + */ + public BaseExpression Name { get; set; } + public BaseExpression[] Ancestors { get; set; } + public CreatorContextBody CreatorBody { get; set; } + public bool IsFreeCreator { get; set; } - public CreatorContext(TypenameExpression typecast, SourceContext context) : this(null, typecast, new BaseStatement[0], context) { } + public bool HasName => Name != null; - public CreatorContext(NameExpression name, TypenameExpression typecast, BaseStatement[] body, SourceContext context) : base(context) + public CreatorContext(BaseExpression name, BaseExpression[] ancestors, CreatorContextBody body, bool is_free_creator, SourceContext context) : base(context) { Name = name; - Typecast = typecast; - Body = body; + Ancestors = ancestors; + CreatorBody = body; + IsFreeCreator = is_free_creator; } + public CreatorContext(BaseExpression name, BaseExpression[] ancestors, CreatorContextBody body, SourceContext context) + : this(name, ancestors, body, true, context) { } + public CreatorContext(BaseExpression name, CreatorContextBody body, SourceContext context) + : this(name, new BaseExpression[0], body, true, context) { } + public CreatorContext(BaseExpression[] ancestors, CreatorContextBody body, SourceContext context) + : this(null, ancestors, body, true, context) { } + public CreatorContext(CreatorContextBody body, SourceContext context) + : this(null, new BaseExpression[0], body, true, context) { } + public CreatorContext(BaseExpression name, BaseExpression[] ancestors, SourceContext context) + : this(name, ancestors, null, true, context) { } + public CreatorContext(BaseExpression name, SourceContext context) + : this(name, new BaseExpression[0], null, true, context) { } + public CreatorContext(BaseExpression[] ancestors, SourceContext context) + : this(null, ancestors, null, true, context) { } + public CreatorContext(SourceContext context) + : this(null, new BaseExpression[0], null, true, context) { } - public override string ExpressionToString() => $"new context {(HasName ? Name.Name : "")} {(HasCast ? $": {Typecast}" : "")} {{\n{Body.JoinIntoString("\n")}\n}}"; + public override string ExpressionToString() => $"context {(HasName ? Name.ToString() : "")} {{\n{CreatorBody}\n}}"; - private string last_context_name; - public string LastContextName => last_context_name; + private ExecutionContext counted_invoked; + private bool is_name_expr; + private int variable_index; - public override object GetValue(ExecutionContext context) + private string GetName() => GetLastName(Name); + public static string GetLastName(BaseExpression name) { - var ret = new ExecutionContext(context); - if (HasName) ret.Name = Name.Name; - last_context_name = ret.Name; - if (HasBody) + name.PrioriryRaised = false; + var n = name.ToString(); + var index = n.LastIndexOf('.'); + if (index == -1) return n; + else return n.Substring(index + 1); + } + + public object GetValue(ExecutionContext target, ExecutionContext context) + { + var ret = new ExecutionContext(target); + for (var i = 0; i < Ancestors.Length; i++) + ret.implement(Ancestors[i].GetValue(target).Cast().Context); + CreatorBody?.GetValue(ret, context); + var wrap = ret.wrap; + if (HasName) { - for (var i = 0; i < Body.Length; i++) - { - if (Body[i] is ExpressionStatement es && es.Expression is BinaryAssign assign) - assign.AssignValue(ret, assign.Left, assign.Right.GetValue(context)); - else if (Body[i] is ContextStatement cs) - cs.GetValue(ret); - } + ret.Name = GetName(); + if (IsFreeCreator) + BinaryAssign.AssignToValue(target, Name, wrap, ref counted_invoked, ref is_name_expr, ref variable_index); } - if (HasCast) return new ContextWrap(ret).CastToType(Typecast.GetValue(context).Cast()); - return new ContextWrap(ret); + return wrap; } - public override object Clone() => new CreatorContext(Name.CloneCast(), Typecast.CloneCast(), Body?.CloneArray(), SourceContext.CloneCast()); + public override object GetValue(ExecutionContext context) => GetValue(context, context); + + public override object Clone() => new CreatorContext(Name.CloneCast(), Ancestors.CloneArray(), CreatorBody.CloneCast(), IsFreeCreator, SourceContext.CloneCast()); } } diff --git a/SLThree/Expressions/Creators/CreatorInstance.cs b/SLThree/Expressions/Creators/CreatorInstance.cs new file mode 100644 index 0000000..c5f02e8 --- /dev/null +++ b/SLThree/Expressions/Creators/CreatorInstance.cs @@ -0,0 +1,215 @@ +using SLThree.Extensions; +using SLThree.Extensions.Cloning; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SLThree +{ + public class CreatorInstance : BaseExpression + { + /* + ---Creating instances--- + new T; + new T {}; + new T(args); + new T(args) {}; + new T: TBase; + new T: TBase {}; + new T(args): TBase; + new T(args): TBase {}; + ---With name assignation + new T Name; + new T Name {}; + new T(args) Name; + new T(args) Name {}; + new T Name: TBase; + new T Name: TBase {}; + new T(args) Name: TBase; + new T(args) Name: TBase {}; + */ + public static CreatorInstance CaseType(TypenameExpression type, SourceContext context) + => new CreatorInstance( + type, + null, + new BaseExpression[0], + null, + context); + public static CreatorInstance CaseTypeBody(TypenameExpression type, CreatorContextBody body, SourceContext context) + => new CreatorInstance( + type, + null, + new BaseExpression[0], + new CreatorContext(null, new BaseExpression[0], body, false, context), + context); + public static CreatorInstance CaseTypeArgs(TypenameExpression type, BaseExpression[] args, SourceContext context) + => new CreatorInstance( + type, + null, + args, + null, + context); + public static CreatorInstance CaseTypeArgsBody(TypenameExpression type, BaseExpression[] args, CreatorContextBody body, SourceContext context) + => new CreatorInstance( + type, + null, + args, + new CreatorContext(null, new BaseExpression[0], body, false, context), + context); + public static CreatorInstance CaseTypeInheritance(TypenameExpression type, BaseExpression[] ancestors, SourceContext context) + => new CreatorInstance( + type, + null, + new BaseExpression[0], + new CreatorContext(null, ancestors, null, false, context), + context); + public static CreatorInstance CaseTypeBodyInheritance(TypenameExpression type, BaseExpression[] ancestors, CreatorContextBody body, SourceContext context) + => new CreatorInstance( + type, + null, + new BaseExpression[0], + new CreatorContext(null, ancestors, body, false, context), + context); + public static CreatorInstance CaseTypeArgsInheritance(TypenameExpression type, BaseExpression[] args, BaseExpression[] ancestors, SourceContext context) + => new CreatorInstance( + type, + null, + args, + null, + context); + public static CreatorInstance CaseTypeArgsBodyInheritance(TypenameExpression type, BaseExpression[] args, BaseExpression[] ancestors, CreatorContextBody body, SourceContext context) + => new CreatorInstance( + type, + null, + args, + new CreatorContext(null, ancestors, body, false, context), + context); + public static CreatorInstance NamedCaseType(TypenameExpression type, BaseExpression name, SourceContext context) + => new CreatorInstance( + type, + name, + new BaseExpression[0], + null, + context); + public static CreatorInstance NamedCaseTypeBody(TypenameExpression type, BaseExpression name, CreatorContextBody body, SourceContext context) + => new CreatorInstance( + type, + name, + new BaseExpression[0], + new CreatorContext(name, new BaseExpression[0], body, false, context), + context); + public static CreatorInstance NamedCaseTypeArgs(TypenameExpression type, BaseExpression name, BaseExpression[] args, SourceContext context) + => new CreatorInstance( + type, + name, + args, + null, + context); + public static CreatorInstance NamedCaseTypeArgsBody(TypenameExpression type, BaseExpression name, BaseExpression[] args, CreatorContextBody body, SourceContext context) + => new CreatorInstance( + type, + name, + args, + new CreatorContext(name, new BaseExpression[0], body, false, context), + context); + public static CreatorInstance NamedCaseTypeInheritance(TypenameExpression type, BaseExpression name, BaseExpression[] ancestors, SourceContext context) + => new CreatorInstance( + type, + name, + new BaseExpression[0], + new CreatorContext(name, ancestors, null, false, context), + context); + public static CreatorInstance NamedCaseTypeBodyInheritance(TypenameExpression type, BaseExpression name, BaseExpression[] ancestors, CreatorContextBody body, SourceContext context) + => new CreatorInstance( + type, + name, + new BaseExpression[0], + new CreatorContext(name, ancestors, body, false, context), + context); + public static CreatorInstance NamedCaseTypeArgsInheritance(TypenameExpression type, BaseExpression name, BaseExpression[] args, BaseExpression[] ancestors, SourceContext context) + => new CreatorInstance( + type, + name, + args, + null, + context); + public static CreatorInstance NamedCaseTypeArgsBodyInheritance(TypenameExpression type, BaseExpression name, BaseExpression[] args, BaseExpression[] ancestors, CreatorContextBody body, SourceContext context) + => new CreatorInstance( + type, + name, + args, + new CreatorContext(name, ancestors, body, false, context), + context); + + + public CreatorInstance(TypenameExpression type, BaseExpression name, BaseExpression[] args, CreatorContext creatorContext, SourceContext context) : base(context) + { + Type = type; + Name = name; + Arguments = args; + CreatorContext = creatorContext; + } + + public TypenameExpression Type { get; set; } + public BaseExpression Name { get; set; } + public BaseExpression[] Arguments { get; set; } + public CreatorContext CreatorContext { get; set; } + + public override string ExpressionToString() + { + var sb = new StringBuilder(); + sb.Append("new "); + sb.Append(Type.ToString()); + if (Arguments.Length > 0) + sb.Append($"({Arguments.JoinIntoString(", ")})"); + if (CreatorContext?.Name != null) + sb.Append($" {CreatorContext.Name}"); + if (CreatorContext?.Ancestors.Length > 0) + { + sb.Append(": "); + sb.Append(CreatorContext.Ancestors.JoinIntoString(", ")); + } + if (CreatorContext?.CreatorBody != null) + { + sb.Append($"{{\n{CreatorContext.CreatorBody}\n}}"); + } + return sb.ToString(); + } + + private ExecutionContext counted_invoked; + private bool is_name_expr; + private int variable_index; + public override object GetValue(ExecutionContext context) + { + object instance; + var type = Type.GetValue(context).Cast(); + if (CreatorContext != null) + { + var created = CreatorContext.GetValue(context).Cast().Context; + if (Arguments.Length == 0 && type.HasInitor()) + instance = type.InstanceUnwrap(created); + else + { + instance = Activator.CreateInstance(type, Arguments.ConvertAll(x => x.GetValue(context))); + type.InstanceUnwrapIn(created, instance); + } + if (CreatorContext.Name != null) + BinaryAssign.AssignToValue(context, CreatorContext.Name, instance, ref counted_invoked, ref is_name_expr, ref variable_index); + } + else + { + instance = Activator.CreateInstance(type, Arguments.ConvertAll(x => x.GetValue(context))); + if (Name != null) + BinaryAssign.AssignToValue(context, Name, instance, ref counted_invoked, ref is_name_expr, ref variable_index); + } + return instance; + } + + public override object Clone() + { + return new CreatorInstance(Type.CloneCast(), Name.CloneCast(), Arguments.CloneArray(), CreatorContext.CloneCast(), SourceContext.CloneCast()); + } + } +} diff --git a/SLThree/Expressions/Creators/CreatorTuple.cs b/SLThree/Expressions/Creators/CreatorTuple.cs index 4b18757..7049977 100644 --- a/SLThree/Expressions/Creators/CreatorTuple.cs +++ b/SLThree/Expressions/Creators/CreatorTuple.cs @@ -9,7 +9,7 @@ namespace SLThree public class CreatorTuple : BaseExpression { public BaseExpression[] Expressions; - public (ExecutionContext, bool, int)[] Caches; + private (ExecutionContext, bool, int)[] Caches; public CreatorTuple(BaseExpression[] expressions, SourceContext context) : base(context) { diff --git a/SLThree/Expressions/FunctionDefinition.cs b/SLThree/Expressions/FunctionDefinition.cs new file mode 100644 index 0000000..857b0b8 --- /dev/null +++ b/SLThree/Expressions/FunctionDefinition.cs @@ -0,0 +1,140 @@ +using SLThree.Extensions; +using SLThree.Extensions.Cloning; +using SLThree.sys; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; + +namespace SLThree +{ + public class FunctionDefinition : BaseExpression + { + /* + ---Function defines--- + [MODS [Name]](args)[:TRet] {} + [MODS [Name]](args)[:TRet] => expr + [MODS [Name]](args)[:TRet] {} + [MODS [Name]](args)[:TRet] => expr + arg[:TRet] => {} + arg[:TRet] => expr + */ + + public string[] Modificators; + public BaseExpression FunctionName; + public NameExpression[] GenericArguments; + public NameExpression[] Arguments; + public StatementList FunctionBody; + public TypenameExpression ReturnTypeHint; + private bool not_native; + + public FunctionDefinition(string[] modificators, BaseExpression name, NameExpression[] generics, NameExpression[] args, StatementList body, TypenameExpression typehint, SourceContext context) : base(context) + { + Modificators = modificators; + FunctionName = name; + GenericArguments = generics; + Arguments = args; + FunctionBody = body; + ReturnTypeHint = typehint; + var many = Modificators.GroupBy(x => x).FirstOrDefault(x => x.Count() > 1); + if (many != null) throw new SyntaxError($"Repeated modifier \"{many.First()}\"", context); + + var is_abstract = Modificators.Contains("abstract"); + if (FunctionBody == null) + { + if (is_abstract) + { + FunctionBody = new StatementList(new BaseStatement[] { new ThrowStatement(new StaticExpression(new AbstractInvokation(SourceContext)), context) }, context); + } + else throw new LogicalError("Abstract method without abstract modifier", context); + } + else if (is_abstract && !slt.is_abstract(FunctionBody)) throw new LogicalError("An abstract method shouldn't have a body", context); + + if (Method == null) + { + if (GenericArguments.Length == 0) Method = new Method( + FunctionName == null ? Method.DefaultMethodName : CreatorContext.GetLastName(FunctionName), + Arguments.Select(x => x.Name).ToArray(), + FunctionBody, + Arguments.Select(x => x.TypeHint).ToArray(), + ReturnTypeHint, + null, + !Modificators.Contains("explicit"), + Modificators.Contains("recursive")); + else Method = new GenericMethod( + FunctionName == null ? Method.DefaultMethodName : CreatorContext.GetLastName(FunctionName), + Arguments.Select(x => x.Name).ToArray(), + FunctionBody, + Arguments.Select(x => x.TypeHint).ToArray(), + ReturnTypeHint, + null, + !Modificators.Contains("explicit"), + Modificators.Contains("recursive"), + GenericArguments); + } + + Method.Abstract = is_abstract; + not_native = !Modificators.Contains("native"); + } + + internal DynamicMethod RebuildNative(ExecutionContext context) + { + return Native.Builder.Build(Method, context); + } + + public override string ExpressionToString() + { + var sb = new StringBuilder(); + + sb.Append(Modificators.JoinIntoString(" ")); + if (FunctionName != null) + { + if (Modificators.Length > 0) sb.Append(" "); + sb.Append($"{FunctionName}"); + } + if (GenericArguments.Length > 0) sb.Append($"<{GenericArguments.JoinIntoString(", ")}>"); + sb.Append($"({Arguments.JoinIntoString(", ")})"); + if (ReturnTypeHint != null) + sb.Append($": {ReturnTypeHint}"); + if (FunctionBody.Statements.Length == 1 && FunctionBody.Statements[0] is ReturnStatement statement && !statement.VoidReturn) + sb.Append($" => {statement.Expression}"); + else sb.Append($"{{{FunctionBody}}}"); + + return sb.ToString(); + } + + public Method Method; + private ExecutionContext counted_invoked; + private bool is_name_expr; + private int variable_index; + + public override object GetValue(ExecutionContext context) + { + if (not_native) + { + var method = Method.CloneCast(); + method.@this = context.wrap; + if (FunctionName != null) + { + BinaryAssign.AssignToValue(context, FunctionName, method, ref counted_invoked, ref is_name_expr, ref variable_index); + } + return method; + } + else + { + var native = RebuildNative(context); + if (FunctionName != null) + BinaryAssign.AssignToValue(context, FunctionName, native, ref counted_invoked, ref is_name_expr, ref variable_index); + return native; + } + } + + public override object Clone() + { + return new FunctionDefinition(Modificators.CloneArray(), FunctionName.CloneCast(), GenericArguments.CloneArray(), Arguments.CloneArray(), Modificators.Contains("abstract") ? null : FunctionBody.CloneCast(), ReturnTypeHint.CloneCast(), SourceContext.CloneCast()); + } + } +} diff --git a/SLThree/Expressions/InvokeExpression.cs b/SLThree/Expressions/InvokeExpression.cs index 509cca4..22e3fed 100644 --- a/SLThree/Expressions/InvokeExpression.cs +++ b/SLThree/Expressions/InvokeExpression.cs @@ -1,7 +1,9 @@ using SLThree.Extensions; using SLThree.Extensions.Cloning; +using System; using System.Linq; using System.Reflection; +using System.Runtime.CompilerServices; namespace SLThree { @@ -26,10 +28,8 @@ public InvokeExpression(BaseExpression name, BaseExpression[] arguments, bool nu public override string ExpressionToString() => $"{Left}{(null_conditional ? ".?" : "")}({Arguments.JoinIntoString(", ")})"; - public object GetValue(ExecutionContext context, object[] args) + public object InvokeForObj(ExecutionContext context, object[] args, object o) { - var o = Left.GetValue(context); - if (o == null) { if (null_conditional) return null; @@ -41,6 +41,14 @@ public object GetValue(ExecutionContext context, object[] args) if (method.ParamNames.Length != args.Length) throw new RuntimeError("Call with wrong arguments count", SourceContext); return method.GetValue(context, args); } + else if (o is ContextWrap wrap) + { + if (wrap.Context.LocalVariables.GetValue("constructor").Item1 is Method constructor) + { + if (constructor.ParamNames.Length != args.Length) throw new RuntimeError("Call constructor with wrong arguments count", SourceContext); + return wrap.Context.CreateInstance(context, constructor, args).wrap; + } + } else if (o is MethodInfo mi) { if (!mi.IsStatic) return mi.Invoke(args[0], args.Skip(1).ToArray()); @@ -54,7 +62,7 @@ public object GetValue(ExecutionContext context, object[] args) else { var type = o.GetType(); - type.GetMethods() + return type.GetMethods() .FirstOrDefault(x => x.Name == Left.ExpressionToString().Replace(" ", "") && x.GetParameters().Length == Arguments.Length) ?.Invoke(o, args); } @@ -62,6 +70,13 @@ public object GetValue(ExecutionContext context, object[] args) throw new RuntimeError($"{o.GetType().GetTypeString()} is not allow to invoke", SourceContext); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public object GetValue(ExecutionContext context, object[] args) + { + return InvokeForObj(context, args, Left.GetValue(context)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public override object GetValue(ExecutionContext context) { return GetValue(context, Arguments.ConvertAll(x => x.GetValue(context))); @@ -89,9 +104,11 @@ public object GetValue(ExecutionContext context, object obj) } else if (obj != null) { - return obj.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance) - .FirstOrDefault(x => x.Name == key && x.GetParameters().Length == Arguments.Length) - .Invoke(obj, Arguments.ConvertAll(x => x.GetValue(context))); + var method = obj.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance) + .FirstOrDefault(x => x.Name == key && x.GetParameters().Length == Arguments.Length); + if (method != null) + return method.Invoke(obj, Arguments.ConvertAll(x => x.GetValue(context))); + else return InvokeForObj(context, Arguments.ConvertAll(x => x.GetValue(context)), MemberAccess.GetNameExprValue(context, obj, Left as NameExpression)); } return null; diff --git a/SLThree/Expressions/InvokeGenericExpression.cs b/SLThree/Expressions/InvokeGenericExpression.cs index 30ae0a6..eeefedb 100644 --- a/SLThree/Expressions/InvokeGenericExpression.cs +++ b/SLThree/Expressions/InvokeGenericExpression.cs @@ -3,6 +3,7 @@ using System; using System.Linq; using System.Reflection; +using System.Runtime.CompilerServices; namespace SLThree { @@ -30,10 +31,8 @@ public InvokeGenericExpression(BaseExpression left, TypenameExpression[] generic public override string ExpressionToString() => $"{Left}{(null_conditional ? ".?" : "")}<{GenericArguments.JoinIntoString(", ")}>({Arguments.JoinIntoString(", ")})"; - public object GetValue(ExecutionContext context, Type[] generic_args, object[] args) + public object InvokeForObj(ExecutionContext context, Type[] generic_args, object[] args, object o) { - var o = Left.GetValue(context); - if (o == null) { if (null_conditional) return null; @@ -56,7 +55,7 @@ public object GetValue(ExecutionContext context, Type[] generic_args, object[] a else { var type = o.GetType(); - type.GetMethods() + return type.GetMethods() .FirstOrDefault(x => x.Name == Left.ExpressionToString().Replace(" ", "") && x.GetParameters().Length == Arguments.Length) ?.MakeGenericMethod(generic_args) .Invoke(o, args); @@ -65,6 +64,13 @@ public object GetValue(ExecutionContext context, Type[] generic_args, object[] a throw new RuntimeError($"{o.GetType().GetTypeString()} is not allow to invoke", SourceContext); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public object GetValue(ExecutionContext context, Type[] generic_args, object[] args) + { + return InvokeForObj(context, generic_args, args, Left.GetValue(context)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public override object GetValue(ExecutionContext context) { return GetValue(context, GenericArguments.ConvertAll(x => (Type)x.GetValue(context)), Arguments.ConvertAll(x => x.GetValue(context))); @@ -93,10 +99,10 @@ public object GetValue(ExecutionContext context, object obj) } else if (obj != null) { - return obj.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance) - .FirstOrDefault(x => x.Name == key && x.GetParameters().Length == Arguments.Length) - .MakeGenericMethod(generic_args) - .Invoke(obj, Arguments.ConvertAll(x => x.GetValue(context))); + var method = obj.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance) + .FirstOrDefault(x => x.Name == key && x.GetParameters().Length == Arguments.Length); + if (method != null) return method.MakeGenericMethod(generic_args).Invoke(obj, Arguments.ConvertAll(x => x.GetValue(context))); + else return InvokeForObj(context, generic_args, Arguments.ConvertAll(x => x.GetValue(context)), MemberAccess.GetNameExprValue(context, obj, Left as NameExpression)); } return null; diff --git a/SLThree/Expressions/LambdaExpression.cs b/SLThree/Expressions/LambdaExpression.cs deleted file mode 100644 index 3241488..0000000 --- a/SLThree/Expressions/LambdaExpression.cs +++ /dev/null @@ -1,52 +0,0 @@ -using SLThree.Extensions.Cloning; -using System.Collections.Generic; -using System.Linq; - -namespace SLThree -{ - public class LambdaExpression : BaseExpression - { - public InvokeExpression Left; - public StatementList Right; - public IList Modificators; - public TypenameExpression ReturnTypeHint; - - public LambdaExpression(InvokeExpression invokeExpression, StatementList statements, TypenameExpression typehint, IList modificators, SourceContext context) : base(context) - { - Left = invokeExpression; - Right = statements; - ReturnTypeHint = typehint; - Modificators = modificators; - var many = Modificators.GroupBy(x => x).FirstOrDefault(x => x.Count() > 1); - if (many != null) throw new SyntaxError($"Repeated modifier \"{many.First()}\"", context); - - if (Method == null) - { - Method = new Method( - "$method", - Left.Arguments.Select(x => (x as NameExpression).Name).ToArray(), - Right, - Left.Arguments.Select(x => (x as NameExpression).TypeHint).ToArray(), - ReturnTypeHint, - null, - !Modificators.Contains("explicit"), - Modificators.Contains("recursive"), - false); - } - } - - public override string ExpressionToString() => $"{Left} => {Right}"; - - public Method Method; - public override object GetValue(ExecutionContext context) - { - Method.definitionplace = context.wrap; - return Method; - } - - public override object Clone() - { - return new LambdaExpression(Left.CloneCast(), Right.CloneCast(), ReturnTypeHint.CloneCast(), Modificators.ToArray().CloneArray(), SourceContext.CloneCast()); - } - } -} diff --git a/SLThree/Expressions/LambdaGenericExpression.cs b/SLThree/Expressions/LambdaGenericExpression.cs deleted file mode 100644 index 9f6397e..0000000 --- a/SLThree/Expressions/LambdaGenericExpression.cs +++ /dev/null @@ -1,55 +0,0 @@ -using SLThree.Extensions.Cloning; -using System.Collections.Generic; -using System.Linq; - -namespace SLThree -{ - public class LambdaGenericExpression : BaseExpression - { - public InvokeExpression Left; - public StatementList Right; - public NameExpression[] Generics; - public IList Modificators; - public TypenameExpression ReturnTypeHint; - - public LambdaGenericExpression(InvokeExpression invokeExpression, StatementList statements, TypenameExpression typehint, IList modificators, NameExpression[] generics, SourceContext context) : base(context) - { - Left = invokeExpression; - Right = statements; - Generics = generics; - ReturnTypeHint = typehint; - Modificators = modificators; - var many = Modificators.GroupBy(x => x).FirstOrDefault(x => x.Count() > 1); - if (many != null) throw new SyntaxError($"Repeated modifier \"{many.First()}\"", context); - - if (Method == null) - { - Method = new GenericMethod( - "$method", - Left.Arguments.Select(x => (x as NameExpression).Name).ToArray(), - Right, - Left.Arguments.Select(x => (x as NameExpression).TypeHint).ToArray(), - ReturnTypeHint, - null, - !Modificators.Contains("explicit"), - Modificators.Contains("recursive"), - false, - Generics); - } - } - - public override string ExpressionToString() => $"{Left} => {Right}"; - - public Method Method; - public override object GetValue(ExecutionContext context) - { - Method.definitionplace = context.wrap; - return Method; - } - - public override object Clone() - { - return new LambdaGenericExpression(Left.CloneCast(), Right.CloneCast(), ReturnTypeHint.CloneCast(), Modificators.ToArray().CloneArray(), Generics.CloneArray(), SourceContext.CloneCast()); - } - } -} diff --git a/SLThree/Expressions/Literals/Special/ParentLiteral.cs b/SLThree/Expressions/Literals/Special/ParentLiteral.cs new file mode 100644 index 0000000..d6aec18 --- /dev/null +++ b/SLThree/Expressions/Literals/Special/ParentLiteral.cs @@ -0,0 +1,14 @@ +using Pegasus.Common; + +namespace SLThree +{ + public class ParentLiteral : Special + { + public ParentLiteral(SourceContext context) : base(context) { } + public ParentLiteral(Cursor cursor) : base(cursor) { } + + public override string ExpressionToString() => "parent"; + public override object GetValue(ExecutionContext context) => context.@this.Context.parent; + public override object Clone() => new ParentLiteral(SourceContext); + } +} diff --git a/SLThree/Expressions/MemberAccess.cs b/SLThree/Expressions/MemberAccess.cs index 334892d..1ffb36b 100644 --- a/SLThree/Expressions/MemberAccess.cs +++ b/SLThree/Expressions/MemberAccess.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices.ComTypes; using System.Text; namespace SLThree @@ -32,6 +33,49 @@ public MemberAccess() : base() { } private bool is_unwrap; private bool is_super; private bool is_upper; + private bool is_parent; + + public static object GetNameExprValue(ExecutionContext context, object left, NameExpression Right) + { + if (left != null) + { + if (left is ContextWrap pred) + { + if (Right is NameExpression predName) + { + if (predName.Name == "super") + { + return pred.Context.super; + } + else if (predName.Name == "parent") + { + return pred.Context.parent; + } + else if (predName.Name == "upper") + { + return pred.Context.PreviousContext?.wrap; + } + return pred.Context.LocalVariables.GetValue(predName.Name).Item1; + } + } + var has_access = left is ClassAccess access; + var type = has_access ? (left as ClassAccess).Name : left.GetType(); + + var field = type.GetField(Right.Name); + if (field != null) return field.GetValue(left); + var prop = type.GetProperty(Right.Name); + if (prop != null) return prop.GetValue(left); + var nest_type = type.GetNestedType(Right.Name); + if (nest_type != null) return new ClassAccess(nest_type); + if (left is IDictionary dict) + return dict[Right.Name]; + + throw new RuntimeError($"Name \"{Right.Name}\" not found in {type.GetTypeString()}", Right.SourceContext); + } + + return null; + } + public override object GetValue(ExecutionContext context) { var left = Left.GetValue(context); @@ -39,6 +83,7 @@ public override object GetValue(ExecutionContext context) if (counted_contextwrapcache) { if (is_super) return (left as ContextWrap).Context.super; + else if (is_parent) return (left as ContextWrap).Context.parent; else if (is_upper) return (left as ContextWrap).Context.PreviousContext.wrap; else return (left as ContextWrap).Context.LocalVariables.GetValue(variable_name).Item1; } @@ -60,6 +105,12 @@ public override object GetValue(ExecutionContext context) is_super = true; return pred.Context.super; } + else if (predName.Name == "parent") + { + counted_contextwrapcache = true; + is_parent = true; + return pred.Context.parent; + } else if (predName.Name == "upper") { counted_contextwrapcache = true; @@ -145,10 +196,15 @@ public void SetValue(ExecutionContext context, ref object value) counted_other_context_assign = true; if (value is Method mth) { - mth = mth.CloneWithNewName(nameExpression2.Name); - mth.UpdateContextName(); - mth.definitionplace = new ContextWrap(context); - value = mth; + if (mth.Binded) value = mth; + else + { + mth.Name = nameExpression2.Name; + mth.UpdateContextName(); + mth.@this = new ContextWrap(context); + mth.Binded = true; + value = mth; + } } context.LocalVariables.SetValue(other_context_name, value); } diff --git a/SLThree/Expressions/NameExpression.cs b/SLThree/Expressions/NameExpression.cs index 6307ba7..9d0ea95 100644 --- a/SLThree/Expressions/NameExpression.cs +++ b/SLThree/Expressions/NameExpression.cs @@ -14,7 +14,7 @@ public NameExpression(string name, TypenameExpression typehint, SourceContext co TypeHint = typehint; } - public override string ExpressionToString() => Name; + public override string ExpressionToString() => $"{(TypeHint == null?"":TypeHint.ToString())}{Name}"; private ExecutionContext counted; private int variable_index; diff --git a/SLThree/Expressions/NewExpression.cs b/SLThree/Expressions/NewExpression.cs deleted file mode 100644 index af70ce4..0000000 --- a/SLThree/Expressions/NewExpression.cs +++ /dev/null @@ -1,33 +0,0 @@ -using SLThree.Extensions; -using SLThree.Extensions.Cloning; -using System; -using System.Linq; - -namespace SLThree -{ - public class NewExpression : BaseExpression - { - public TypenameExpression Typename; - public BaseExpression[] Arguments; - - public NewExpression(TypenameExpression typename, BaseExpression[] arguments, SourceContext context) : base(context) - { - Typename = typename; - Arguments = arguments; - } - - public NewExpression(TypenameExpression typename, SourceContext context) : this(typename, new BaseExpression[0], context) { } - - public override string ExpressionToString() => $"new {Typename}({Arguments.JoinIntoString(", ")})"; - - public override object GetValue(ExecutionContext context) - { - return Activator.CreateInstance(Typename.GetValue(context).Cast(), Arguments.ConvertAll(x => x.GetValue(context))); - } - - public override object Clone() - { - return new NewExpression(Typename.CloneCast(), Arguments.CloneArray(), SourceContext.CloneCast()); - } - } -} diff --git a/SLThree/Expressions/Operators/Binary/BinaryAssign.cs b/SLThree/Expressions/Operators/Binary/BinaryAssign.cs index 6016b45..6ca18b0 100644 --- a/SLThree/Expressions/Operators/Binary/BinaryAssign.cs +++ b/SLThree/Expressions/Operators/Binary/BinaryAssign.cs @@ -26,11 +26,15 @@ public object AssignValue(ExecutionContext context, BaseExpression Left, object { if (right is Method mth) { - var m2 = mth.CloneWithNewName(nl.Name); - m2.UpdateContextName(); - if (m2.Binded) m2.definitionplace = mth.definitionplace; - else m2.definitionplace = new ContextWrap(context); - right = m2; + if (mth.Binded) right = mth; + else + { + mth.Name = nl.Name; + mth.UpdateContextName(); + mth.@this = new ContextWrap(context); + mth.Binded = true; + right = mth; + } } variable_index = context.LocalVariables.SetValue(nl.Name, right); is_name_expr = true; @@ -48,11 +52,15 @@ private static object InternalAssignToValue(ExecutionContext context, BaseExpres { if (right is Method mth) { - var m2 = mth.CloneWithNewName(nl.Name); - m2.UpdateContextName(); - if (m2.Binded) m2.definitionplace = mth.definitionplace; - else m2.definitionplace = new ContextWrap(context); - right = m2; + if (mth.Binded) right = mth; + else + { + mth.Name = nl.Name; + mth.UpdateContextName(); + mth.@this = new ContextWrap(context); + mth.Binded = true; + right = mth; + } } context.LocalVariables.SetValue(nl.Name, right); return right; @@ -87,11 +95,15 @@ public static object AssignToValue(ExecutionContext context, BaseExpression Left { if (right is Method mth) { - var m2 = mth.CloneWithNewName(nl.Name); - m2.UpdateContextName(); - if (m2.Binded) m2.definitionplace = mth.definitionplace; - else m2.definitionplace = new ContextWrap(context); - right = m2; + if (mth.Binded) right = mth; + else + { + mth.Name = nl.Name; + mth.UpdateContextName(); + mth.@this = new ContextWrap(context); + mth.Binded = true; + right = mth; + } } variable_index = context.LocalVariables.SetValue(nl.Name, right); is_name_expr = true; diff --git a/SLThree/Expressions/Operators/Binary/BinaryAssignUnknown.cs b/SLThree/Expressions/Operators/Binary/BinaryAssignUnknown.cs index 2c3b63f..95c7f4d 100644 --- a/SLThree/Expressions/Operators/Binary/BinaryAssignUnknown.cs +++ b/SLThree/Expressions/Operators/Binary/BinaryAssignUnknown.cs @@ -29,13 +29,13 @@ public override object GetValue(ExecutionContext context) context.LocalVariables.SetValue(wrap.Context.Name, wrap); return wrap; } - NonGenericWrapper wrapper; + /*NonGenericWrapper wrapper; if ((wrapper = NonGenericWrapper.GetWrapper(right.GetType())).HasName()) { var name = wrapper.GetName(right); context.LocalVariables.SetValue(name, right); return right; - } + }*/ } throw new OperatorError(this, right?.GetType() ?? Left.GetType()); } diff --git a/SLThree/Expressions/StaticExpression.cs b/SLThree/Expressions/StaticExpression.cs new file mode 100644 index 0000000..16f0dae --- /dev/null +++ b/SLThree/Expressions/StaticExpression.cs @@ -0,0 +1,41 @@ +using SLThree.Extensions.Cloning; + +namespace SLThree +{ + public class StaticExpression : BaseExpression + { + public BaseExpression Right; + + public StaticExpression(object obj) : base(new SourceContext()) + { + artificial = true; + this.obj = obj; + done = true; + } + public StaticExpression(BaseExpression right, SourceContext context) : base(context) + { + Right = right; + } + + public override string ExpressionToString() => $"static {Right ?? obj}"; + + private bool done; + private object obj; + private bool artificial; + + public bool IsArtificial => artificial; + public object Object => obj; + + public override object GetValue(ExecutionContext context) + { + if (done) return obj; + done = true; + return obj = Right.GetValue(context); + } + + public override object Clone() + { + return artificial ? new StaticExpression(obj) : new StaticExpression(Right.CloneCast(), SourceContext.CloneCast()); + } + } +} diff --git a/SLThree/Expressions/UsingExpression.cs b/SLThree/Expressions/UsingExpression.cs new file mode 100644 index 0000000..d725b6b --- /dev/null +++ b/SLThree/Expressions/UsingExpression.cs @@ -0,0 +1,48 @@ +using SLThree.Extensions; +using SLThree.Extensions.Cloning; +using System.Linq; + +namespace SLThree +{ + public class UsingExpression : BaseExpression + { + public BaseExpression Alias; + public CreatorUsing Using; + private ExecutionContext counted_invoked; + private bool is_name_expr; + private int variable_index; + + public UsingExpression(BaseExpression alias, CreatorUsing usingBody, SourceContext context) : base(context) + { + Alias = alias; + Using = usingBody; + } + + public UsingExpression(CreatorUsing @using, SourceContext context) : this(null, @using, context) { } + + public override string ExpressionToString() => $"using {Using.Type}{(Alias == null ? "" : $" as {Alias}")}"; + + public override object GetValue(ExecutionContext context) + { + var @using = Using.GetValue(context).Cast(); + string name; + if (Alias == null) + { + var type_name = Using.GetTypenameWithoutGenerics(); + name = type_name.Contains(".") ? @using.Name.Name : type_name; + name = name.Contains("`") ? name.Substring(0, name.IndexOf("`")) : name; + variable_index = context.LocalVariables.SetValue(name, @using); + } + else { + BinaryAssign.AssignToValue(context, Alias, @using, ref counted_invoked, ref is_name_expr, ref variable_index); + } + + return @using; + } + + public override object Clone() + { + return new UsingExpression(Alias.CloneCast(), Using.CloneCast(), SourceContext.CloneCast()); + } + } +} diff --git a/SLThree/Extensions/GenericExtensions.cs b/SLThree/Extensions/GenericExtensions.cs index c0401be..20b2f1a 100644 --- a/SLThree/Extensions/GenericExtensions.cs +++ b/SLThree/Extensions/GenericExtensions.cs @@ -71,5 +71,8 @@ public static ChanceChooser ConvertChooser(this ChanceChooser new ChanceChooser(input.Values.Select(x => (selector(x.Item1), x.Item2)).ToArray()); public static ChanceChooser ConvertChooser(this ChanceChooser input) where TOut : TIn => new ChanceChooser(input.Values.Select(x => ((TOut)x.Item1, x.Item2)).ToArray()); + + [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)] + public static LocalVariablesContainer ToLocals(this Dictionary dict) => LocalVariablesContainer.GetFromDictionary(dict); } } diff --git a/SLThree/Extensions/SLTHelpers.cs b/SLThree/Extensions/SLTHelpers.cs index 5b59730..b2fcbbc 100644 --- a/SLThree/Extensions/SLTHelpers.cs +++ b/SLThree/Extensions/SLTHelpers.cs @@ -197,30 +197,9 @@ public static object CastToType(this object o, Type casting_type) if (casting_type == typeof(string)) return o.ToString(); - if (casting_type == type_context) - { - if (o is Type st_type) - return - st_type.IsAbstract && st_type.IsSealed - ? new ContextWrap(NonGenericWrapper.GetWrapper(st_type).WrapStaticClass()) - : new ContextWrap(NonGenericWrapper.GetWrapper(st_type).WrapStatic()); - else - return new ContextWrap(NonGenericWrapper.GetWrapper(o.GetType()).Wrap(o)); - } var type = o.GetType(); if (type == casting_type) return o; if (o is IConvertible) return Convert.ChangeType(o, casting_type); - if (type == type_context) - { - var wrapper = NonGenericWrapper.GetWrapper(casting_type); - if (casting_type.IsAbstract) - { - if (casting_type.IsSealed) wrapper.UnwrapStaticClass(((ContextWrap)o).Context); - else wrapper.UnwrapStatic(((ContextWrap)o).Context); - return null; - } - else return wrapper.Unwrap(((ContextWrap)o).Context); - } if (casting_type.IsEnum) { if (type == type_string) return Enum.Parse(casting_type, (string)o); diff --git a/SLThree/Extensions/SLThreeExtensions.cs b/SLThree/Extensions/SLThreeExtensions.cs index b55ad43..6d0c36e 100644 --- a/SLThree/Extensions/SLThreeExtensions.cs +++ b/SLThree/Extensions/SLThreeExtensions.cs @@ -31,5 +31,7 @@ public static string[] ReadStrings(this Stream stream) return sr.ReadToEnd().Split(new string[1] { Environment.NewLine }, StringSplitOptions.None); } } + public static string Representation(this ExecutionContext context) => sys.slt.context_repr(context.wrap); + public static string Representation(this ContextWrap context) => sys.slt.context_repr(context); } } diff --git a/SLThree/LocalVariablesContainer.cs b/SLThree/LocalVariablesContainer.cs index bab6cc7..a56ed5b 100644 --- a/SLThree/LocalVariablesContainer.cs +++ b/SLThree/LocalVariablesContainer.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using SLThree.Extensions; +using System; +using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; @@ -6,20 +8,29 @@ namespace SLThree { public class LocalVariablesContainer { - public LocalVariablesContainer() + public LocalVariablesContainer(int default_size = 8, Dictionary names = null) { - + Variables = new object[default_size]; + NamedIdentificators = names ?? new Dictionary(); + current = NamedIdentificators.Count; } internal int current = 0; - internal object[] Variables = new object[8]; - public Dictionary NamedIdenificators = new Dictionary(); + [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)] + public object[] Variables; + public Dictionary NamedIdentificators; - public Dictionary GetAsDictionary() => NamedIdenificators.ToDictionary(x => x.Key, x => Variables[x.Value]); + public Dictionary GetAsDictionary() => NamedIdentificators.ToDictionary(x => x.Key, x => Variables[x.Value]); + public static LocalVariablesContainer GetFromDictionary(IDictionary objs) + { + var ret = new LocalVariablesContainer(objs.Count, objs.Keys.Select((x, i) => (x, i)).ToDictionary(x => x.x, x => x.i)); + objs.Values.ToArray().CopyTo(ret.Variables, 0); + return ret; + } public void ClearNulls() { - NamedIdenificators = NamedIdenificators.Where(x => Variables[x.Value] != null).ToDictionary(x => x.Key, x => x.Value); + NamedIdentificators = NamedIdentificators.Where(x => Variables[x.Value] != null).ToDictionary(x => x.Key, x => x.Value); } //[MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -37,13 +48,18 @@ public void FillArguments(Method method, object[] args) if (current <= args.Length) current = args.Length; args.CopyTo(Variables, 0); for (var i = 0; i < args.Length; i++) - NamedIdenificators[method.ParamNames[i]] = i; + NamedIdentificators[method.ParamNames[i]] = i; + } + public void FillOther(LocalVariablesContainer container) + { + foreach (var x in container.NamedIdentificators) + SetValue(x.Key, container.Variables[x.Value]); } //[MethodImpl(MethodImplOptions.AggressiveInlining)] public int SetValue(string name, object value) { - if (NamedIdenificators.TryGetValue(name, out var id)) + if (NamedIdentificators.TryGetValue(name, out var id)) { Variables[id] = value; return id; @@ -52,7 +68,7 @@ public int SetValue(string name, object value) { if (current >= Variables.Length) Expand(); Variables[current] = value; - NamedIdenificators[name] = current; + NamedIdentificators[name] = current; return current++; } } @@ -65,7 +81,7 @@ public void SetValue(int index, object value) //[MethodImpl(MethodImplOptions.AggressiveInlining)] public (object, int) GetValue(string name) { - if (NamedIdenificators.TryGetValue(name, out var x)) + if (NamedIdentificators.TryGetValue(name, out var x)) { return (Variables[x], x); } diff --git a/SLThree/Methods/GenericMethod.cs b/SLThree/Methods/GenericMethod.cs index a6e717e..e9af16c 100644 --- a/SLThree/Methods/GenericMethod.cs +++ b/SLThree/Methods/GenericMethod.cs @@ -1,5 +1,6 @@ using SLThree.Extensions; using SLThree.Extensions.Cloning; +using SLThree.sys; using SLThree.Visitors; using System; using System.CodeDom; @@ -113,14 +114,14 @@ public CastGenericInfo(CastExpression concrete, int position) : base(concrete, p public override ref TypenameExpression GetPlacer() => ref Concrete.Type; } - public class New : GenericInfo + /*public class New : GenericInfo { public New(NewExpression concrete, int position) : base(concrete, position) { } public override ref TypenameExpression GetPlacer() => ref Concrete.Typename; - } + }*/ public class ArrayCreator : GenericInfo { public ArrayCreator(CreatorArray concrete, int position) : base(concrete, position) @@ -145,14 +146,14 @@ public RangeCreator(CreatorRange concrete, int position) : base(concrete, positi public override ref TypenameExpression GetPlacer() => ref Concrete.RangeType; } - public class ContextCreator : GenericInfo +/* public class ContextCreator : GenericInfo { - public ContextCreator(CreatorContext concrete, int position) : base(concrete, position) + public ContextCreator(CreatorContextOld concrete, int position) : base(concrete, position) { } public override ref TypenameExpression GetPlacer() => ref Concrete.Typecast; - } + }*/ public class Chooser : GenericInfo { public Chooser(UnaryGetChooser concrete, int position) : base(concrete, position) @@ -339,7 +340,7 @@ public static List FindAll(GenericMethod method) } } - public GenericMethod(string name, string[] paramNames, StatementList statements, TypenameExpression[] paramTypes, TypenameExpression returnType, ContextWrap definitionPlace, bool @implicit, bool recursive, bool binded, NameExpression[] generics) : base(name, paramNames, statements, paramTypes, returnType, definitionPlace, @implicit, recursive, binded) + public GenericMethod(string name, string[] paramNames, StatementList statements, TypenameExpression[] paramTypes, TypenameExpression returnType, ContextWrap definitionPlace, bool @implicit, bool recursive, NameExpression[] generics) : base(name, paramNames, statements, paramTypes, returnType, definitionPlace, @implicit, recursive) { Generics = generics; GenericsInfo = GenericFinder.FindAll(this); @@ -359,13 +360,35 @@ public Method MakeGenericMethod(Type[] args) } public readonly NameExpression[] Generics; - public override string ToString() => $"{DefinitionReturnType?.ToString() ?? "any"} {Name}<{Generics.JoinIntoString(", ")}>({DefinitionParamTypes.ConvertAll(x => x?.ToString() ?? "any").JoinIntoString(", ")})"; + public override string ToString() + { + var sb = new StringBuilder(); + var unnamed = Name == DefaultMethodName; + if (slt.is_abstract(Statements)) + sb.Append("abstract "); + else + { + if (Recursive) + sb.Append("recursive "); + if (!Implicit) + sb.Append("explicit "); + } + if (!unnamed) + sb.Append(Name); + sb.Append($"<{Generics.JoinIntoString(", ")}>"); + sb.Append($"({ParamTypes.ConvertAll(x => x?.ToString() ?? "any").JoinIntoString(", ")})"); + sb.Append($": {ReturnType?.ToString() ?? "any"}"); + return sb.ToString(); + } public List GenericsInfo; public override Method CloneWithNewName(string name) { - return new GenericMethod(name, ParamNames?.CloneArray(), Statements.CloneCast(), ParamTypes?.CloneArray(), ReturnType.CloneCast(), definitionplace, Implicit, Recursive, Binded, Generics.CloneArray()); + return new GenericMethod(name, ParamNames?.CloneArray(), Statements.CloneCast(), ParamTypes?.CloneArray(), ReturnType.CloneCast(), definitionplace, Implicit, Recursive, Generics.CloneArray()) + { + Abstract = Abstract + }; } } } diff --git a/SLThree/Methods/Method.cs b/SLThree/Methods/Method.cs index 9fd387d..7efdc3d 100644 --- a/SLThree/Methods/Method.cs +++ b/SLThree/Methods/Method.cs @@ -1,24 +1,28 @@ using SLThree.Extensions; using SLThree.Extensions.Cloning; +using SLThree.sys; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; +using System.Text; namespace SLThree { public class Method : ICloneable { - private static readonly Dictionary cached_method_contextes = new Dictionary(); + public const string DefaultMethodName = "$method"; - public readonly string Name; + private ExecutionContext cached_context; + public string Name; public readonly string[] ParamNames; public readonly StatementList Statements; public readonly bool Implicit = false; public readonly bool Recursive = false; - public readonly bool Binded = false; + public bool Abstract = false; + public bool Binded = false; public TypenameExpression[] ParamTypes; public TypenameExpression ReturnType; @@ -26,10 +30,17 @@ public class Method : ICloneable internal ContextWrap definitionplace; internal string contextName = ""; - public ContextWrap @this => definitionplace; + public ContextWrap @this + { + get => definitionplace; internal set + { + definitionplace = value; + cached_context = null; + } + } internal protected Method() { } - public Method(string name, string[] paramNames, StatementList statements, TypenameExpression[] paramTypes, TypenameExpression returnType, ContextWrap definitionPlace, bool @implicit, bool recursive, bool binded) + public Method(string name, string[] paramNames, StatementList statements, TypenameExpression[] paramTypes, TypenameExpression returnType, ContextWrap definitionPlace, bool @implicit, bool recursive) { Name = name; ParamNames = paramNames; @@ -39,19 +50,36 @@ public Method(string name, string[] paramNames, StatementList statements, Typena definitionplace = definitionPlace; Implicit = @implicit; Recursive = recursive; - Binded = binded; } internal void UpdateContextName() => contextName = $"<{Name}>methodcontext"; - public override string ToString() => $"{ReturnType?.ToString() ?? "any"} {Name}({ParamTypes.ConvertAll(x => x?.ToString() ?? "any").JoinIntoString(", ")})"; + public override string ToString() + { + var sb = new StringBuilder(); + var unnamed = Name == DefaultMethodName; + if (Abstract) + sb.Append("abstract "); + else + { + if (Recursive) + sb.Append("recursive "); + if (!Implicit) + sb.Append("explicit "); + } + if (!unnamed) + sb.Append(Name); + sb.Append($"({ParamTypes.ConvertAll(x => x?.ToString() ?? "any").JoinIntoString(", ")})"); + sb.Append($": {ReturnType?.ToString() ?? "any"}"); + return sb.ToString(); + } public virtual ExecutionContext GetExecutionContext(object[] arguments, ExecutionContext super_context = null) { ExecutionContext ret; if (Recursive) { - ret = new ExecutionContext(); + ret = new ExecutionContext(false, false); ret.Name = contextName; ret.PreviousContext = super_context; ret.LocalVariables.FillArguments(this, arguments); @@ -61,19 +89,19 @@ public virtual ExecutionContext GetExecutionContext(object[] arguments, Executio } else { - if (cached_method_contextes.TryGetValue(this, out var cntx)) + if (cached_context != null) { - ret = cntx; + ret = cached_context; ret.PrepareToInvoke(); } else { - ret = new ExecutionContext(super_context) + ret = new ExecutionContext(super_context, false) { @this = definitionplace }; ret.SuperContext = ret.@this.Context?.SuperContext; - cached_method_contextes.Add(this, ret); + cached_context = ret; } ret.Name = contextName; ret.PreviousContext = super_context; @@ -88,15 +116,25 @@ public virtual ExecutionContext GetExecutionContext(object[] arguments, Executio public virtual object GetValue(ExecutionContext old_context, object[] args) { var context = GetExecutionContext(args, old_context); - for (var i = 0; i < Statements.Statements.Length; i++) + var i = 0; + var bs = Statements.Statements; + var count = bs.Length; + while (i < count) { if (context.Returned) return context.ReturnedValue; - else Statements.Statements[i].GetValue(context); + else bs[i++].GetValue(context); } if (context.Returned) return context.ReturnedValue; return null; } + public Method identity(ContextWrap context) + { + @this = context; + Binded = true; + return this; + } + #region Invoke [auto-generated] [MethodImpl(MethodImplOptions.AggressiveInlining)] public object Invoke() @@ -218,7 +256,10 @@ public object InvokeWithContext(ExecutionContext from, object arg1, object arg2, public virtual Method CloneWithNewName(string name) { - return new Method(name, ParamNames?.CloneArray(), Statements.CloneCast(), ParamTypes?.CloneArray(), ReturnType.CloneCast(), definitionplace, Implicit, Recursive, Binded); + return new Method(name, ParamNames?.CloneArray(), Statements.CloneCast(), ParamTypes?.CloneArray(), ReturnType.CloneCast(), definitionplace, Implicit, Recursive) + { + Abstract = Abstract + }; } public virtual object Clone() diff --git a/SLThree/JIT/AbstractNameInfo.cs b/SLThree/Native/AbstractNameInfo.cs similarity index 99% rename from SLThree/JIT/AbstractNameInfo.cs rename to SLThree/Native/AbstractNameInfo.cs index f9a5afd..9bb1b24 100644 --- a/SLThree/JIT/AbstractNameInfo.cs +++ b/SLThree/Native/AbstractNameInfo.cs @@ -2,7 +2,7 @@ using System; using System.Reflection.Emit; -namespace SLThree.JIT +namespace SLThree.Native { public class AbstractNameInfo { diff --git a/SLThree/Native/Builder.cs b/SLThree/Native/Builder.cs new file mode 100644 index 0000000..e0ec1de --- /dev/null +++ b/SLThree/Native/Builder.cs @@ -0,0 +1,33 @@ +using SLThree.Extensions; +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Linq; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; + +namespace SLThree.Native +{ + public static class Builder + { + public static DynamicMethod Build(Method method, ExecutionContext context) + { + Support.CheckOnSupporting(method); + var ret_type = default(Type); + if (method.ReturnType != null) + ret_type = method.ReturnType.GetValue(context).Cast(); + else ret_type = TypeInferencer.ReconstructReturnType(method); + + var dyn_method = new DynamicMethod( + method.Name, + ret_type, + method.ParamTypes.ConvertAll(x => x.GetValue(context).Cast()), + true); + var ngen = new NETGenerator(method, context, dyn_method.GetILGenerator()); + ngen.Visit(method); + + return dyn_method; + } + } +} diff --git a/SLThree/JIT/NETGenerator.cs b/SLThree/Native/NETGenerator.cs similarity index 78% rename from SLThree/JIT/NETGenerator.cs rename to SLThree/Native/NETGenerator.cs index 30f187f..214405f 100644 --- a/SLThree/JIT/NETGenerator.cs +++ b/SLThree/Native/NETGenerator.cs @@ -2,18 +2,12 @@ using SLThree.sys; using SLThree.Visitors; using System; -using System.CodeDom; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Reflection.Emit; -using System.Security.AccessControl; -using System.Security.Permissions; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -namespace SLThree.JIT +namespace SLThree.Native { public class NETGenerator : AbstractVisitor { @@ -145,6 +139,84 @@ public void VisitLiteral(int literal) } } + public static void EmitLoadStaticFieldOrConst(FieldInfo fieldInfo, ILGenerator il) + { + if (fieldInfo.Attributes.HasFlag(FieldAttributes.HasDefault) && fieldInfo.Attributes.HasFlag(FieldAttributes.Literal)) + { + var value = fieldInfo.GetRawConstantValue(); + if (value is Enum) value = value.CastToType(Enum.GetUnderlyingType(fieldInfo.FieldType)); + switch (value) + { + case long i64: + if (i64 >= int.MinValue && i64 <= int.MaxValue) + { + il.Emit(OpCodes.Ldc_I4, (int)i64); + il.Emit(OpCodes.Conv_I8); + } + else + { + il.Emit(OpCodes.Ldc_I8, i64); + } + break; + case ulong u64: + if (u64 >= 0 && u64 <= int.MaxValue) + { + il.Emit(OpCodes.Ldc_I4, (int)u64); + il.Emit(OpCodes.Conv_I8); + } + else + { + il.Emit(OpCodes.Ldc_I8, unchecked((long)u64)); + } + break; + case int i32: + il.Emit(OpCodes.Ldc_I4, i32); + break; + case uint u32: + il.Emit(OpCodes.Ldc_I4, unchecked((int)u32)); + break; + case float f32: + il.Emit(OpCodes.Ldc_R4, f32); + break; + case double f64: + il.Emit(OpCodes.Ldc_R8, f64); + break; + case short i: + il.Emit(OpCodes.Ldc_I4, (int)i); + il.Emit(OpCodes.Conv_I2); + break; + case ushort i: + il.Emit(OpCodes.Ldc_I4, (int)i); + il.Emit(OpCodes.Conv_I2); + break; + case sbyte i: + il.Emit(OpCodes.Ldc_I4, (int)i); + il.Emit(OpCodes.Conv_I1); + break; + case byte i: + il.Emit(OpCodes.Ldc_I4, (int)i); + il.Emit(OpCodes.Conv_I1); + break; + case bool b: + if (b) + il.Emit(OpCodes.Ldc_I4_1); + else + il.Emit(OpCodes.Ldc_I4_0); + il.Emit(OpCodes.Conv_I1); + break; + case string s: + il.Emit(OpCodes.Ldstr, s); + break; + default: + throw new NotSupportedException($"{fieldInfo.FieldType} of constant not supported"); + } + } + else + { + il.Emit(OpCodes.Ldsfld, fieldInfo); + } + } + public override void VisitExpression(Literal expression) { switch (expression) @@ -205,6 +277,11 @@ public override void VisitStatement(ExpressionStatement statement) public override void Visit(Method method) { var count = method.Statements.Statements.Length; + if (count == 0) + { + IL.Emit(OpCodes.Ret); + return; + } var current = 0; foreach (var x in method.Statements.Statements) { @@ -291,7 +368,7 @@ public void MakeBRCondition(BaseExpression expression, Label label) } } - public override void VisitStatement(ConditionStatement statement) + public override void VisitExpression(ConditionExpression statement) { var ifbody = statement.IfBody; var elsebody = statement.ElseBody; @@ -365,6 +442,23 @@ public override void VisitStatement(ReturnStatement statement) IL.Emit(OpCodes.Ret); } + public NETGenerator(Method method, ExecutionContext context, ILGenerator generator) + { + (Variables, VariablesMap) = NameCollector.Collect(method, context); + IL = generator; + var paramid = 1; + foreach (var x in Variables) + { + if (x.NameType == NameType.Local) + { + var lb = IL.DeclareLocal(x.Type); +#if NETFRAMEWORK + lb.SetLocalSymInfo(x.Name); +#endif + index++; + } + } + } public NETGenerator(Method method, ExecutionContext context, MethodBuilder mb, ILGenerator generator) { (Variables, VariablesMap) = NameCollector.Collect(method, context); diff --git a/SLThree/JIT/NameCollector.cs b/SLThree/Native/NameCollector.cs similarity index 96% rename from SLThree/JIT/NameCollector.cs rename to SLThree/Native/NameCollector.cs index 0784629..a678017 100644 --- a/SLThree/JIT/NameCollector.cs +++ b/SLThree/Native/NameCollector.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; -namespace SLThree.JIT +namespace SLThree.Native { public class NameCollector : AbstractVisitor { @@ -40,7 +40,7 @@ public Type GetAutotype(BaseExpression expression, bool throws = true) return bt.GetGenericArguments()[0]; } if (expression is InterpolatedString) return typeof(string); - if (expression is NewExpression newExpression) return (Type)newExpression.Typename.GetValue(temporary_method_context); + //if (expression is NewExpression newExpression) return (Type)newExpression.Typename.GetValue(temporary_method_context); if (expression is NameExpression name) { var vname = variables.LastOrDefault(x => x.Name == name.Name); diff --git a/SLThree/JIT/NameType.cs b/SLThree/Native/NameType.cs similarity index 72% rename from SLThree/JIT/NameType.cs rename to SLThree/Native/NameType.cs index 3c1d825..59d00be 100644 --- a/SLThree/JIT/NameType.cs +++ b/SLThree/Native/NameType.cs @@ -1,4 +1,4 @@ -namespace SLThree.JIT +namespace SLThree.Native { public enum NameType { diff --git a/SLThree/Native/Support.cs b/SLThree/Native/Support.cs new file mode 100644 index 0000000..0e76b63 --- /dev/null +++ b/SLThree/Native/Support.cs @@ -0,0 +1,74 @@ +using SLThree.Extensions; +using SLThree.Visitors; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SLThree.Native +{ + public sealed class Support : AbstractVisitor + { + private List Exceptions = new List(); + + static Type[] SupportedExpressions, SupportedStatements; + private Support() { } + static Support() + { + SupportedExpressions = new Type[] + { + typeof(LongLiteral), + typeof(NameExpression), + + typeof(BinaryAdd), + typeof(BinaryRem), + typeof(BinaryMultiply), + typeof(BinaryDivide), + }; + SupportedStatements = new Type[] + { + typeof(ExpressionStatement), + typeof(ReturnStatement), + }; + } + + public override void VisitExpression(BaseExpression expression) + { + var type = expression.GetType(); + if (!SupportedExpressions.Contains(type)) + Exceptions.Add(new SupportException($"{type}", expression.SourceContext)); + base.VisitExpression(expression); + } + public override void VisitStatement(BaseStatement statement) + { + var type = statement.GetType(); + if (!SupportedStatements.Contains(type)) + Exceptions.Add(new SupportException($"{type}", statement.SourceContext)); + base.VisitStatement(statement); + } + + public static void CheckOnSupporting(Method method) + { + var sup = new Support(); + sup.Visit(method); + if (sup.Exceptions.Count > 0) + throw new NotSupportedException($"Method {method.Name} contains unsupported elements\n{sup.Exceptions.JoinIntoString("\n")}"); + } + } + + + [Serializable] + public class SupportException : LogicalError + { + public SupportException() { } + + public SupportException(SourceContext context) : base(context) { } + + public SupportException(string message, SourceContext context) : base(message, context) { } + + public SupportException(string message, Exception inner, SourceContext context) : base(message, inner, context) { } + } +} diff --git a/SLThree/Native/TypeInferencer.cs b/SLThree/Native/TypeInferencer.cs new file mode 100644 index 0000000..ea287ca --- /dev/null +++ b/SLThree/Native/TypeInferencer.cs @@ -0,0 +1,39 @@ +using SLThree.Visitors; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SLThree.Native +{ + public class TypeInferencer + { + public class ReturnCollector : AbstractVisitor + { + public List Returns = new List(); + + public override void VisitStatement(ReturnStatement statement) + { + Returns.Add(statement); + base.VisitStatement(statement); + } + + public static List Collect(IList statements) + { + var visitor = new ReturnCollector(); + foreach (var x in statements) + visitor.VisitStatement(x); + return visitor.Returns; + } + } + + public static Type ReconstructReturnType(Method method) + { + var statements = method.Statements.Statements; + var returns = ReturnCollector.Collect(statements); + if (returns.Count == 0 || returns.All(x => x.Expression == null)) return typeof(void); + throw new NotSupportedException("Non-void returns not supported right now"); + } + } +} diff --git a/SLThree/Parser.cs b/SLThree/Parser.cs index 7b15937..663222b 100644 --- a/SLThree/Parser.cs +++ b/SLThree/Parser.cs @@ -1,5 +1,7 @@ using SLThree.Extensions; +using SLThree.Extensions.Cloning; using SLThree.Visitors; +using System; using System.Collections.Generic; using System.Linq; @@ -9,14 +11,22 @@ public partial class Parser { public static readonly Parser This = new Parser(); - public BaseExpression ParseExpression(string s) => this.Parse("#EXPR# " + s).Cast().Expression; + public BaseExpression ParseExpression(string s) + { + var ret = this.Parse("#EXPR# " + s).Cast().Expression; + return ret; + } public object EvalExpression(string s, ExecutionContext context = null) { if (context == null) context = new ExecutionContext(); return ParseExpression(s).GetValue(context); } - public BaseStatement ParseScript(string s, string filename = null) => this.Parse("#SLT# " + s, filename); + public BaseStatement ParseScript(string s, string filename = null) + { + var ret = this.Parse("#SLT# " + s, filename); + return ret; + } public ExecutionContext RunScript(string s, string filename = null, ExecutionContext context = null) { var parsed = ParseScript(s, filename); @@ -51,6 +61,7 @@ private BaseExpression GetSpecialName(NameExpression expression) { switch (expression.Name) { + case "parent": return new ParentLiteral(expression.SourceContext); case "global": return new GlobalLiteral(expression.SourceContext); case "self": return new SelfLiteral(expression.SourceContext); case "this": return new ThisLiteral(expression.SourceContext); @@ -102,22 +113,106 @@ private static BaseExpression InjectFirst(BaseExpression left, BaseExpression ri return right; } - private static T Panic(SLTException exception) + private sealed class VFirst: AbstractVisitor where T: class, ExecutionContext.IExecutable { - throw exception; + public T Found = null; + public Func Predicate = x => true; + + public override void VisitExpression(BaseExpression expression) + { + if (expression is T t && Predicate(t)) + { + Found = t; + return; + } + base.VisitExpression(expression); + } + public override void VisitStatement(BaseStatement statement) + { + if (statement is T t && Predicate(t)) + { + Found = t; + return; + } + base.VisitStatement(statement); + } + } + private static bool Any(object o) where T : class, ExecutionContext.IExecutable + { + var has = new VFirst(); + has.VisitAny(o); + return has.Found != null; + } + private static bool Any(object o, out T ret) where T : class, ExecutionContext.IExecutable + { + var has = new VFirst(); + has.VisitAny(o); + ret = has.Found; + return ret != null; + } + private static bool Any(object o, Func predicate) where T : class, ExecutionContext.IExecutable + { + var has = new VFirst(); + has.Predicate = predicate; + has.VisitAny(o); + return has.Found != null; + } + private static bool Any(object o, Func predicate, out T ret) where T : class, ExecutionContext.IExecutable + { + var has = new VFirst(); + has.Predicate = predicate; + has.VisitAny(o); + ret = has.Found; + return has.Found != null; } - private static BaseStatement CheckOnContextStatements(BaseStatement statement) + public static void UncachebleCheck(object o, string suffix = " after static") + { + if (Any(o, out var wrongassign)) + throw new LogicalError($"Unexpected assign {wrongassign}{suffix}", wrongassign.SourceContext); + if (Any(o, func => func.FunctionName != null, out var wrongmethod)) + throw new LogicalError($"Unexpected named method{suffix}", wrongmethod.SourceContext); + if (Any(o, context => context.Name != null, out var wrongcontext)) + throw new LogicalError($"Unexpected named context{suffix}", wrongcontext.SourceContext); + if (Any(o, instance => instance.Name != null, out var wronginstance)) + throw new LogicalError($"Unexpected named instantation{suffix}", wronginstance.SourceContext); + if (Any(o, @using => @using.Alias != null, out var wrongusing)) + throw new LogicalError($"Unexpected named using{suffix}", wrongusing.SourceContext); + } + private BaseExpression ReorderStatic(StaticExpression expression) { - if (statement is ExpressionStatement expressionStatement) + //if (did.TryGetValue(expression, out var expr)) return expr; + if (expression.Right is BinaryAssign) { - if (expressionStatement.Expression is BinaryAssign) - return statement; - throw new SyntaxError($"Expected assign expression, found {expressionStatement.Expression.GetType().Name}", expressionStatement.Expression.SourceContext); + var input = expression.CloneCast(); + var left = input.Right as BinaryAssign; + while (left is BinaryAssign assign && assign.Right is BinaryAssign) + left = assign.Right as BinaryAssign; + UncachebleCheck(left.Right); + var ret = input.Right; + input.Right = left.Right; + left.Right = input; + return ret; } - if (statement is ContextStatement contextStatement) - return contextStatement; - throw new SyntaxError($"Expected assign expression, found {statement.GetType().Name}", statement.SourceContext); + if (expression.Right is CreatorContext context && context.HasName) + return new BinaryAssign(context.Name.CloneCast(), expression, context.SourceContext); + if (expression.Right is CreatorInstance instance && instance.Name != null) + return new BinaryAssign(instance.Name.CloneCast(), expression, instance.SourceContext); + if (expression.Right is UsingExpression @using && @using.Alias != null) + return new BinaryAssign(@using.Alias.CloneCast(), expression, @using.SourceContext); + return ReorderStaticMethod(expression); + } + private BaseExpression ReorderStaticMethod(StaticExpression expression) + { + if (expression.Right is FunctionDefinition func && func.FunctionName != null) + return new BinaryAssign(func.FunctionName.CloneCast(), expression, expression.Right.SourceContext); + UncachebleCheck(expression.Right); + return expression; + } + + private static T Panic(SLTException exception) + { + throw exception; } } } diff --git a/SLThree/Properties/AssemblyInfo.cs b/SLThree/Properties/AssemblyInfo.cs index 5d454a8..8ec6527 100644 --- a/SLThree/Properties/AssemblyInfo.cs +++ b/SLThree/Properties/AssemblyInfo.cs @@ -62,7 +62,7 @@ static SLTVersion() } } - public static string Edition { get; } = "Typing Update"; + public static string Edition { get; } = "Binding&Naming Update"; public static string GetTitle() { diff --git a/SLThree/README.md b/SLThree/README.md deleted file mode 100644 index 1791614..0000000 --- a/SLThree/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# SThree - -C#-like script programming language for .NET Framework \ No newline at end of file diff --git a/SLThree/SLThree.csproj b/SLThree/SLThree.csproj index 0966e66..6b0ba89 100644 --- a/SLThree/SLThree.csproj +++ b/SLThree/SLThree.csproj @@ -1,6 +1,5 @@  - net471;netstandard2.1;net6.0 disable @@ -13,63 +12,43 @@ git language;scripts;script-lang True - 0.7.1.2989 - $(Version) - $(Version) - slthree.ico - Bugfixes: - - Add support for generic dict creators <T, T>{} + 0.8.1 + $([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/docs/versions/0.8.0")) + nugetreadme.md - 4 False - 4 False - 4 False - 4 False - False - False - + - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - @@ -83,6 +62,15 @@ + + + + + True + \ + - - + + + + \ No newline at end of file diff --git a/SLThree/SLThreeOLD.csproj b/SLThree/SLThreeOLD.csproj deleted file mode 100644 index a2f9e4f..0000000 --- a/SLThree/SLThreeOLD.csproj +++ /dev/null @@ -1,210 +0,0 @@ - - - - - Debug - AnyCPU - {06A97274-8266-4F25-A78B-8CF615B12771} - Library - Properties - SLThree - SLThree - v4.7.1 - 512 - true - - - - - true - full - false - ..\bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - ..\bin\ - TRACE - prompt - 4 - - - OnBuildSuccess - - - - ..\packages\Pegasus.4.1.0\lib\net45\Pegasus.Common.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Данный проект ссылается на пакеты NuGet, отсутствующие на этом компьютере. Используйте восстановление пакетов NuGet, чтобы скачать их. Дополнительную информацию см. по адресу: http://go.microsoft.com/fwlink/?LinkID=322105. Отсутствует следующий файл: {0}. - - - - - ../building/IncRevision.bat - - - - - - \ No newline at end of file diff --git a/SLThree/Statements/ContextStatement.cs b/SLThree/Statements/ContextStatement.cs deleted file mode 100644 index 403a30e..0000000 --- a/SLThree/Statements/ContextStatement.cs +++ /dev/null @@ -1,29 +0,0 @@ -using SLThree.Extensions; -using SLThree.Extensions.Cloning; - -namespace SLThree -{ - public class ContextStatement : BaseStatement - { - public CreatorContext Creator; - - public ContextStatement(CreatorContext creator, SourceContext context) : base(context) - { - Creator = creator; - } - - public override string ToString() => $"context {(Creator.HasName ? Creator.Name.Name : "")} {(Creator.HasCast ? $": {Creator.Typecast}" : "")} {{\n{Creator.Body.JoinIntoString("\n")}\n}}"; - - public override object GetValue(ExecutionContext context) - { - var created_context = Creator.GetValue(context); - context.LocalVariables.SetValue(Creator.LastContextName, created_context); - return created_context; - } - - public override object Clone() - { - return new ContextStatement(Creator.CloneCast(), SourceContext.CloneCast()); - } - } -} diff --git a/SLThree/Statements/CreatorContextBody.cs b/SLThree/Statements/CreatorContextBody.cs new file mode 100644 index 0000000..3285f7b --- /dev/null +++ b/SLThree/Statements/CreatorContextBody.cs @@ -0,0 +1,92 @@ +using SLThree.Extensions.Cloning; +using System; +using System.Collections.Generic; + +namespace SLThree +{ + public class CreatorContextBody : StatementList, ICloneable + { + private (ExecutionContext, bool, int)[] Caches; + + public CreatorContextBody() : base() { } + public CreatorContextBody(IList statements, SourceContext context) : base(statements, context) + { + foreach (var x in Statements) + CheckOnContextStatements(x); + Caches = new (ExecutionContext, bool, int)[Statements.Length]; + } + + public ExecutionContext GetValue(ExecutionContext target, ExecutionContext context) + { + for (var i = 0; i < count; i++) + { + if (Statements[i] is ExpressionStatement es) + { + if (es.Expression is BinaryAssign assign) + { + if (assign.Left is MemberAccess @private) + BinaryAssign.AssignToValue(target.@private.Context, @private.Right, assign.Right.GetValue(context), ref Caches[i].Item1, ref Caches[i].Item2, ref Caches[i].Item3); + else + BinaryAssign.AssignToValue(target, assign.Left, assign.Right.GetValue(context), ref Caches[i].Item1, ref Caches[i].Item2, ref Caches[i].Item3); + } + else if (es.Expression is CreatorContext creator) + { + if (creator.Name is MemberAccess @private) + BinaryAssign.AssignToValue(target.@private.Context, @private.Right, creator.GetValue(target, context), ref Caches[i].Item1, ref Caches[i].Item2, ref Caches[i].Item3); + else + BinaryAssign.AssignToValue(target, creator.Name, creator.GetValue(target, context), ref Caches[i].Item1, ref Caches[i].Item2, ref Caches[i].Item3); + } + else if (es.Expression is FunctionDefinition function) + { + if (function.FunctionName is MemberAccess @private) + BinaryAssign.AssignToValue(target.@private.Context, @private.Right, function.GetValue(target.@private.Context), ref Caches[i].Item1, ref Caches[i].Item2, ref Caches[i].Item3); + else + BinaryAssign.AssignToValue(target, function.FunctionName, function.GetValue(target), ref Caches[i].Item1, ref Caches[i].Item2, ref Caches[i].Item3); + } + } + } + return target; + } + + private static bool CheckName(BaseExpression expression) + { + if (expression is NameExpression) return true; + if (expression is MemberAccess memberAccess && memberAccess.Right is NameExpression && memberAccess.Left is PrivateLiteral) return true; + + throw new LogicalError($"Expected name or private.name, found \"{expression}\"", expression.SourceContext); + } + + private static BaseStatement CheckOnContextStatements(BaseStatement statement) + { + if (statement is ExpressionStatement expressionStatement) + { + if (expressionStatement.Expression is BinaryAssign assign) + { + if (CheckName(assign.Left)) return statement; + } + if (expressionStatement.Expression is CreatorContext creator) + { + if (creator.Name == null) throw new LogicalError($"Nested context definitions should be named", expressionStatement.Expression.SourceContext); + if (CheckName(creator.Name)) return statement; + } + if (expressionStatement.Expression is FunctionDefinition function) + { + if (function.FunctionName == null) throw new LogicalError($"Methods should be named", expressionStatement.Expression.SourceContext); + if (CheckName(function.FunctionName)) return statement; + } + throw new SyntaxError($"Expected assign/context/method, found \"{expressionStatement.Expression}\"", expressionStatement.Expression.SourceContext); + } + throw new SyntaxError($"Expected assign/context/method, found \"{statement}\"", statement.SourceContext); + } + + public override object GetValue(ExecutionContext context) + { + throw new NotImplementedException(); + } + + public override object Clone() + { + return new CreatorContextBody(Statements.CloneArray(), SourceContext.CloneCast()); + } + } +} diff --git a/SLThree/Statements/EmptyStatement.cs b/SLThree/Statements/EmptyStatement.cs new file mode 100644 index 0000000..c1e4fd4 --- /dev/null +++ b/SLThree/Statements/EmptyStatement.cs @@ -0,0 +1,13 @@ +using SLThree.Extensions.Cloning; + +namespace SLThree +{ + public class EmptyStatement : BaseStatement + { + public EmptyStatement(SourceContext context) : base(context) { } + + public override string ToString() => $";"; + public override object GetValue(ExecutionContext context) => null; + public override object Clone() => new EmptyStatement(SourceContext.CloneCast()); + } +} diff --git a/SLThree/Statements/ReturnStatement.cs b/SLThree/Statements/ReturnStatement.cs index 28d7090..b1670df 100644 --- a/SLThree/Statements/ReturnStatement.cs +++ b/SLThree/Statements/ReturnStatement.cs @@ -18,7 +18,7 @@ public ReturnStatement(SourceContext context) : base(context) VoidReturn = true; } - public override string ToString() => $"{Expression}"; + public override string ToString() => VoidReturn ? "return;" : $"return {Expression};"; public override object GetValue(ExecutionContext context) { if (VoidReturn) diff --git a/SLThree/Statements/StatementList.cs b/SLThree/Statements/StatementList.cs index d8e5f9a..3d98f60 100644 --- a/SLThree/Statements/StatementList.cs +++ b/SLThree/Statements/StatementList.cs @@ -7,14 +7,14 @@ namespace SLThree public class StatementList : BaseStatement { public BaseStatement[] Statements; - private int count; + private protected int count; public StatementList() : base() { } public StatementList(IList statements, SourceContext context) : base(context) { - Statements = statements.ToArray(); - count = statements.Count; + Statements = statements.Where(x => !(x is EmptyStatement)).ToArray(); + count = Statements.Length; } public override string ToString() => $"{Statements.Length} statements"; diff --git a/SLThree/Statements/UsingStatement.cs b/SLThree/Statements/UsingStatement.cs deleted file mode 100644 index f976d5e..0000000 --- a/SLThree/Statements/UsingStatement.cs +++ /dev/null @@ -1,42 +0,0 @@ -using SLThree.Extensions; -using SLThree.Extensions.Cloning; -using System.Linq; - -namespace SLThree -{ - public class UsingStatement : BaseStatement - { - public NameExpression Alias; - public CreatorUsing Using; - - public UsingStatement(NameExpression alias, CreatorUsing usingBody, SourceContext context) : base(context) - { - Alias = alias; - Using = usingBody; - } - - public UsingStatement(CreatorUsing @using, SourceContext context) : this(null, @using, context) { } - - public override string ToString() => $"using {Using.Type} as {Alias}"; - - public override object GetValue(ExecutionContext context) - { - var @using = Using.GetValue(context).Cast(); - string name; - if (Alias == null) - { - var type_name = Using.GetTypenameWithoutGenerics(); - name = type_name.Contains(".") ? @using.Name.Name : type_name; - name = name.Contains("`") ? name.Substring(0, name.IndexOf("`")) : name; - } - else name = Alias.Name; - context.LocalVariables.SetValue(name, @using); - return null; - } - - public override object Clone() - { - return new UsingStatement(Using.CloneCast(), SourceContext.CloneCast()); - } - } -} diff --git a/SLThree/Visitors/Definition/AbstractVisitor.cs b/SLThree/Visitors/Definition/AbstractVisitor.cs index de1c91c..4fc983e 100644 --- a/SLThree/Visitors/Definition/AbstractVisitor.cs +++ b/SLThree/Visitors/Definition/AbstractVisitor.cs @@ -52,10 +52,11 @@ public virtual void VisitExpression(BaseExpression expression) case UnaryOperator expr: VisitExpression(expr); return; case Special expr: VisitExpression(expr); return; case Literal expr: VisitExpression(expr); return; - case NewExpression expr: VisitExpression(expr); return; + case CreatorInstance expr: VisitExpression(expr); return; case NameExpression expr: VisitExpression(expr); return; - case LambdaExpression expr: VisitExpression(expr); return; - case LambdaGenericExpression expr: VisitExpression(expr); return; + case ConditionExpression expr: VisitExpression(expr); return; + case FunctionDefinition expr: VisitExpression(expr); return; + case StaticExpression expr: VisitExpression(expr); return; case InvokeExpression expr: VisitExpression(expr); return; case InvokeGenericExpression expr: VisitExpression(expr); return; case InterpolatedString expr: VisitExpression(expr); return; @@ -71,6 +72,7 @@ public virtual void VisitExpression(BaseExpression expression) case CreatorContext expr: VisitExpression(expr); return; case CreatorRange expr: VisitExpression(expr); return; case MatchExpression expr: VisitExpression(expr); return; + case UsingExpression expr: VisitExpression(expr); return; } Executables.Remove(expression); } @@ -170,11 +172,7 @@ public virtual void VisitExpression(InvokeGenericExpression expression) VisitExpression(x); } } - public virtual void VisitExpression(LambdaExpression expression) - { - Visit(expression.Method); - } - public virtual void VisitExpression(LambdaGenericExpression expression) + public virtual void VisitExpression(FunctionDefinition expression) { Visit(expression.Method); } @@ -189,13 +187,17 @@ public virtual void VisitExpression(NameExpression expression) } } - public virtual void VisitExpression(NewExpression expression) + public virtual void VisitExpression(CreatorInstance expression) { Executables.Add(expression); - VisitExpression(expression.Typename); + VisitExpression(expression.Type); Executables.Remove(expression); - for (var i = 0; i < expression.Arguments.Length; i++) - VisitExpression(expression.Arguments[i]); + if (expression.Name != null) + VisitExpression(expression.Name); + foreach (var x in expression.Arguments) + VisitExpression(x); + if (expression.CreatorContext != null) + VisitExpression(expression.CreatorContext); } public virtual void VisitExpression(Special expression) @@ -291,13 +293,10 @@ public virtual void VisitStatement(BaseStatement statement) case ForeachLoopStatement st: VisitStatement(st); return; case WhileLoopStatement st: VisitStatement(st); return; case ExpressionStatement st: VisitStatement(st); return; - case ConditionStatement st: VisitStatement(st); return; case ReturnStatement st: VisitStatement(st); return; - case UsingStatement st: VisitStatement(st); return; case StatementList st: VisitStatement(st); return; case BreakStatement st: VisitStatement(st); return; case ContinueStatement st: VisitStatement(st); return; - case ContextStatement st: VisitStatement(st); return; case TryStatement st: VisitStatement(st); return; case ThrowStatement st: VisitStatement(st); return; } @@ -324,10 +323,10 @@ public virtual void VisitStatement(ExpressionStatement statement) VisitExpression(statement.Expression); } - public virtual void VisitStatement(ConditionStatement statement) + public virtual void VisitExpression(ConditionExpression expression) { - VisitExpression(statement.Condition); - foreach (var x in statement.Body) + VisitExpression(expression.Condition); + foreach (var x in expression.Body) VisitStatement(x); } @@ -336,14 +335,11 @@ public virtual void VisitStatement(ReturnStatement statement) if (!statement.VoidReturn) VisitExpression(statement.Expression); } - public virtual void VisitStatement(ContextStatement statement) - { - VisitExpression(statement.Creator); - } - - public virtual void VisitStatement(UsingStatement statement) + public virtual void VisitExpression(UsingExpression statement) { VisitExpression(statement.Using); + if (statement.Alias != null) + VisitExpression(statement.Alias); } public virtual void VisitStatement(StatementList statement) @@ -370,15 +366,12 @@ public virtual void VisitExpression(CreatorNewArray expression) public virtual void VisitExpression(CreatorContext expression) { - if (expression.Typecast != null) - { - Executables.Add(expression); - VisitExpression(expression.Typecast); - Executables.Remove(expression); - } - if (expression.Body != null) - foreach (var x in expression.Body) - VisitStatement(x); + if (expression.HasName) + VisitExpression(expression.Name); + foreach (var x in expression.Ancestors) + VisitExpression(x); + if (expression.CreatorBody != null) + VisitStatement(expression.CreatorBody); } public virtual void VisitExpression(CreatorRange expression) @@ -409,5 +402,10 @@ public virtual void VisitStatement(ThrowStatement statement) { VisitExpression(statement.ThrowExpression); } + + public virtual void VisitExpression(StaticExpression expression) + { + VisitExpression(expression.Right); + } } } diff --git a/SLThree/Visitors/Definition/IExpressionVisitor.cs b/SLThree/Visitors/Definition/IExpressionVisitor.cs index babe5df..03ac3b5 100644 --- a/SLThree/Visitors/Definition/IExpressionVisitor.cs +++ b/SLThree/Visitors/Definition/IExpressionVisitor.cs @@ -6,32 +6,33 @@ public interface IExpressionVisitor void VisitExpression(CreatorArray expression); void VisitExpression(CreatorNewArray expression); - void VisitExpression(CreatorContext expression); void VisitExpression(CreatorDictionary expression); void VisitExpression(CreatorList expression); void VisitExpression(CreatorRange expression); void VisitExpression(CreatorTuple expression); void VisitExpression(CreatorUsing expression); + void VisitExpression(CreatorContext expression); + void VisitExpression(CreatorInstance expression); void VisitExpression(CastExpression expression); + void VisitExpression(ConditionExpression expression); void VisitExpression(IndexExpression expression); void VisitExpression(InterpolatedString expression); void VisitExpression(InvokeExpression expression); void VisitExpression(InvokeGenericExpression expression); - void VisitExpression(LambdaExpression expression); - void VisitExpression(LambdaGenericExpression expression); + void VisitExpression(FunctionDefinition expression); void VisitExpression(MemberAccess expression); void VisitExpression(NameExpression expression); - void VisitExpression(NewExpression expression); void VisitExpression(ReflectionExpression expression); void VisitExpression(TypenameExpression expression); void VisitExpression(MatchExpression expression); + void VisitExpression(StaticExpression expression); + void VisitExpression(UsingExpression statement); void VisitExpression(Special expression); void VisitExpression(Literal expression); void VisitExpression(UnaryOperator expression); void VisitExpression(BinaryOperator expression); void VisitExpression(TernaryOperator expression); - } } diff --git a/SLThree/Visitors/Definition/IStatementVisitor.cs b/SLThree/Visitors/Definition/IStatementVisitor.cs index b9307d0..1454cc7 100644 --- a/SLThree/Visitors/Definition/IStatementVisitor.cs +++ b/SLThree/Visitors/Definition/IStatementVisitor.cs @@ -5,8 +5,6 @@ public interface IStatementVisitor void VisitStatement(BaseStatement statement); void VisitStatement(BreakStatement statement); - void VisitStatement(ContextStatement statement); - void VisitStatement(ConditionStatement statement); void VisitStatement(ContinueStatement statement); void VisitStatement(ExpressionStatement statement); void VisitStatement(ForeachLoopStatement statement); @@ -14,7 +12,6 @@ public interface IStatementVisitor void VisitStatement(StatementList statement); void VisitStatement(ThrowStatement statement); void VisitStatement(TryStatement statement); - void VisitStatement(UsingStatement statement); void VisitStatement(WhileLoopStatement statement); } } diff --git a/SLThree/Wrapper.cs b/SLThree/Wrapper.cs index b8704c2..0a90a1d 100644 --- a/SLThree/Wrapper.cs +++ b/SLThree/Wrapper.cs @@ -1,21 +1,25 @@ using SLThree.Extensions; +using SLThree.Native; using SLThree.sys; using System; using System.Collections; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Reflection; +using System.Reflection.Emit; using System.Runtime.CompilerServices; +using System.Threading; namespace SLThree { - public abstract class WrappersTypeSetting + public static class Wrapper { #region Type Setting - protected static Type generic_list = typeof(List).GetGenericTypeDefinition(); - protected static Type generic_dict = typeof(Dictionary).GetGenericTypeDefinition(); - protected static Type type_ituple = typeof(ITuple); - protected static bool HasRecast(Type type) + internal static Type generic_list = typeof(List).GetGenericTypeDefinition(); + internal static Type generic_dict = typeof(Dictionary).GetGenericTypeDefinition(); + internal static Type type_ituple = typeof(ITuple); + public static bool HasRecast(Type type) { if (type.IsArray) return true; if (type.IsGenericType) @@ -27,14 +31,14 @@ protected static bool HasRecast(Type type) if (interfaces.Contains(type_ituple)) return true; return false; } - protected static object[] TupleToArray(ITuple tuple) + public static object[] TupleToArray(ITuple tuple) { var ret = new object[tuple.Length]; for (var i = 0; i < ret.Length; i++) ret[i] = tuple[i]; return ret; } - internal static object UnwrapCast(Type type_to_cast, object o) + public static object UnwrapCast(Type type_to_cast, object o) { if (type_to_cast.IsArray && o is object[] obj_array) { @@ -121,7 +125,7 @@ internal static object UnwrapCast(Type type_to_cast, object o) } return o.CastToType(type_to_cast); } - internal static object WrapCast(object o) + public static object WrapCast(object o) { if (o == null) return null; var type = o.GetType(); @@ -188,228 +192,933 @@ internal static object WrapCast(object o) } #endregion - internal protected WrappersTypeSetting() { } - } + /// + /// Пропускает этот элемент + /// + [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)] + public sealed class IgnoreAttribute : Attribute + { - public class NonGenericWrapper : WrappersTypeSetting - { - protected Type type; - protected string typename; - protected int counter; - internal string GetWrappedContextName() => $"<{typename}>@{Convert.ToString(counter++, 16).ToUpper().PadLeft(2, '0')}"; - private static Dictionary Wrappers { get; } = new Dictionary(); - public static NonGenericWrapper GetWrapper(Type type) + } + + /// + /// Выделяет элемент для хранения имени + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)] + public sealed class NameAttribute : Attribute { - if (Wrappers.TryGetValue(type, out var value)) return value; - else return new NonGenericWrapper(type); + } - public static NonGenericWrapper GetWrapper() => GetWrapper(typeof(T)); - - protected internal NonGenericWrapper() { } - protected readonly Dictionary Properties = new Dictionary(); - protected Dictionary Fields = new Dictionary(); - protected readonly Dictionary StaticProperties = new Dictionary(); - protected readonly Dictionary StaticFields = new Dictionary(); - protected readonly PropertyInfo InjectContextName = null; - protected readonly bool SupportedNameWrap; - protected internal NonGenericWrapper(Type type) + + /// + /// Выключает неявные приведения при разворачивании для данного элемента + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)] + public sealed class StrongUnwrapAttribute : Attribute { - this.type = type; - Wrappers.Add(type, this); - typename = type.Name; - var props = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy); - foreach (var property in props) - { - if (Attribute.IsDefined(property, typeof(WrapperContextNameAttribute))) InjectContextName = property; - if (Attribute.IsDefined(property, typeof(WrapperSkipAttribute))) continue; - else Properties[property.Name] = property; - } - var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy); - foreach (var field in fields) - { - if (Attribute.IsDefined(field, typeof(WrapperSkipAttribute))) continue; - else Fields[field.Name] = field; - } - var static_props = type.GetProperties(BindingFlags.Static | BindingFlags.Public); - foreach (var property in static_props) - { - if (Attribute.IsDefined(property, typeof(WrapperSkipAttribute))) continue; - //else if (Attribute.IsDefined(property, typeof(WrappeContextNameAttribute))) InjectContextName = property; - else StaticProperties[property.Name] = property; - } - var static_fields = type.GetFields(BindingFlags.Static | BindingFlags.Public); - foreach (var field in static_fields) - { - if (Attribute.IsDefined(field, typeof(WrapperSkipAttribute))) continue; - else StaticFields[field.Name] = field; - } - if (InjectContextName != null) SupportedNameWrap = InjectContextName.SetMethod != null; + + } + + /// + /// Выключает неявные приведения при сворачивании для данного элемента + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)] + public sealed class StrongWrapAttribute : Attribute + { + } - public bool HasName() => InjectContextName != null; - public string GetName(object obj) + /// + /// Заставляет элемент проводить разворачивание и сворачивание словно контекст + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)] + public sealed class ContextAttribute : Attribute { - if (InjectContextName != null) return (string)InjectContextName.GetValue(obj); - throw new ArgumentException($"Type {typename} doesn't have property with InjectContextName"); + } - public ExecutionContext Wrap(object obj) + + /// + /// Позволяет свернуть этот readonly-элемент в контекст + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)] + public sealed class WrapReadonlyAttribute : Attribute { - var ret = new ExecutionContext(); - ret.Name = SupportedNameWrap ? InjectContextName.GetValue(obj).ToString() : GetWrappedContextName(); - foreach (var x in Properties) - ret.LocalVariables.SetValue(x.Key, WrapCast(x.Value.GetValue(obj))); - foreach (var x in Fields) - ret.LocalVariables.SetValue(x.Key, WrapCast(x.Value.GetValue(obj))); - return ret; + } - public ExecutionContext WrapStatic() + + /// + /// Задаёт конструктор, который будет использован при разворачивании + /// + [AttributeUsage(AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)] + public sealed class ConstructorAttribute : Attribute { - var ret = new ExecutionContext(); - ret.Name = GetWrappedContextName(); - foreach (var x in StaticProperties) - ret.LocalVariables.SetValue(x.Key, WrapCast(x.Value.GetValue(null))); - foreach (var x in StaticFields) - ret.LocalVariables.SetValue(x.Key, WrapCast(x.Value.GetValue(null))); - return ret; + + } + + /// + /// Выделяет метод, возвращающий аргументы для конструктора + /// сигнатуры static Func<ExecutionContext, object[]> + /// + [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + public sealed class ConstructorArgsAttribute : Attribute + { + } - public void SafeUnwrapStatic(ExecutionContext context) + + private class WrappingMemberInfo { - foreach (var name in context.LocalVariables.GetAsDictionary()) + public MemberInfo MemberInfo; + public bool IsStrongWrap; + public bool IsStrongUnwrap; + public bool IsWrapReadonly; + public bool IsContext; + public bool IsField; + public int id = 0; + } + + /// + /// + /// + /// + /// (элементы, элемент-имя, конструктор, метод для аргументов конструктора) + private static (List, WrappingMemberInfo, ConstructorInfo, MethodInfo) Collect(Type type) + { + var ret = new List(); + var name = default(WrappingMemberInfo); + var constructor = default(ConstructorInfo); + var constructorargs = default(MethodInfo); + var id = 0; + + void Check(MemberInfo member) { - try + switch (member.MemberType) { - if (Properties.ContainsKey(name.Key) && Properties[name.Key].SetMethod != null) - Properties[name.Key].SetValue(null, UnwrapCast(Properties[name.Key].PropertyType, name.Value)); - else if (Fields.ContainsKey(name.Key)) Fields[name.Key].SetValue(null, UnwrapCast(Fields[name.Key].FieldType, name.Value)); + case MemberTypes.Field: + { + var field = (FieldInfo)member; + if (field.IsInitOnly && member.GetCustomAttribute() == null) return; + var m = new WrappingMemberInfo + { + MemberInfo = member, + IsWrapReadonly = field.IsInitOnly, + IsContext = member.GetCustomAttribute() != null, + IsStrongUnwrap = member.GetCustomAttribute() != null, + IsStrongWrap = member.GetCustomAttribute() != null, + IsField = true, + id = id++, + }; + if (member.GetCustomAttribute() == null) ret.Add(m); + else + { + if (field.IsInitOnly) throw new NotSupportedException($"Wrapper.Name cannot be readonly [{field}]"); + if (name != null) throw new NotSupportedException($"Wrapper.Name has already been defined [{field}]"); + name = m; + id--; + } + } + break; + case MemberTypes.Property: + { + var property = (PropertyInfo)member; + if (!property.CanRead) return; + if (!property.CanWrite && member.GetCustomAttribute() == null) return; + var m = new WrappingMemberInfo + { + MemberInfo = member, + IsWrapReadonly = !property.CanWrite, + IsContext = member.GetCustomAttribute() != null, + IsStrongUnwrap = member.GetCustomAttribute() != null, + IsStrongWrap = member.GetCustomAttribute() != null, + id = id++, + }; + if (member.GetCustomAttribute() == null) ret.Add(m); + else + { + if (!property.CanWrite) throw new NotSupportedException($"Wrapper.Name cannot be readonly [{property}]"); + if (name != null) throw new NotSupportedException($"Wrapper.Name has already been defined [{property}]"); + name = m; + id--; + } + } + break; + case MemberTypes.Constructor: + { + var ctor = (ConstructorInfo)member; + if (ctor.GetParameters().Length == 0) + { + constructor = ctor; + return; + } + if (member.GetCustomAttribute(typeof(ConstructorAttribute)) == null) return; + if (constructor != null && constructor.GetParameters().Length != 0) throw new NotSupportedException($"Explicit constructor has already been defined [{constructor}]"); + constructor = ctor; + } + break; } - catch (Exception e) + } + + void CheckCtorArgs(MemberInfo member) + { + switch (member.MemberType) { - context.Errors.Add(e); + case MemberTypes.Method: + { + if (member.GetCustomAttribute() == null) return; + var method = (MethodInfo)member; + var pars = method.GetParameters(); + if (method.ReturnType != typeof(object[]) || !(pars.Length == 1 && pars[0].ParameterType == ContextType)) throw new NotSupportedException($"Wrong signature... [{method}]"); + constructorargs = method; + } + break; } } - } - public void UnwrapStatic(ExecutionContext context) - { - foreach (var name in context.LocalVariables.GetAsDictionary()) + + foreach (var member in type.GetMembers(BindingFlags.Public | BindingFlags.Instance)) { - if (Properties.ContainsKey(name.Key) && Properties[name.Key].SetMethod != null) - Properties[name.Key].SetValue(null, UnwrapCast(Properties[name.Key].PropertyType, name.Value)); - else if (Fields.ContainsKey(name.Key)) Fields[name.Key].SetValue(null, UnwrapCast(Fields[name.Key].FieldType, name.Value)); + if (member.GetCustomAttribute() != null) continue; + Check(member); } + + foreach (var member in type.GetMembers(BindingFlags.Public | BindingFlags.Static)) + { + if (member.GetCustomAttribute() != null) continue; + CheckCtorArgs(member); + } + + if (constructor != null && constructor.GetParameters().Length != 0 && constructorargs == null) + { + throw new NotSupportedException($"{type.Name} must have Wrapper.ConstructorArgs method because it has an explicit constructor"); + } + + return (ret, name, constructor, constructorargs); } - public ExecutionContext WrapStaticClass() - { - var ret = new ExecutionContext(); - ret.Name = GetWrappedContextName(); - var props = StaticProperties; - var fields = StaticFields; - foreach (var x in props) - ret.LocalVariables.SetValue(x.Key, x.Value.GetValue(null)); - foreach (var x in fields) - ret.LocalVariables.SetValue(x.Key, x.Value.GetValue(null)); - return ret; - } - public void UnwrapStaticClass(ExecutionContext context) + private static (List, WrappingMemberInfo) CollectStatic(Type type) { - var props = StaticProperties; - var fields = StaticFields; - foreach (var name in context.LocalVariables.GetAsDictionary()) + var ret = new List(); + var name = default(WrappingMemberInfo); + var id = 0; + + void Check(MemberInfo member) + { + switch (member.MemberType) + { + case MemberTypes.Field: + { + var field = (FieldInfo)member; + if (field.IsInitOnly && member.GetCustomAttribute() == null) return; + var m = new WrappingMemberInfo + { + MemberInfo = member, + IsWrapReadonly = type.IsEnum ? true : field.IsInitOnly, + IsContext = member.GetCustomAttribute() != null, + IsStrongUnwrap = member.GetCustomAttribute() != null, + IsStrongWrap = member.GetCustomAttribute() != null, + IsField = true, + id = id++, + }; + if (member.GetCustomAttribute() == null) ret.Add(m); + else + { + if (field.IsInitOnly) throw new NotSupportedException($"StaticWrapper.Name cannot be readonly [{field}]"); + if (name != null) throw new NotSupportedException($"StaticWrapper.Name has already been defined [{field}]"); + name = m; + id--; + } + } + break; + case MemberTypes.Property: + { + var property = (PropertyInfo)member; + if (!property.CanRead) return; + if (!property.CanWrite && member.GetCustomAttribute() == null) return; + var m = new WrappingMemberInfo + { + MemberInfo = member, + IsWrapReadonly = !property.CanWrite, + IsContext = member.GetCustomAttribute() != null, + IsStrongUnwrap = member.GetCustomAttribute() != null, + IsStrongWrap = member.GetCustomAttribute() != null, + id = id++, + }; + if (member.GetCustomAttribute() == null) ret.Add(m); + else + { + if (!property.CanWrite) throw new NotSupportedException($"StaticWrapper.Name cannot be readonly [{property}]"); + if (name != null) throw new NotSupportedException($"StaticWrapper.Name has already been defined [{property}]"); + name = m; + id--; + } + } + break; + } + } + + foreach (var member in type.GetMembers(BindingFlags.Public | BindingFlags.Static)) { - if (props.ContainsKey(name.Key) && props[name.Key].SetMethod != null) - props[name.Key].SetValue(null, UnwrapCast(props[name.Key].PropertyType, name.Value)); - else if (fields.ContainsKey(name.Key)) fields[name.Key].SetValue(null, UnwrapCast(fields[name.Key].FieldType, name.Value)); + if (member.GetCustomAttribute() != null) continue; + Check(member); } + + return (ret, name); } - public void SafeUnwrapStaticClass(ExecutionContext context) + + private static Type ContextType = typeof(ExecutionContext); + private static Type LocalsType = typeof(LocalVariablesContainer); + private static Type Void = typeof(void); + + internal static MethodInfo GetPropertyGetter(PropertyInfo propertyInfo) => propertyInfo.GetAccessors(false).FirstOrDefault(x => x.ReturnType != Void); + internal static MethodInfo GetPropertySetter(PropertyInfo propertyInfo) => propertyInfo.GetAccessors(false).FirstOrDefault(x => x.ReturnType == Void); + private static Type GetElementType(WrappingMemberInfo elem) => elem.IsField ? ((FieldInfo)elem.MemberInfo).FieldType : ((PropertyInfo)elem.MemberInfo).PropertyType; + + internal static (Delegate, Delegate, Delegate, Delegate, Delegate, Dictionary) InitStaticWrapper(Type type) { - var props = StaticProperties; - var fields = StaticFields; - foreach (var name in context.LocalVariables.GetAsDictionary()) + var (elems, nameelem) = CollectStatic(type); + + void LoadElement(WrappingMemberInfo elem, ILGenerator il) + { + if (elem.IsField) + { + NETGenerator.EmitLoadStaticFieldOrConst((FieldInfo)elem.MemberInfo, il); + } + else il.Emit(OpCodes.Callvirt, GetPropertyGetter((PropertyInfo)elem.MemberInfo)); + } + + void SetElement(WrappingMemberInfo elem, ILGenerator il) { - try + if (elem.IsField) il.Emit(OpCodes.Stsfld, (FieldInfo)elem.MemberInfo); + else il.Emit(OpCodes.Callvirt, GetPropertySetter((PropertyInfo)elem.MemberInfo)); + } + + var quickwrapper = default(Delegate); + { + var wrapper_dm = new DynamicMethod("QuickWrapper", Void, new Type[2] { ContextType, LocalsType }); + var wrapper_il = wrapper_dm.GetILGenerator(); + + if (elems.Count > 0) { - if (props.ContainsKey(name.Key) && props[name.Key].SetMethod != null) - props[name.Key].SetValue(null, UnwrapCast(props[name.Key].PropertyType, name.Value)); - else if (fields.ContainsKey(name.Key)) fields[name.Key].SetValue(null, UnwrapCast(fields[name.Key].FieldType, name.Value)); + wrapper_il.Emit(OpCodes.Ldarg_1); + wrapper_il.Emit(OpCodes.Ldfld, LocalsType.GetField("Variables")); } - catch (Exception e) + for (var i = 0; i < elems.Count; i++) { - context.Errors.Add(e); + if (i < elems.Count - 1) wrapper_il.Emit(OpCodes.Dup); + wrapper_il.Emit(OpCodes.Ldc_I4, elems[i].id); + LoadElement(elems[i], wrapper_il); + + var elem_type = GetElementType(elems[i]); + if (elems[i].IsContext) + { + wrapper_il.Emit(OpCodes.Ldarg_1); + wrapper_il.Emit(OpCodes.Call, typeof(Wrapper<>).MakeGenericType(new Type[] { elem_type }).GetMethod("WrapUnder", BindingFlags.Public | BindingFlags.Static)); + } + else + { + if (elem_type.IsValueType) + wrapper_il.Emit(OpCodes.Box, elem_type); + } + if (!elems[i].IsStrongWrap && HasRecast(elem_type)) + wrapper_il.Emit(OpCodes.Call, typeof(Wrapper).GetMethod("WrapCast", BindingFlags.Public | BindingFlags.Static)); + + wrapper_il.Emit(OpCodes.Stelem_Ref); } + + wrapper_il.Emit(OpCodes.Ret); + quickwrapper = wrapper_dm.CreateDelegate(typeof(Action<,>).MakeGenericType(new Type[2] { ContextType, LocalsType })); } - } - public object Unwrap(ExecutionContext context) - { - var ret = Activator.CreateInstance(type); - InjectContextName?.SetValue(ret, context.Name); - foreach (var name in context.LocalVariables.GetAsDictionary()) + + var safewrapper = default(Delegate); { - if (Properties.ContainsKey(name.Key) && Properties[name.Key].SetMethod != null) - Properties[name.Key].SetValue(ret, UnwrapCast(Properties[name.Key].PropertyType, name.Value)); - else if (Fields.ContainsKey(name.Key)) Fields[name.Key].SetValue(ret, UnwrapCast(Fields[name.Key].FieldType, name.Value)); + var wrapper_dm = new DynamicMethod("SafeWrapper", Void, new Type[] { ContextType, LocalsType }); + var wrapper_il = wrapper_dm.GetILGenerator(); + + for (var i = 0; i < elems.Count; i++) + { + wrapper_il.Emit(OpCodes.Ldarg_1); + wrapper_il.Emit(OpCodes.Ldstr, elems[i].MemberInfo.Name); + LoadElement(elems[i], wrapper_il); + + var elem_type = GetElementType(elems[i]); + if (elems[i].IsContext) + { + wrapper_il.Emit(OpCodes.Ldarg_0); + wrapper_il.Emit(OpCodes.Call, typeof(Wrapper<>).MakeGenericType(new Type[] { elem_type }).GetMethod("WrapUnder", BindingFlags.Public | BindingFlags.Static)); + } + else + { + if (elem_type.IsValueType) + wrapper_il.Emit(OpCodes.Box, elem_type); + + if (!elems[i].IsStrongWrap && HasRecast(elem_type)) + wrapper_il.Emit(OpCodes.Call, typeof(Wrapper).GetMethod("WrapCast", BindingFlags.Public | BindingFlags.Static)); + } + + wrapper_il.Emit(OpCodes.Callvirt, typeof(LocalVariablesContainer).GetMethod("SetValue", new Type[] { typeof(string), typeof(object) })); + wrapper_il.Emit(OpCodes.Pop); + } + + wrapper_il.Emit(OpCodes.Ret); + safewrapper = wrapper_dm.CreateDelegate(typeof(Action<,>).MakeGenericType(new Type[] { ContextType, LocalsType })); } - return ret; + + var unwrapper = default(Delegate); + { + var unwrapper_dm = new DynamicMethod("Unwrapper", Void, new Type[] { LocalsType }); + var unwrapper_il = unwrapper_dm.GetILGenerator(); + unwrapper_il.DeclareLocal(typeof(int)); + unwrapper_il.DeclareLocal(typeof(object[])); + unwrapper_il.DeclareLocal(typeof(ContextWrap)); + + unwrapper_il.Emit(OpCodes.Ldc_I4_0); + unwrapper_il.Emit(OpCodes.Stloc_0); + unwrapper_il.Emit(OpCodes.Ldarg_0); + unwrapper_il.Emit(OpCodes.Ldfld, typeof(LocalVariablesContainer).GetField("NamedIdentificators")); + unwrapper_il.Emit(OpCodes.Ldarg_0); + unwrapper_il.Emit(OpCodes.Ldfld, typeof(LocalVariablesContainer).GetField("Variables")); + unwrapper_il.Emit(OpCodes.Stloc_1); + + + var label = default(Label); + + for (var i = 0; i < elems.Count; i++) + { + if (elems[i].IsWrapReadonly) continue; + if (i < elems.Count - 1) unwrapper_il.Emit(OpCodes.Dup); + + unwrapper_il.Emit(OpCodes.Ldstr, elems[i].MemberInfo.Name); + unwrapper_il.Emit(OpCodes.Ldloca_S, 0); + unwrapper_il.Emit(OpCodes.Callvirt, typeof(Dictionary).GetMethod("TryGetValue")); + unwrapper_il.Emit(OpCodes.Brfalse_S, label = unwrapper_il.DefineLabel()); + + + var elem_type = GetElementType(elems[i]); + if (elems[i].IsContext) + { + unwrapper_il.Emit(OpCodes.Ldloc_1); + unwrapper_il.Emit(OpCodes.Ldloc_0); + unwrapper_il.Emit(OpCodes.Ldelem_Ref); + unwrapper_il.Emit(OpCodes.Isinst, typeof(ContextWrap)); + unwrapper_il.Emit(OpCodes.Stloc_2); + unwrapper_il.Emit(OpCodes.Ldloc_2); + unwrapper_il.Emit(OpCodes.Brfalse_S, label); + + unwrapper_il.Emit(OpCodes.Ldloc_2); + //unwrapper_il.Emit(OpCodes.Ldfld, typeof(ContextWrap).GetField("Context")); + unwrapper_il.Emit(OpCodes.Call, typeof(Wrapper<>).MakeGenericType(new Type[] { elem_type }).GetMethod("UnwrapUnder", BindingFlags.Public | BindingFlags.Static)); + SetElement(elems[i], unwrapper_il); + } + else + { + unwrapper_il.Emit(OpCodes.Ldloc_1); + unwrapper_il.Emit(OpCodes.Ldloc_0); + unwrapper_il.Emit(OpCodes.Ldelem_Ref); + + if (elem_type.IsValueType) unwrapper_il.Emit(OpCodes.Unbox_Any, elem_type); + else unwrapper_il.Emit(OpCodes.Castclass, elem_type); + + if (!elems[i].IsStrongUnwrap && HasRecast(elem_type)) + unwrapper_il.Emit(OpCodes.Call, typeof(Wrapper).GetMethod("UnwrapCast", BindingFlags.Public | BindingFlags.Static)); + + SetElement(elems[i], unwrapper_il); + } + unwrapper_il.MarkLabel(label); + } + + unwrapper_il.Emit(OpCodes.Ret); + unwrapper = unwrapper_dm.CreateDelegate(typeof(Action<>).MakeGenericType(new Type[] { LocalsType })); + } + + var wrapname = default(Delegate); + { + var wrapname_dm = new DynamicMethod("WrapName", Void, new Type[] { ContextType }); + var wrapname_il = wrapname_dm.GetILGenerator(); + if (nameelem != null) + { + if (GetElementType(nameelem) != typeof(string)) throw new NotSupportedException($"Name must be string [{nameelem}]"); + + wrapname_il.Emit(OpCodes.Ldarg_1); + LoadElement(nameelem, wrapname_il); + + wrapname_il.Emit(OpCodes.Stfld, ContextType.GetField("Name", BindingFlags.Public | BindingFlags.Instance)); + } + wrapname_il.Emit(OpCodes.Ret); + wrapname = wrapname_dm.CreateDelegate(typeof(Action<>).MakeGenericType(new Type[] { ContextType })); + } + + var unwrapname = default(Delegate); + { + var wrapname_dm = new DynamicMethod("UnwrapName", Void, new Type[] { ContextType }); + var wrapname_il = wrapname_dm.GetILGenerator(); + if (nameelem != null) + { + if (GetElementType(nameelem) != typeof(string)) throw new NotSupportedException($"Name must be string [{nameelem}]"); + + wrapname_il.Emit(OpCodes.Ldarg_0); + wrapname_il.Emit(OpCodes.Ldfld, ContextType.GetField("Name", BindingFlags.Public | BindingFlags.Instance)); + SetElement(nameelem, wrapname_il); + } + wrapname_il.Emit(OpCodes.Ret); + unwrapname = wrapname_dm.CreateDelegate(typeof(Action<>).MakeGenericType(new Type[] { ContextType })); + } + + return (quickwrapper, safewrapper, unwrapper, wrapname, unwrapname, elems.ToDictionary(x => x.MemberInfo.Name, x => x.id)); } - public object SafeUnwrap(ExecutionContext context) + internal static (Delegate, Delegate, Delegate, Delegate, Delegate, Delegate, Dictionary) InitWrapper(Type type) { - var ret = Activator.CreateInstance(type); - try + if (type.IsAbstract && type.IsSealed) throw new NotSupportedException("Non-static Wrapper not supported static classes"); + + var (elems, nameelem, explicit_constructor, explicit_constructor_args) = Collect(type); + + void LoadElement(WrappingMemberInfo elem, ILGenerator il) { - InjectContextName?.SetValue(ret, context.Name); + if (elem.IsField) il.Emit(OpCodes.Ldfld, (FieldInfo)elem.MemberInfo); + else il.Emit(OpCodes.Callvirt, GetPropertyGetter((PropertyInfo)elem.MemberInfo)); } - catch (Exception e) + + void SetElement(WrappingMemberInfo elem, ILGenerator il) { - context.Errors.Add(e); + if (elem.IsField) il.Emit(OpCodes.Stfld, (FieldInfo)elem.MemberInfo); + else il.Emit(OpCodes.Callvirt, GetPropertySetter((PropertyInfo)elem.MemberInfo)); } - foreach (var name in context.LocalVariables.GetAsDictionary()) + + var quickwrapper = default(Delegate); { - try + var wrapper_dm = new DynamicMethod("QuickWrapper", Void, new Type[] { type, ContextType, LocalsType }); + var wrapper_il = wrapper_dm.GetILGenerator(); + + if (elems.Count > 0) { - if (Properties.ContainsKey(name.Key) && Properties[name.Key].SetMethod != null) - Properties[name.Key].SetValue(ret, UnwrapCast(Properties[name.Key].PropertyType, name.Value)); - else if (Fields.ContainsKey(name.Key)) Fields[name.Key].SetValue(ret, UnwrapCast(Fields[name.Key].FieldType, name.Value)); + wrapper_il.Emit(OpCodes.Ldarg_2); + wrapper_il.Emit(OpCodes.Ldfld, LocalsType.GetField("Variables", BindingFlags.Public | BindingFlags.Instance)); } - catch (Exception e) + + for (var i = 0; i < elems.Count; i++) { - context.Errors.Add(e); + if (i < elems.Count - 1) wrapper_il.Emit(OpCodes.Dup); + wrapper_il.Emit(OpCodes.Ldc_I4, elems[i].id); + + wrapper_il.Emit(OpCodes.Ldarg_0); + LoadElement(elems[i], wrapper_il); + + var elem_type = GetElementType(elems[i]); + if (elems[i].IsContext) + { + wrapper_il.Emit(OpCodes.Ldarg_1); + wrapper_il.Emit(OpCodes.Call, typeof(Wrapper<>).MakeGenericType(new Type[] { elem_type }).GetMethod("WrapUnder", BindingFlags.Public | BindingFlags.Static)); + } + else + { + if (elem_type.IsValueType) + wrapper_il.Emit(OpCodes.Box, elem_type); + } + if (!elems[i].IsStrongWrap && HasRecast(elem_type)) + wrapper_il.Emit(OpCodes.Call, typeof(Wrapper).GetMethod("WrapCast", BindingFlags.Public | BindingFlags.Static)); + + wrapper_il.Emit(OpCodes.Stelem_Ref); } + + wrapper_il.Emit(OpCodes.Ret); + quickwrapper = wrapper_dm.CreateDelegate(typeof(Action<,,>).MakeGenericType(new Type[] { type, ContextType, LocalsType })); } - return ret; + + var safewrapper = default(Delegate); + { + var wrapper_dm = new DynamicMethod("SafeWrapper", Void, new Type[] { type, ContextType, LocalsType }); + var wrapper_il = wrapper_dm.GetILGenerator(); + + for (var i = 0; i < elems.Count; i++) + { + wrapper_il.Emit(OpCodes.Ldarg_2); + wrapper_il.Emit(OpCodes.Ldstr, elems[i].MemberInfo.Name); + wrapper_il.Emit(OpCodes.Ldarg_0); + LoadElement(elems[i], wrapper_il); + + var elem_type = GetElementType(elems[i]); + if (elems[i].IsContext) + { + wrapper_il.Emit(OpCodes.Ldarg_1); + wrapper_il.Emit(OpCodes.Call, typeof(Wrapper<>).MakeGenericType(new Type[] { elem_type }).GetMethod("WrapUnder", BindingFlags.Public | BindingFlags.Static)); + } + else + { + if (elem_type.IsValueType) + wrapper_il.Emit(OpCodes.Box, elem_type); + + if (!elems[i].IsStrongWrap && HasRecast(elem_type)) + wrapper_il.Emit(OpCodes.Call, typeof(Wrapper).GetMethod("WrapCast", BindingFlags.Public | BindingFlags.Static)); + } + + wrapper_il.Emit(OpCodes.Callvirt, typeof(LocalVariablesContainer).GetMethod("SetValue", new Type[] {typeof(string), typeof(object)})); + wrapper_il.Emit(OpCodes.Pop); + } + + wrapper_il.Emit(OpCodes.Ret); + safewrapper = wrapper_dm.CreateDelegate(typeof(Action<,,>).MakeGenericType(new Type[] { type, ContextType, LocalsType })); + } + + var unwrapper = default(Delegate); + { + var unwrapper_dm = new DynamicMethod("Unwrapper", Void, new Type[] { LocalsType, type }); + var unwrapper_il = unwrapper_dm.GetILGenerator(); + + if (elems.Count > 0) + { + unwrapper_il.DeclareLocal(typeof(int)); + unwrapper_il.DeclareLocal(typeof(object[])); + unwrapper_il.DeclareLocal(typeof(ContextWrap)); + + unwrapper_il.Emit(OpCodes.Ldc_I4_0); + unwrapper_il.Emit(OpCodes.Stloc_0); + unwrapper_il.Emit(OpCodes.Ldarg_0); + unwrapper_il.Emit(OpCodes.Ldfld, typeof(LocalVariablesContainer).GetField("NamedIdentificators")); + unwrapper_il.Emit(OpCodes.Ldarg_0); + unwrapper_il.Emit(OpCodes.Ldfld, typeof(LocalVariablesContainer).GetField("Variables")); + unwrapper_il.Emit(OpCodes.Stloc_1); + + + var label = default(Label); + + for (var i = 0; i < elems.Count; i++) + { + if (elems[i].IsWrapReadonly) continue; + if (i < elems.Count - 1) unwrapper_il.Emit(OpCodes.Dup); + + unwrapper_il.Emit(OpCodes.Ldstr, elems[i].MemberInfo.Name); + unwrapper_il.Emit(OpCodes.Ldloca_S, 0); + unwrapper_il.Emit(OpCodes.Callvirt, typeof(Dictionary).GetMethod("TryGetValue")); + unwrapper_il.Emit(OpCodes.Brfalse_S, label = unwrapper_il.DefineLabel()); + + + var elem_type = GetElementType(elems[i]); + if (elems[i].IsContext) + { + unwrapper_il.Emit(OpCodes.Ldloc_1); + unwrapper_il.Emit(OpCodes.Ldloc_0); + unwrapper_il.Emit(OpCodes.Ldelem_Ref); + unwrapper_il.Emit(OpCodes.Isinst, typeof(ContextWrap)); + unwrapper_il.Emit(OpCodes.Stloc_2); + unwrapper_il.Emit(OpCodes.Ldloc_2); + unwrapper_il.Emit(OpCodes.Brfalse_S, label); + + unwrapper_il.Emit(OpCodes.Ldarg_1); + unwrapper_il.Emit(OpCodes.Ldloc_2); + //unwrapper_il.Emit(OpCodes.Ldfld, typeof(ContextWrap).GetField("Context")); + unwrapper_il.Emit(OpCodes.Call, typeof(Wrapper<>).MakeGenericType(new Type[] { elem_type }).GetMethod("UnwrapUnder", BindingFlags.Public | BindingFlags.Static)); + SetElement(elems[i], unwrapper_il); + } + else + { + unwrapper_il.Emit(OpCodes.Ldarg_1); + unwrapper_il.Emit(OpCodes.Ldloc_1); + unwrapper_il.Emit(OpCodes.Ldloc_0); + unwrapper_il.Emit(OpCodes.Ldelem_Ref); + + if (elem_type.IsValueType) unwrapper_il.Emit(OpCodes.Unbox_Any, elem_type); + else unwrapper_il.Emit(OpCodes.Castclass, elem_type); + + if (!elems[i].IsStrongUnwrap && HasRecast(elem_type)) + unwrapper_il.Emit(OpCodes.Call, typeof(Wrapper).GetMethod("UnwrapCast", BindingFlags.Public | BindingFlags.Static)); + + SetElement(elems[i], unwrapper_il); + } + unwrapper_il.MarkLabel(label); + } + } + + unwrapper_il.Emit(OpCodes.Ret); + unwrapper = unwrapper_dm.CreateDelegate(typeof(Action<,>).MakeGenericType(new Type[] { LocalsType, type })); + } + + var wrapname = default(Delegate); + { + var wrapname_dm = new DynamicMethod("WrapName", Void, new Type[] { type, ContextType }); + var wrapname_il = wrapname_dm.GetILGenerator(); + if (nameelem != null) + { + if (GetElementType(nameelem) != typeof(string)) throw new NotSupportedException($"Name must be string [{nameelem}]"); + + wrapname_il.Emit(OpCodes.Ldarg_1); + wrapname_il.Emit(OpCodes.Ldarg_0); + LoadElement(nameelem, wrapname_il); + + wrapname_il.Emit(OpCodes.Stfld, ContextType.GetField("Name", BindingFlags.Public | BindingFlags.Instance)); + } + wrapname_il.Emit(OpCodes.Ret); + wrapname = wrapname_dm.CreateDelegate(typeof(Action<,>).MakeGenericType(new Type[] { type, ContextType })); + } + + var unwrapname = default(Delegate); + { + var wrapname_dm = new DynamicMethod("UnwrapName", Void, new Type[] { ContextType, type }); + var wrapname_il = wrapname_dm.GetILGenerator(); + if (nameelem != null) + { + if (GetElementType(nameelem) != typeof(string)) throw new NotSupportedException($"Name must be string [{nameelem}]"); + + wrapname_il.Emit(OpCodes.Ldarg_1); + wrapname_il.Emit(OpCodes.Ldarg_0); + wrapname_il.Emit(OpCodes.Ldfld, ContextType.GetField("Name", BindingFlags.Public | BindingFlags.Instance)); + SetElement(nameelem, wrapname_il); + } + wrapname_il.Emit(OpCodes.Ret); + unwrapname = wrapname_dm.CreateDelegate(typeof(Action<,>).MakeGenericType(new Type[] { ContextType, type })); + } + + var initor = default(Delegate); + if (explicit_constructor != null) + { + if (explicit_constructor.GetParameters().Length > 0) + { + var initor_dm = new DynamicMethod("Initor", type, new Type[1] { ContextType }, true); + var initor_il = initor_dm.GetILGenerator(); + initor_il.Emit(OpCodes.Ldarg_0); + initor_il.Emit(OpCodes.Call, explicit_constructor_args); + initor_il.DeclareLocal(typeof(object[])); + initor_il.Emit(OpCodes.Stloc_0); + var i = 0; + foreach (var p in explicit_constructor.GetParameters()) + { + initor_il.Emit(OpCodes.Ldloc_0); + initor_il.Emit(OpCodes.Ldc_I4, i++); + initor_il.Emit(OpCodes.Ldelem_Ref); + if (p.ParameterType.IsValueType) initor_il.Emit(OpCodes.Unbox_Any, p.ParameterType); + else initor_il.Emit(OpCodes.Castclass, p.ParameterType); + } + initor_il.Emit(OpCodes.Newobj, explicit_constructor); + initor_il.Emit(OpCodes.Ret); + initor = initor_dm.CreateDelegate(typeof(Func<,>).MakeGenericType(new Type[] { ContextType, type })); + } + else + { + var initor_dm = new DynamicMethod("Initor", type, new Type[1] { ContextType }, true); + var initor_il = initor_dm.GetILGenerator(); + initor_il.Emit(OpCodes.Newobj, explicit_constructor); + initor_il.Emit(OpCodes.Ret); + initor = initor_dm.CreateDelegate(typeof(Func<,>).MakeGenericType(new Type[] { ContextType, type })); + } + } + + return (quickwrapper, safewrapper, unwrapper, wrapname, unwrapname, initor, elems.ToDictionary(x => x.MemberInfo.Name, x => x.id)); } + + #region Extensions + public static ExecutionContext Wrap(this T obj) => Wrapper.Wrap(obj); + public static T Unwrap(this ExecutionContext context) => Wrapper.Unwrap(context); + public static void WrapIn(this T obj, ExecutionContext context) => Wrapper.WrapIn(obj, context); + public static void UnwrapIn(this ExecutionContext context, T obj) => Wrapper.UnwrapIn(context, obj); + public static ExecutionContext StaticWrap() => StaticWrapper.Wrap(); + public static void StaticUnwrap(this ExecutionContext context) => StaticWrapper.Unwrap(context); + public static void StaticWrapIn(this ExecutionContext context) => StaticWrapper.WrapIn(context); + public static void StaticUnwrapIn(this ExecutionContext context) => StaticWrapper.UnwrapIn(context); + + public static readonly NonGenericWrapper NonGeneric = new NonGenericWrapper(typeof(object)); + public static readonly NonGenericStaticWrapper NonGenericStatic = new NonGenericStaticWrapper(typeof(object)); + public static ExecutionContext StaticWrap(this Type T) => NonGenericStatic[T].Wrap(); + public static void StaticUnwrap(this ExecutionContext context, Type T) => NonGenericStatic[T].Unwrap(context); + public static void StaticUnwrap(this Type T, ExecutionContext context) => NonGenericStatic[T].Unwrap(context); + public static void StaticWrapIn(this Type T, ExecutionContext context) => NonGenericStatic[T].WrapIn(context); + public static void StaticWrapIn(this ExecutionContext context, Type T) => NonGenericStatic[T].WrapIn(context); + public static void StaticUnwrapIn(this ExecutionContext context, Type T) => NonGenericStatic[T].UnwrapIn(context); + public static void StaticUnwrapIn(this Type T, ExecutionContext context) => NonGenericStatic[T].UnwrapIn(context); + public static ExecutionContext Wrap(this object obj, Type T) => NonGeneric[T].Wrap(obj); + public static ExecutionContext InstanceWrap(this Type T, object obj) => NonGeneric[T].Wrap(obj); + public static object Unwrap(this ExecutionContext context, Type T) => NonGeneric[T].Unwrap(context); + public static object InstanceUnwrap(this Type T, ExecutionContext context) => NonGeneric[T].Unwrap(context); + public static void WrapIn(this object obj, Type T, ExecutionContext context) => NonGeneric[T].WrapIn(obj, context); + public static void InstanceWrapIn(this Type T, object obj, ExecutionContext context) => NonGeneric[T].WrapIn(obj, context); + public static void UnwrapIn(this ExecutionContext context, Type T, object obj) => NonGeneric[T].UnwrapIn(context, obj); + public static void InstanceUnwrapIn(this Type T, ExecutionContext context, object obj) => NonGeneric[T].UnwrapIn(context, obj); + public static bool HasInitor(this Type T) => NonGeneric[T].HasInitior; + public sealed class NonGenericStaticWrapper + { + public readonly MethodInfo mWrap; + public readonly MethodInfo mUnwrap; + public readonly MethodInfo mWrapIn; + public readonly MethodInfo mUnwrapIn; + + internal NonGenericStaticWrapper(Type T) + { + var type = typeof(StaticWrapper<>).MakeGenericType(T); + mWrap = type.GetMethod("Wrap"); + mUnwrap = type.GetMethod("Unwrap"); + mWrapIn = type.GetMethod("WrapIn"); + mUnwrapIn = type.GetMethod("UnwrapIn"); + nongeneric_wrappers[T] = this; + } + + private static readonly Dictionary nongeneric_wrappers = new Dictionary(); + public NonGenericStaticWrapper this[Type type] + { + get + { + if (nongeneric_wrappers.TryGetValue(type, out var ret)) return ret; + return new NonGenericStaticWrapper(type); + } + } + + public ExecutionContext Wrap() => (ExecutionContext)mWrap.Invoke(null, Array.Empty()); + public void Unwrap(ExecutionContext context) => mUnwrap.Invoke(null, new object[] { context }); + public void WrapIn(ExecutionContext context) => mWrapIn.Invoke(null, new object[] { context }); + public void UnwrapIn(ExecutionContext context) => mUnwrapIn.Invoke(null, new object[] { context }); + } + public sealed class NonGenericWrapper + { + public readonly MethodInfo mWrap; + public readonly MethodInfo mUnwrap; + public readonly MethodInfo mWrapIn; + public readonly MethodInfo mUnwrapIn; + public readonly bool HasInitior; + + internal NonGenericWrapper(Type T) + { + var type = typeof(Wrapper<>).MakeGenericType(T); + mWrap = type.GetMethod("Wrap"); + mUnwrap = type.GetMethod("Unwrap"); + mWrapIn = type.GetMethod("WrapIn"); + mUnwrapIn = type.GetMethod("UnwrapIn"); + HasInitior = (bool)type.GetField("HasInitor").GetValue(null); + nongeneric_wrappers[T] = this; + } + + private static readonly Dictionary nongeneric_wrappers = new Dictionary(); + public NonGenericWrapper this[Type type] + { + get + { + if (nongeneric_wrappers.TryGetValue(type, out var ret)) return ret; + return new NonGenericWrapper(type); + } + } + + public ExecutionContext Wrap(object obj) => (ExecutionContext)mWrap.Invoke(null, new object[] { obj }); + public object Unwrap(ExecutionContext context) => mUnwrap.Invoke(null, new object[] { context }); + public void WrapIn(object obj, ExecutionContext context) => mWrapIn.Invoke(null, new object[] { obj, context }); + public void UnwrapIn(ExecutionContext context, object obj) => mUnwrapIn.Invoke(null, new object[] { context, obj }); + } + #endregion } public static class Wrapper { - private static readonly NonGenericWrapper wrapper; + public static readonly Func Initor; + public static readonly bool HasInitor; + + //Быстрое оборачивание заполняет переменные по отступу + public static readonly Action QuickWrapper; + //Безопасное оборачивание заполняет переменные по имени + public static readonly Action SafeWrapper; + public static readonly Action Unwrapper; + + public static readonly Action WrapName; + public static readonly Action UnwrapName; + + public static readonly Dictionary ContextNames; + public static readonly string[] Names; + public static readonly int ContextSize; + static Wrapper() { - wrapper = NonGenericWrapper.GetWrapper(typeof(T)); + var d = Wrapper.InitWrapper(typeof(T)); + QuickWrapper = (Action)d.Item1; + SafeWrapper = (Action)d.Item2; + Unwrapper = (Action)d.Item3; + WrapName = (Action)d.Item4; + UnwrapName = (Action)d.Item5; + Initor = (Func)d.Item6; + HasInitor = Initor != null; + ContextNames = d.Item7; + Names = ContextNames.Keys.ToArray(); + ContextSize = ContextNames.Count; } - public static T Unwrap(ExecutionContext context) => (T)wrapper.Unwrap(context); - public static void UnwrapStatic(ExecutionContext context) => wrapper.UnwrapStatic(context); - public static ExecutionContext Wrap(T value) => wrapper.Wrap(value); - public static ExecutionContext WrapStatic() => wrapper.WrapStatic(); - - public static T SafeUnwrap(ExecutionContext context) => (T)wrapper.SafeUnwrap(context); - public static void SafeUnwrapStatic(ExecutionContext context) => wrapper.SafeUnwrapStatic(context); + public static ExecutionContext Wrap(T obj) + { + var lc = new LocalVariablesContainer(ContextSize, new Dictionary(ContextNames)); + var ret = new ExecutionContext(false, false, lc); + QuickWrapper(obj, ret, lc); + WrapName(obj, ret); + return ret; + } + public static ContextWrap WrapUnder(T obj, ExecutionContext context) + { + if (obj == null) return null; + if (Wrapper.HasRecast(obj.GetType())) throw new NotSupportedException("This type can't be converted into context"); + var lc = new LocalVariablesContainer(ContextSize, new Dictionary(ContextNames)); + var ret = new ExecutionContext(context, false, lc); + QuickWrapper(obj, ret, lc); + WrapName(obj, ret); + return ret.wrap; + } + public static T Unwrap(ExecutionContext context) + { + if (HasInitor) + { + var ret = Initor(context); + UnwrapName(context, ret); + Unwrapper(context.LocalVariables, ret); + return ret; + } + throw new NotSupportedException($"{typeof(T)} should have constructor"); + } + public static T UnwrapUnder(ContextWrap context) => Unwrap(context.Context); + public static void WrapIn(T obj, ExecutionContext context) + { + SafeWrapper(obj, context, context.LocalVariables); + WrapName(obj, context); + } + public static void UnwrapIn(ExecutionContext context, T obj) + { + Unwrapper(context.LocalVariables, obj); + UnwrapName(context, obj); + } } - - /// - /// Это свойство будет пропущено при разворачивании - /// - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited = false, AllowMultiple = false)] - public sealed class WrapperSkipAttribute : Attribute + public static class StaticWrapper { - public WrapperSkipAttribute() { } - } + public static readonly Action QuickWrapper; + public static readonly Action SafeWrapper; + public static readonly Action Unwrapper; - /// - /// В это свойство типа string будет вписано имя контекста - /// - [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)] - public sealed class WrapperContextNameAttribute : Attribute - { - public WrapperContextNameAttribute() { } + public static readonly Action WrapName; + public static readonly Action UnwrapName; + + public static readonly Dictionary ContextNames; + public static readonly string[] Names; + public static readonly int ContextSize; + + static StaticWrapper() + { + var d = Wrapper.InitStaticWrapper(typeof(T)); + QuickWrapper = (Action)d.Item1; + SafeWrapper = (Action)d.Item2; + Unwrapper = (Action)d.Item3; + WrapName = (Action)d.Item4; + UnwrapName = (Action)d.Item5; + ContextNames = d.Item6; + Names = ContextNames.Keys.ToArray(); + ContextSize = ContextNames.Count; + } + + public static ExecutionContext Wrap() + { + var lc = new LocalVariablesContainer(ContextSize, new Dictionary(ContextNames)); + var ret = new ExecutionContext(false, false, lc); + QuickWrapper(ret, lc); + WrapName(ret); + return ret; + } + public static void Unwrap(ExecutionContext context) + { + UnwrapName(context); + Unwrapper(context.LocalVariables); + } + public static void WrapIn(ExecutionContext context) + { + SafeWrapper(context, context.LocalVariables); + WrapName(context); + } + public static void UnwrapIn(ExecutionContext context) + { + Unwrapper(context.LocalVariables); + UnwrapName(context); + } } } diff --git a/SLThree/docs/SLThree_Notepad++_highlighting.xml b/SLThree/docs/SLThree_Notepad++_highlighting.xml index 2e5d5ad..0ae5584 100644 --- a/SLThree/docs/SLThree_Notepad++_highlighting.xml +++ b/SLThree/docs/SLThree_Notepad++_highlighting.xml @@ -24,7 +24,7 @@ - new as is true false null using context self this global upper super private recursive explicit + new as is true false null using context self this global upper super private recursive explicit static constructor abstract u8 i8 u16 i16 u32 i32 u64 i64 f64 f32 string bool any char list dict tuple while return break continue if else foreach in try catch finally match throw \n \t \r \\\ diff --git a/SLThree/docs/nugetreadme.md b/SLThree/docs/nugetreadme.md new file mode 100644 index 0000000..02954ab --- /dev/null +++ b/SLThree/docs/nugetreadme.md @@ -0,0 +1,50 @@ +# SLThree + +A simple and easily embedded programming language for the .NET platform. Dynamic typing, lightweight reflection, this language is convenient for describing data and behavior. + +For more information about syntax: [slt-lang.github.io](https://slt-lang.github.io) + +### Embedding +Code example for C#: + +```CSharp +using System; +using SLThree; +using SLThree.Embedding; + +namespace TestSLThree +{ + public class Program + { + public class TC + { + public int x, y; + public Method sum; + public object Sum() => sum.Invoke(x, y); + } + + public class TC2 + { + public Func sum2; + } + + static void Main(string[] args) + { + //Context.ReturnedValue method + Console.WriteLine("return 2 + 2 * 2;".RunScript().ReturnedValue); + + //Uwrapping method + var tc = "x = 3; y = 5; sum = (a, b) => a + b;".RunScript().Unwrap(); + Console.WriteLine(tc.Sum()); + + //[Experimental] Compilation: + var tc2 = "sum2 = (new using jit).opt(sum2 = (i32 x, i32 y): i32 => x + y, self).CreateDelegate(@System.Func);".RunScript().Unwrap(); + Console.WriteLine(tc2.sum2(35, 65)); + } + } +} + +``` + +### Download +[![stable](https://img.shields.io/badge/stable-0.8.0-00cc00)](https://github.com/AIexandrKotov/SLThree/releases/tag/0.8.0) \ No newline at end of file diff --git a/SLThree/docs/versions/0.8.0 b/SLThree/docs/versions/0.8.0 new file mode 100644 index 0000000..038966b --- /dev/null +++ b/SLThree/docs/versions/0.8.0 @@ -0,0 +1,39 @@ +------ 0.8.0 Binding&Naming Update ------ [21.06.24] +Language: + - New method definition syntax + `[modifs][Name][](args) {...}` + `[modifs][Name][](args) => value` + - You can now implements contexts with ":" in the following cases: + - New initializers: // [] - optional + `new T [Name][: Ancestors][{...}]` + - New context creators: + `context [Name][: Ancestors] {...}` + `new context [Name][: Ancestors]` + - Statement-like notation (without `;`) for expressions with body: + condition, match, context, new, methods + - Constructor method that creates new contexts + `context TBase { constructor = (f) => this.f = f; };` + `T1 = TBase(5); T2 = TBase(10);` + - The right side of the nested context initializer + assignations now always refers to the self context + `x = 1; context A { context B { x = x; }}` + - Parent keyword in constructed contexts + `T1.parent == TBase;` + - Abstract methods (withoud body) + - Static expression (will be executed only once) `static x` + - Condition statement is now expression + - Using statement is now expression + - Strong method binding + - Changed context syntax: + `new context Name: T {...}` -> `new T Name {...}` + `new context: T {...}` -> `new T {...}` + `new context Name: T` -> `new T Name` + `new context: T` -> `new T` + `new context Name {...}` -> `context Name {...}` + `new context {...}` -> `context {...}` +Optimization: + - Executing method performance has been increased by ~10% + - Wrappers refactoring, minumum 3x faster wrapping + minimum 20x faster unwrapping +Bugfixes: + - Fixed object invokation (#125) \ No newline at end of file diff --git a/SLThree/docs/versions/develop b/SLThree/docs/versions/develop new file mode 100644 index 0000000..3267eb6 --- /dev/null +++ b/SLThree/docs/versions/develop @@ -0,0 +1,4 @@ +------ Changes ------ [~.~.~] +Optimization: + - Wrappers refactoring, minumum 3x faster wrapping + minimum 20x faster unwrapping \ No newline at end of file diff --git a/SLThree/slthree.ico b/SLThree/slthree.ico deleted file mode 100644 index f31a739..0000000 Binary files a/SLThree/slthree.ico and /dev/null differ diff --git a/SLThree/syntax.peg b/SLThree/syntax.peg index fef4185..459e118 100644 --- a/SLThree/syntax.peg +++ b/SLThree/syntax.peg @@ -15,23 +15,20 @@ statement = return_statement / break_statement / continue_statement - / using_statement - / context_statement - / condition_statement / foreach_statement / while_statement / try_statement / throw_statement + / e:condition_statement { new ExpressionStatement(e, state) } + / e:match_expression { new ExpressionStatement(e, state) } + / e:context_expression { new ExpressionStatement(e, state) } + / e:block_instance_expression { new ExpressionStatement(e, state) } + / "static" _required_ e:method_definition_statement { new ExpressionStatement(ReorderStaticMethod(new StaticExpression(e, state)), state) } + / "static" _ e:method_definition_nswm { new ExpressionStatement(ReorderStaticMethod(new StaticExpression(e, state)), state) } + / e:method_definition_statement { new ExpressionStatement(e, state) } / expression_statement / block_statement - / ";" { new StatementList(new BaseStatement[0], state) } - -using_statement - = "using" _required_ u:using - using_alias:( _required_ "as" _required_ n:name {n})? - _ ";" { - new UsingStatement(GetOptional(using_alias), u, state) - } + / ";" { new EmptyStatement(state) } return_statement = "return" _ expr:expression _ ";" { new ReturnStatement(expr, state) } @@ -63,11 +60,6 @@ foreach_statement / "foreach" _ "(" _ ")" _ statement? { Panic(new SyntaxError("Empty loop head", state)) } / "foreach" _required_ cond:expression { Panic(new SyntaxError("Loop head must be in ( )", state)) } -condition_statement - = "if" _ "(" _ cond:expression _ ")" _ t:statement _ "else" _ f:statement { new ConditionStatement(cond, GetListStatement(t), GetListStatement(f), state) } - / "if" _ "(" _ cond:expression _ ")" _ t:statement { new ConditionStatement(cond, GetListStatement(t), new StatementList(new BaseStatement[0], state), state) } - / "if" _ "(" _ ")" _ statement? { Panic(new SyntaxError("Empty condition", state)) } - try_statement = "try" _ try_body:block_statement _ "catch" _ "(" _ catch_var:expression _ ")" _ catch_body:statement _ @@ -87,8 +79,13 @@ throw_statement = "throw" _required_ expr:expression _ ";" { new ThrowStatement(expr, state) } / "throw" _required_ expr:expression _ { Panic(new SyntaxError("Expected `;`", state)) } -context_statement - = "context" c:context { new ContextStatement(c, state) } +expression_as_return + = block_statement + / value:expression { new ReturnStatement(value, state) } + +expression_as_statement + = block_statement + / value:expression { new ExpressionStatement(value, state) } expression_statement = value:expression _ ";" { new ExpressionStatement(value, state) } @@ -99,8 +96,11 @@ expression binary_9 -memoize = left:keyword _ ("=" / "+=" / "-=" / "*=" / "/=" / "%=" / "&=" / "|=" / "^=") _ right:binary_9 { Panic(new SyntaxError("Keywords is not a valid name", state)) } - / method / left:binary_9 _ "|>" _ right:binary_7 { InjectFirst(left, right) } + / "static" _required_ left:expression { ReorderStatic(new StaticExpression(left, state)) } + / condition_expression + / match_expression + / method_definition_expression / "?" _ "=" _ right:binary_9 { new BinaryAssignUnknown(right, state) } / left:arg_name _ "=" _ right:binary_9 { new BinaryAssign(left, right, state) } / left:binary_7 _ "=" _ right:binary_9 { new BinaryAssign(left, right, state) } @@ -113,10 +113,6 @@ binary_9 -memoize / left:binary_7 _ "|=" _ right:binary_9 { new BinaryAssign(left, new BinaryBitOr(left, right, state), state) } / left:binary_7 _ "^=" _ right:binary_9 { new BinaryAssign(left, new BinaryBitXor(left, right, state), state) } / ternary_0 - -method - = generic_lambda - / lambda ternary_0 -memoize = cond:ternary_0 _ "?" _ t:expression _ ":" _ f:expression { new TernaryOperator(cond, t, f, state) } @@ -199,22 +195,44 @@ unary / "*" _ left:binary_min { new UnaryGetChooser(left, null, state) } / "@@" _ left:typename { new UnaryStaticReflection(left, state) } / "@" _ left:typename { new UnaryReflection(left, state) } - / match + / primary -match +using_expression + = "using" _required_ u:using + using_alias:( _required_ "as" _required_ name:primary {name})? { + new UsingExpression(GetOptional(using_alias), u, state) + } + +condition_statement + = expr:condition_expression _ ";" { expr } + / "if" _ "(" _ cond:expression _ ")" _ t:statement _ "else" _ f:statement { new ConditionExpression(cond, GetListStatement(t), GetListStatement(f), state) } + / condition_expression_1 + / "if" _ "(" _ cond:expression _ ")" _ t:block_statement { new ConditionExpression(cond, GetListStatement(t), new StatementList(new BaseStatement[0], state), state) } + / "if" _ "(" _ ")" _ block_statement? { Panic(new SyntaxError("Empty condition", state)) } + +condition_expression + = condition_expression_1 + / "if" _ "(" _ ")" _ statement? { Panic(new SyntaxError("Empty condition", state)) } + +condition_expression_1 + = "if" _ "(" _ cond:expression _ ")" _ t:expression_as_statement _ "else" _ f:expression_as_statement { new ConditionExpression(cond, GetListStatement(t), GetListStatement(f), state) } + +match_expression = "match" _ "(" _ expr:expression _ ")" _ "{" _ - matches:match_node<1,,";" _> + matches:match_node<1,,_> _ ";"? _ "}" { new MatchExpression(expr, matches, state) } - / primary match_node , BaseStatement>> = left:(>"(" _ ")" { null } / exprs:expression<1,,"," _> { exprs }) - _ "==>" _ right:( - - expr:expression { new ExpressionStatement(expr, state) } - / block_statement - ) { new ValueTuple, BaseStatement>(left, right) } + _ "==>" _ right:statement + { new ValueTuple, BaseStatement>(left, right) } + +withoutinvokation_primary -memoize + = left:withoutinvokation_primary _ "." _ "?" _ "[" _ args:expression<1,,"," _> _ "]" { new IndexExpression(left, args.ToArray(), true, state) } + / left:withoutinvokation_primary _ "."? _ "[" _ args:expression<1,,"," _> _ "]" { new IndexExpression(left, args.ToArray(), false, state) } + / left:withoutinvokation_primary _ conditional:"?"? _ "." _ right:onlyname_access { new MemberAccess(left, right, conditional.Count == 1, state) } + / onlyname_access primary -memoize = left:primary _ "." _ "?" _ "<" _ gen_args:typename<1,,"," _> _ ">" _ "(" _ args:expression<0,,"," _> _ ")" { new InvokeGenericExpression(left, gen_args.ToArray(), args.ToArray(), true, state) } @@ -227,10 +245,13 @@ primary -memoize / "(" _ x:expression _ ")" { x.RaisePriority() } / "<" _ t:typename<2,2,"," _> _ ">" _ "{" _ etrs:dictionary_entry <0,,"," _> _ ("," _ )? "}" { new CreatorDictionary(etrs.ToArray(), t.ToArray(), state) } / "{" _ etrs:dictionary_entry <0,,"," _> _ ("," _ )? "}" { new CreatorDictionary(etrs.ToArray(), state) } - / "new" _required_ "context" c: context { c } - / "new" _required_ "using" _required_ u: using { u } - / "new" _required_ right:typename _ "(" _ args:expression<0,,"," _> _ ")" { new NewExpression(right, args.ToArray(), state) } / "new" _required_ tp:typename _ "[" _ size:expression _ "]" { new CreatorNewArray(tp, size, state) } + // "new" _required_ "context" c: context { c } + / "new" _required_ "using" _required_ u: using { u } + / using_expression + / new_context_expression + / context_expression + / instance_expression / "(" _ args:req_arg_name<1,,"," _> _ ("," _ )? ")" { new CreatorTuple(args.ToArray(), state) } / "(" _ args:expression<1,,"," _> _ ("," _ )? ")" { new CreatorTuple(args.ToArray(), state) } / "<" _ t:typename _ ">" _ "-[" _ args:expression<0,,"," _> _ ("," _ )? "]" { new CreatorArray(args.ToArray(), t, state) } @@ -241,6 +262,206 @@ primary -memoize / "[" _ x:expression { Panic(new SyntaxError("Unclosed brackets", state)) } / "(" _ x:expression { Panic(new SyntaxError("Unclosed brackets", state)) } +new_context_expression +//--------CREATOR--CONTEXT------------------------------------------------- +// new context Name: TBase + = "new" _required_ "context" _required_ name:primary _ ":" _ ancestors:primary<1,,"," _> { + new CreatorContext(name, ancestors.ToArray(), state) + } +//--------CREATOR--CONTEXT------------------------------------------------- +// new context Name + / "new" _required_ "context" _required_ name:primary { + new CreatorContext(name, state) + } +//--------CREATOR--CONTEXT------------------------------------------------- +// new context: TBase + / "new" _required_ "context" _ ":" _ ancestors:primary<1,,"," _> { + new CreatorContext(ancestors.ToArray(), state) + } +//--------CREATOR--CONTEXT------------------------------------------------- +// new context + / "new" _required_ "context" { + new CreatorContext(state) + } + +context_expression +//--------CREATOR--CONTEXT------------------------------------------------- +// context Name: TBase {} + = "context" _required_ name:primary _ ":" _ ancestors:primary<1,,"," _> + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + new CreatorContext(name, ancestors.ToArray(), body, state) + } +//--------CREATOR--CONTEXT------------------------------------------------- +// context Name {} + / "context" _required_ name:primary + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + new CreatorContext(name, body, state) + } +//--------CREATOR--CONTEXT------------------------------------------------- +// context: TBase {} + / "context" _ ":" _ ancestors:primary<1,,"," _> + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + new CreatorContext(ancestors.ToArray(), body, state) + } +//--------CREATOR--CONTEXT------------------------------------------------- +// context {} + / "context" + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + new CreatorContext(body, state) + } + +instance_expression +//--------CREATOR--INSTANCE------------------------------------------------ +// new T(args) Name: TBase {}; + = "new" _required_ t:typename _ "(" _ args:expression<0,,"," _> _ ")" _ name:primary + _ ":" _ ancestors:primary<1,,"," _> + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.NamedCaseTypeArgsBodyInheritance(t, name, args.ToArray(), ancestors.ToArray(), body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T(args) Name: TBase; + / "new" _required_ t:typename _ "(" _ args:expression<0,,"," _> _ ")" _ name:primary + _ ":" _ ancestors:primary<1,,"," _> { + CreatorInstance.NamedCaseTypeArgsInheritance(t, name, args.ToArray(), ancestors.ToArray(), state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T(args): TBase {}; + / "new" _required_ t:typename _ "(" _ args:expression<0,,"," _> _ ")" + _ ":" _ ancestors:primary<1,,"," _> + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.CaseTypeArgsBodyInheritance(t, args.ToArray(), ancestors.ToArray(), body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T(args): TBase; + / "new" _required_ t:typename _ "(" _ args:expression<0,,"," _> _ ")" + _ ":" _ ancestors:primary<1,,"," _> { + CreatorInstance.CaseTypeArgsInheritance(t, args.ToArray(), ancestors.ToArray(), state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T Name: TBase {}; + / "new" _required_ t:typename _ name:primary + _ ":" _ ancestors:primary<1,,"," _> + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.NamedCaseTypeBodyInheritance(t, name, ancestors.ToArray(), body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T Name: TBase; + / "new" _required_ t:typename _ name:primary + _ ":" _ ancestors:primary<1,,"," _> { + CreatorInstance.NamedCaseTypeInheritance(t, name, ancestors.ToArray(), state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T: TBase {}; + / "new" _required_ t:typename + _ ":" _ ancestors:primary<1,,"," _> + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.CaseTypeBodyInheritance(t, ancestors.ToArray(), body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T: TBase; + / "new" _required_ t:typename + _ ":" _ ancestors:primary<1,,"," _> { + CreatorInstance.CaseTypeInheritance(t, ancestors.ToArray(), state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T(args) Name {}; + / "new" _required_ t:typename _ "(" _ args:expression<0,,"," _> _ ")" _ name:primary + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.NamedCaseTypeArgsBody(t, name, args.ToArray(), body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T(args) Name; + / "new" _required_ t:typename _ "(" _ args:expression<0,,"," _> _ ")" _ name:primary { + CreatorInstance.NamedCaseTypeArgs(t, name, args.ToArray(), state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T(args) {}; + / "new" _required_ t:typename _ "(" _ args:expression<0,,"," _> _ ")" + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.CaseTypeArgsBody(t, args.ToArray(), body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T(args); + / "new" _required_ t:typename _ "(" _ args:expression<0,,"," _> _ ")" { + CreatorInstance.CaseTypeArgs(t, args.ToArray(), state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T Name {}; + / "new" _required_ t:typename _ name:primary + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.NamedCaseTypeBody(t, name, body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T Name; + / "new" _required_ t:typename _ name:primary { + CreatorInstance.NamedCaseType(t, name, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T {}; + / "new" _required_ t:typename + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.CaseTypeBody(t, body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T; + / "new" _required_ t:typename { + CreatorInstance.CaseType(t, state) + } + +block_instance_expression +//--------CREATOR--INSTANCE------------------------------------------------ +// new T(args) Name: TBase {}; + = "new" _required_ t:typename _ "(" _ args:expression<0,,"," _> _ ")" _ name:primary + _ ":" _ ancestors:primary<1,,"," _> + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.NamedCaseTypeArgsBodyInheritance(t, name, args.ToArray(), ancestors.ToArray(), body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T(args): TBase {}; + / "new" _required_ t:typename _ "(" _ args:expression<0,,"," _> _ ")" + _ ":" _ ancestors:primary<1,,"," _> + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.CaseTypeArgsBodyInheritance(t, args.ToArray(), ancestors.ToArray(), body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T Name: TBase {}; + / "new" _required_ t:typename _ name:primary + _ ":" _ ancestors:primary<1,,"," _> + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.NamedCaseTypeBodyInheritance(t, name, ancestors.ToArray(), body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T: TBase {}; + / "new" _required_ t:typename + _ ":" _ ancestors:primary<1,,"," _> + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.CaseTypeBodyInheritance(t, ancestors.ToArray(), body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T(args) Name {}; + / "new" _required_ t:typename _ "(" _ args:expression<0,,"," _> _ ")" _ name:primary + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.NamedCaseTypeArgsBody(t, name, args.ToArray(), body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T(args) {}; + / "new" _required_ t:typename _ "(" _ args:expression<0,,"," _> _ ")" + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.CaseTypeArgsBody(t, args.ToArray(), body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T Name {}; + / "new" _required_ t:typename _ name:primary + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.NamedCaseTypeBody(t, name, body, state) + } +//--------CREATOR--INSTANCE------------------------------------------------ +// new T {}; + / "new" _required_ t:typename + _ body:( _ st:block_statement { new CreatorContextBody(st.Statements, st.SourceContext) }) { + CreatorInstance.CaseTypeBody(t, body, state) + } + dictionary_entry = left:expression _ ":" _ right:expression { new CreatorDictionary.Entry(left, right, state) } @@ -250,62 +471,92 @@ access_right -memoize / right:access_right { right } / right:name { right } +onlyname_access -memoize + = left:special _ conditional:"?"? _ "." _ right:onlyname_access { new MemberAccess(left, right, conditional.Count == 1, state) } + / right:special { right } + using = t_name:typename { new CreatorUsing(t_name, state) } -context - = context_name:( _required_ n:name {n})? - context_type:( _ ":" _ t:typename {t})? - context_body:( _ st:block_statement {st})? { - new CreatorContext( - GetOptional(context_name), - GetOptional(context_type), - GetOptional(context_body)?.Statements.ToArray().ConvertAll(x => CheckOnContextStatements(x)) ?? new BaseStatement[0], - state) - } - -generic_lambda - = left:( - , NameExpression[], TypenameExpression, NameExpression[]>> - mods:(> mods_i:method_modificator<1,,_required_> _required_ { mods_i })? - _ "<" _ generic_args:name<1,,"," _> _ ">" _ - args:( - > "(" _ args_i:arg_name<0,,"," _> _ ")" { args_i } - / a:arg_name { new NameExpression[1] { a } } - ) - ret:( _ ":" _ t:typename {t})? { - new ValueTuple, NameExpression[], TypenameExpression, NameExpression[]>(GetOptional(mods) ?? new string[0], args.ToArray(), GetOptional(ret), generic_args.ToArray()) - } - ) _ "=>" _ right:( - - expr:expression { GetListStatement(new ReturnStatement(expr, state)) } - / block_statement - ) { - new LambdaGenericExpression(new InvokeExpression(null, left.Item2, state), right, left.Item3, left.Item1, left.Item4, state) - } - -lambda - = left:( - , NameExpression[], TypenameExpression>> - mods:(> mods_i:method_modificator<1,,_required_> _required_ { mods_i })? - args:( - > "(" _ args_i:arg_name<0,,"," _> _ ")" { args_i } - / a:arg_name { new NameExpression[1] { a } } - ) - ret:( _ ":" _ t:typename {t})? { - new ValueTuple, NameExpression[], TypenameExpression>(GetOptional(mods) ?? new string[0], args.ToArray(), GetOptional(ret)) - } - ) _ "=>" _ right:( - - expr:expression { GetListStatement(new ReturnStatement(expr, state)) } - / block_statement - ) { - new LambdaExpression(new InvokeExpression(null, left.Item2, state), right, left.Item3, left.Item1, state) - } +method_definition_expression + = method_definition_statement1 + / mods_name:method_mods_name? + generics:method_generic_part? + "(" _ args:arg_name<0,,"," _> _ ")" + ret:( _ ":" _ t:typename {t})? _ "=>" _ value:expression + { + new FunctionDefinition(GetOptional(mods_name)?.Item1 ?? new string[0], GetOptional(mods_name)?.Item2, GetOptional(generics)?.ToArray() ?? new NameExpression[0], args.ToArray(), GetListStatement(new ReturnStatement(value, state)), GetOptional(ret), state) + } + / method_definition_statement2 + / method_definition_statement3 + / generics:method_generic_part? + arg:arg_name + ret:( _ ":" _ t:typename {t})? _ "=>" _ value:expression + { + new FunctionDefinition(new string[0], null, GetOptional(generics)?.ToArray() ?? new NameExpression[0], new NameExpression[1] {arg}, GetListStatement(new ReturnStatement(value, state)), GetOptional(ret), state) + } + / abstract_method_expression +method_definition_statement + = method_definition_statement1 + / method_definition_statement2 + / method_definition_statement3 + / abstract_method_statement + +abstract_method_statement = func:abstract_method_expression _ ";" { func } +abstract_method_expression + = "abstract" _required_ + name:withoutinvokation_primary _ + generics:method_generic_part? + "(" _ args:arg_name<0,,"," _> _ ")" + ret:( _ ":" _ t:typename {t})? + { + new FunctionDefinition(new string[1] { "abstract" }, name, GetOptional(generics)?.ToArray() ?? new NameExpression[0], args.ToArray(), null, GetOptional(ret), state) + } +method_definition_statement1 + = mods_name:method_mods_name? + generics:method_generic_part? + "(" _ args:arg_name<0,,"," _> _ ")" + ret:( _ ":" _ t:typename {t})? _ body:block_statement { + new FunctionDefinition(GetOptional(mods_name)?.Item1 ?? new string[0], GetOptional(mods_name)?.Item2, GetOptional(generics)?.ToArray() ?? new NameExpression[0], args.ToArray(), body, GetOptional(ret), state) + } +method_definition_statement2 + = mods_name:method_mods_name? + generics:method_generic_part? + "(" _ args:arg_name<0,,"," _> _ ")" + ret:( _ ":" _ t:typename {t})? _ "=>" _ body:block_statement + { + new FunctionDefinition(GetOptional(mods_name)?.Item1 ?? new string[0], GetOptional(mods_name)?.Item2, GetOptional(generics)?.ToArray() ?? new NameExpression[0], args.ToArray(), body, GetOptional(ret), state) + } +method_definition_statement3 + = generics:method_generic_part? + arg:arg_name + ret:( _ ":" _ t:typename {t})? _ "=>" _ body:block_statement + { + new FunctionDefinition(new string[0], null, GetOptional(generics)?.ToArray() ?? new NameExpression[0], new NameExpression[1] {arg}, GetListStatement(body), GetOptional(ret), state) + } + + +method_definition_nswm + = generics:method_generic_part? + "(" _ args:arg_name<0,,"," _> _ ")" + ret:( _ ":" _ t:typename {t})? _ + body:block_statement { + new FunctionDefinition(new string[0], null, GetOptional(generics)?.ToArray() ?? new NameExpression[0], args.ToArray(), body, GetOptional(ret), state) + } + +method_generic_part > + = "<" _ generic_args:name<1,,"," _> _ ">" _ { generic_args } + +method_mods_name > + = mods:method_modificator<1,,_required_> _required_ name:withoutinvokation_primary _ { new Tuple(mods.ToArray(), name) } + / mods:method_modificator<1,,_required_> _ { new Tuple(mods.ToArray(), null) } + / name:withoutinvokation_primary _ { new Tuple(new string[0], name) } method_modificator - = "recursive" + = "abstract" + / "recursive" / "explicit" + / "native" typename = t_node:typename_node _ "<" _ t_list:typename<1,,"," _> _ ">" { new TypenameExpression(t_node, t_list.ToArray(), state) } @@ -394,7 +645,7 @@ num_literal / i64:([0-9_]+ ("i64")?) { new LongLiteral (long.Parse (i64.Replace("i64", "").Replace("_", ""), CultureInfo.InvariantCulture), i64, state) } keyword - = "while" / "if" / "else" / "foreach" / "return" / "break" / "continue" + = "while" / "if" / "else" / "foreach" / "return" / "break" / "continue" / "static" / "using" / "context" / "new" / "match" / "self" / "upper" / "this" / "global" / "super" / "private" / "try" / "catch" / "finally" / "throw" diff --git a/SLThree/sys/console.cs b/SLThree/sys/console.cs index bba3cbe..1d49679 100644 --- a/SLThree/sys/console.cs +++ b/SLThree/sys/console.cs @@ -1,11 +1,13 @@ -using System; +using SLThree.Extensions; +using System; +using System.Linq; namespace SLThree.sys { #pragma warning disable IDE1006 // Стили именования public static class console { - public static ContextWrap color = new ContextWrap(Wrapper.WrapStatic()); + public static ContextWrap color = typeof(ConsoleColor).StaticWrap().wrap; public static string readln() => Console.ReadLine(); public static void write(object o) => Console.Write(o); public static void writeln() => Console.WriteLine(); diff --git a/SLThree/sys/jit.cs b/SLThree/sys/jit.cs index 1cd65d4..37a7a00 100644 --- a/SLThree/sys/jit.cs +++ b/SLThree/sys/jit.cs @@ -31,9 +31,9 @@ static jit() #endif } - public static List collect_vars(Method method, ExecutionContext context) + public static List collect_vars(Method method, ExecutionContext context) { - return JIT.NameCollector.Collect(method, context).Item1; + return Native.NameCollector.Collect(method, context).Item1; } public static MethodInfo opt(Method method, ContextWrap context) @@ -47,7 +47,7 @@ public static MethodInfo opt(Method method, ContextWrap context) try { mb = dt.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.Static, rettype, ptypes); - var ng = new JIT.NETGenerator(method, context.Context, mb, mb.GetILGenerator()); + var ng = new Native.NETGenerator(method, context.Context, mb, mb.GetILGenerator()); ng.Visit(method); } catch (Exception e) diff --git a/SLThree/sys/language.cs b/SLThree/sys/language.cs new file mode 100644 index 0000000..598bdf8 --- /dev/null +++ b/SLThree/sys/language.cs @@ -0,0 +1,88 @@ +using SLThree.Native; +using SLThree.Visitors; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SLThree.sys +{ +#pragma warning disable IDE1006 // Стили именования + public static class language + { + public static Assembly SLThree = typeof(language).Assembly; + public static IEnumerable GetAncestors(Type type) + { + type = type.BaseType; + while (type != null) + { + yield return type; + type = type.BaseType; + } + } + + public static void show() + { + var types = SLThree.GetTypes(); + var statements = types.Where(x => GetAncestors(x).Contains(typeof(BaseStatement))); + var expressions = types.Where(x => GetAncestors(x).Contains(typeof(BaseExpression))); + expressions = expressions.Where(x => !GetAncestors(x).Contains(typeof(Literal))); + expressions = expressions.Where(x => !GetAncestors(x).Contains(typeof(Special))); + expressions = expressions.Where(x => !GetAncestors(x).Contains(typeof(BinaryOperator))); + expressions = expressions.Where(x => !GetAncestors(x).Contains(typeof(UnaryOperator))); + + //name, AV define, TV define, XMLV define + var infos = new List<(string, bool, bool, bool, bool, bool)>(); + foreach (var statement in statements) + { + var AVdefine = typeof(IStatementVisitor).GetMethods().Any(x => x.Name == "VisitStatement" && x.GetParameters()[0].ParameterType == statement); + var TVdefine = typeof(TreeViewer).GetMethods().Any(x => x.Name == "VisitStatement" && x.GetParameters()[0].ParameterType == statement && x.DeclaringType != typeof(AbstractVisitor)); + var XMLdefine = typeof(XmlViewer).GetMethods().Any(x => x.Name == "VisitStatement" && x.GetParameters()[0].ParameterType == statement && x.DeclaringType != typeof(AbstractVisitor)); + var NETdefine = typeof(NETGenerator).GetMethods().Any(x => x.Name == "VisitStatement" && x.GetParameters()[0].ParameterType == statement && x.DeclaringType != typeof(AbstractVisitor)); + infos.Add((statement.Name, false, AVdefine, TVdefine, XMLdefine, NETdefine)); + } + foreach (var expression in expressions) + { + var AVdefine = typeof(IExpressionVisitor).GetMethods().Any(x => x.Name == "VisitExpression" && x.GetParameters()[0].ParameterType == expression); + var TVdefine = typeof(TreeViewer).GetMethods().Any(x => x.Name == "VisitExpression" && x.GetParameters()[0].ParameterType == expression && x.DeclaringType != typeof(AbstractVisitor)); + var XMLdefine = typeof(XmlViewer).GetMethods().Any(x => x.Name == "VisitExpression" && x.GetParameters()[0].ParameterType == expression && x.DeclaringType != typeof(AbstractVisitor)); + var NETdefine = typeof(NETGenerator).GetMethods().Any(x => x.Name == "VisitExpression" && x.GetParameters()[0].ParameterType == expression && x.DeclaringType != typeof(AbstractVisitor)); + infos.Add((expression.Name, true, AVdefine, TVdefine, XMLdefine, NETdefine)); + } + infos.Sort((x, y) => (string.Compare(x.Item1, y.Item1))); + var nameident = infos.Max(x => x.Item1.Length); + var defs = new Dictionary { { false, "not" }, { true, "defined" } }; + var colors = new Dictionary { { false, ConsoleColor.Red }, { true, ConsoleColor.Green } }; + Console.ResetColor(); + Console.WriteLine($"{"Element name".PadRight(nameident)} │ AVdef │ TVdef │ XMLdef │ NETdef "); + foreach (var x in infos) + { + Console.ForegroundColor = x.Item2 ? ConsoleColor.Cyan : ConsoleColor.Magenta; + Console.Write(x.Item1.PadRight(nameident)); + Console.ResetColor(); + Console.Write(" │ "); + Console.ForegroundColor = colors[x.Item3]; + Console.Write(defs[x.Item3].PadRight(7)); + Console.ResetColor(); + Console.Write(" │ "); + Console.ForegroundColor = colors[x.Item4]; + Console.Write(defs[x.Item4].PadRight(7)); + Console.ResetColor(); + Console.Write(" │ "); + Console.ForegroundColor = colors[x.Item5]; + Console.Write(defs[x.Item5].PadRight(7)); + Console.ResetColor(); + Console.Write(" │ "); + Console.ForegroundColor = colors[x.Item6]; + Console.Write(defs[x.Item6].PadRight(7)); + Console.ResetColor(); + Console.WriteLine(); + } + + Console.WriteLine(); + } + } +#pragma warning restore IDE1006 // Стили именования +} diff --git a/SLThree/sys/slt.cs b/SLThree/sys/slt.cs index 40f8227..50a0a3a 100644 --- a/SLThree/sys/slt.cs +++ b/SLThree/sys/slt.cs @@ -15,6 +15,8 @@ public static class slt public static object eval(string s) => Parser.This.EvalExpression(s); public static object eval(ContextWrap context, string s) => Parser.This.EvalExpression(s, context.Context); + public static object clone(ICloneable clone) => clone.Clone(); + public static string repr(object o) => TreeViewer.GetView(o); public static string context_repr(ContextWrap wrap) => wrap.ToDetailedString(1, new List()); public static string xml_repr(object o) => XmlViewer.GetView(o); @@ -23,6 +25,13 @@ public static class slt public static Method make_generic(GenericMethod method) => method.MakeGenericMethod(new Type[] { typeof(T1) }); public static Method make_generic(GenericMethod method) => method.MakeGenericMethod(new Type[] { typeof(T1), typeof(T2) }); public static Method make_generic(GenericMethod method) => method.MakeGenericMethod(new Type[] { typeof(T1), typeof(T2), typeof(T3) }); + internal static bool is_abstract(StatementList statement) + { + return statement.Statements.Length > 0 + && statement.Statements[0] is ThrowStatement @throw + && @throw.ThrowExpression is StaticExpression expression + && expression.IsArtificial && expression.Object is AbstractInvokation; + } public static readonly List registred; static slt() diff --git a/TestSuite/Program.cs b/TestSuite/Program.cs index bd8bba8..4672ca5 100644 --- a/TestSuite/Program.cs +++ b/TestSuite/Program.cs @@ -1,5 +1,6 @@ using SLThree; using SLThree.Extensions; +using SLThree.sys; using System; using System.Collections.Generic; using System.IO; @@ -11,6 +12,7 @@ public static class Program { public static List ErrorLog = new List(); + private static bool global_assert = true; private static bool current_assert = true; private static int current_assert_id = 1; public static void Log(object o) @@ -51,6 +53,53 @@ public static void Assert(ContextWrap context, BaseExpression expression) ErrorLog.Add($"FAILED {expression} as {expression.SourceContext} ===> {e}"); } } + public static void AssertThrow(ContextWrap context, BaseExpression sc, Type type, string val) + { + try + { + Console.ForegroundColor = ConsoleColor.White; + Console.Write(""); + Console.Write($"{current_assert_id++,6} "); + var expression = slt.parse_expr(val); + expression.GetValue(context.Context); + current_assert = false; + Console.ForegroundColor = ConsoleColor.Red; + Console.Write($" FAILED "); + Console.ForegroundColor = ConsoleColor.Red; + Console.Write($" [NO]"); + Console.ForegroundColor = ConsoleColor.Magenta; + Console.Write($" at {expression.SourceContext.ToStringWithoutFile()} "); + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine($"{expression}"); + ErrorLog.Add($"FAILED {expression} as {expression.SourceContext} ===> {type} not thrown"); + } + catch (Exception e) + { + if (SLTHelpers.IsType(type, e.GetType())) + { + Console.ForegroundColor = ConsoleColor.Green; + Console.Write($"SUCCESS "); + Console.ForegroundColor = ConsoleColor.Green; + Console.Write($" [{type.Name}]"); + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine($" {val} "); + Console.ForegroundColor = ConsoleColor.White; + } + else + { + current_assert = false; + Console.ForegroundColor = ConsoleColor.Red; + Console.Write($" FAILED "); + Console.ForegroundColor = ConsoleColor.Red; + Console.Write($" [{e.GetType().Name}]"); + Console.ForegroundColor = ConsoleColor.Magenta; + Console.Write($" at {sc.SourceContext.ToStringWithoutFile()} "); + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine($"{val}"); + ErrorLog.Add($"FAILED {val} as {sc.SourceContext} ===> another exception thrown\n{e}"); + } + } + } public static bool ParseTest(string filename) { @@ -61,11 +110,13 @@ public static bool ParseTest(string filename) } catch (SLTException e) { + global_assert = false; ErrorLog.Add(e.ToString()); return false; } catch (Exception e) { + global_assert = false; ErrorLog.Add($"with {filename}: "); ErrorLog.Add(e.ToString()); return false; @@ -80,6 +131,7 @@ public static bool ExecTest(string filename) { var context = new ExecutionContext(); context.LocalVariables.SetValue("ASSERT", ((Action)Assert).Method); + context.LocalVariables.SetValue("ASSERT_THROW", ((Action)AssertThrow).Method); context.LocalVariables.SetValue("PATH", ((Func)GetPath).Method); context.LocalVariables.SetValue("LOG", ((Action)Log).Method); @@ -88,11 +140,13 @@ public static bool ExecTest(string filename) } catch (SLTException e) { + global_assert = false; ErrorLog.Add(e.ToString()); return false; } catch (Exception e) { + global_assert = false; ErrorLog.Add($"with {filename}: "); ErrorLog.Add(e.ToString()); return false; @@ -165,8 +219,7 @@ public static int Main(string[] args) ParsingTests(); ExecutingTests(); File.WriteAllLines("testsuite.log", ErrorLog.ToArray()); - if (ErrorLog.Count > 0) return 1; - else return 0; + return global_assert ? 0 : 1; } } } diff --git a/examples/char_based_interface.slt b/examples/char_based_interface.slt index 3f2df76..6ac9601 100644 --- a/examples/char_based_interface.slt +++ b/examples/char_based_interface.slt @@ -2,39 +2,31 @@ out_help = () => { using console; console.writeln("0 - Выйти"); console.writeln("h - Вывести ещё раз"); - console.writeln("? - Вывести применённый оператор к a и b"); + console.writeln("+ - Вывести a + b"); + console.writeln("* - Вывести a * b"); + console.writeln("% - Вывести a % b"); console.writeln($"a - Заполнить a (Сейчас: {global.a})"); console.writeln($"b - Заполнить b (Сейчас: {global.b})"); }; read = str => { - using slt; using console; console.write(str); - try { - return slt.eval(console.readln()); - } - catch (err) return err.GetType().Name; + return console.readln().Trim() as i64; }; using console; -using slt; -(global.a, global.b) = (228, 666); +global.a = global.b = 2; out_help(); -while (true) -{ +while (true) { console.write(">>> "); input = console.readln().Trim(); - switch (input) - { - case "0": - break; - case "h": - out_help(); - case "a": - global.a = read("Введите a: "); - case "b": - global.b = read("Введите b: "); - } - if (input.Length == 1 && "+-/*".Contains(input)) - console.writeln($"Вывод: {slt.eval($"global.a {input} global.b")}"); + match (input) { + "0" ==> break; + "h" ==> out_help(); + "+" ==> console.writeln($"Вывод: {global.a + global.b}"); + "*" ==> console.writeln($"Вывод: {global.a * global.b}"); + "%" ==> console.writeln($"Вывод: {global.a % global.b}"); + "a" ==> global.a = read("Введите a: "); + "b" ==> global.b = read("Введите b: "); + }; } \ No newline at end of file diff --git a/examples/get_system_types.slt b/examples/get_system_types.slt index 99a3215..5bf8099 100644 --- a/examples/get_system_types.slt +++ b/examples/get_system_types.slt @@ -1,3 +1,6 @@ -using slt; -using linq; -sly.sys_types.Keys |> linq.jts("\n"); \ No newline at end of file +(using linq).jts( + linq.to_enumerable( + (using slt).sys_types + ), + "\n" +); \ No newline at end of file diff --git a/examples/recursive_fibonacci.slt b/examples/recursive_fibonacci.slt index a977e2b..1fd393f 100644 --- a/examples/recursive_fibonacci.slt +++ b/examples/recursive_fibonacci.slt @@ -1,3 +1,3 @@ -fib = (new context { fib = recursive (n) => (n < 2) ? n : this.fib(n - 2) + this.fib(n - 1); }.fib); +fib = (context { fib = recursive (n) => (n < 2) ? n : this.fib(n - 2) + this.fib(n - 1); }.fib); using linq; 1..20 |> linq.select(fib) |> linq.jts(); \ No newline at end of file diff --git a/slt/.msbump b/slt/.msbump deleted file mode 100644 index b6e665a..0000000 --- a/slt/.msbump +++ /dev/null @@ -1,3 +0,0 @@ -{ - BumpRevision: true -} \ No newline at end of file diff --git a/slt/Program.cs b/slt/Program.cs index e4bfbd9..0e20210 100644 --- a/slt/Program.cs +++ b/slt/Program.cs @@ -55,7 +55,7 @@ private static Dictionary EncodingAliases } #endif ; - internal static Assembly SLThreeAssembly; + internal static Assembly SLThreeAssembly, REPLAssembly; private static SLTVersion.Reflected SLThreeVersion; private static REPLVersion.Reflected SLTREPLVersion; private static SortedDictionary SLThreeVersions; @@ -68,6 +68,7 @@ private static bool TryGetArgument(string arg, out string value, Func no private static void InitSLThreeAssemblyInfo() { SLThreeAssembly = Assembly.GetAssembly(typeof(SLTVersion)); + REPLAssembly = Assembly.GetAssembly(typeof(Program)); SLThreeVersion = new SLTVersion.Reflected(); SLTREPLVersion = new REPLVersion.Reflected(); var sltver = SLThreeAssembly.GetType("SLTVersion"); @@ -125,25 +126,17 @@ public static string GetArgument(this string[] arguments, string arg, Dictionary public static void OutCurrentVersion() { Console.ForegroundColor = ConsoleColor.Green; - Console.Write(REPLVersion.Name); + Console.Write("REPL"); Console.ForegroundColor = ConsoleColor.White; - Console.Write($" {SLTREPLVersion.VersionWithoutRevision} "); - Console.ResetColor(); - Console.Write("rev "); - Console.ForegroundColor = ConsoleColor.White; - Console.WriteLine($"{SLTREPLVersion.Revision}"); + Console.WriteLine($" {GetVersionOfREPL()} "); Console.ResetColor(); Console.ForegroundColor = ConsoleColor.Green; Console.Write(SLTVersion.Name); Console.ForegroundColor = ConsoleColor.White; - Console.Write($" {SLThreeVersion.VersionWithoutRevision} "); + Console.Write($" {GetVersionOfLanguage()} "); Console.ForegroundColor = ConsoleColor.Yellow; - Console.Write($"{SLTVersion.Edition} "); - Console.ResetColor(); - Console.Write("rev "); - Console.ForegroundColor = ConsoleColor.White; - Console.WriteLine($"{SLThreeVersion.Revision}"); + Console.WriteLine($"{SLTVersion.Edition} "); Console.ResetColor(); } @@ -795,9 +788,9 @@ string[] Splitter(string str) if (onlynull) { - var old = REPLContext.LocalVariables.NamedIdenificators.Count; + var old = REPLContext.LocalVariables.NamedIdentificators.Count; REPLContext.LocalVariables.ClearNulls(); - var @new = REPLContext.LocalVariables.NamedIdenificators.Count; + var @new = REPLContext.LocalVariables.NamedIdentificators.Count; OutAsWarning($"{old - @new} nulls deleted from context"); } else @@ -860,13 +853,28 @@ public static void REPLCommand(string command) } #endregion + private static string VersionGetted = null; + private static string REPLVersionGetted = null; + private static string GetVersionOf(Assembly assembly, ref string getted) + { + if (string.IsNullOrEmpty(getted)) + { + var fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location).ProductVersion; + var index = fileVersionInfo.IndexOf('+'); + getted = index != -1 ? fileVersionInfo.Substring(0, index) : fileVersionInfo; + } + return getted; + } + private static string GetVersionOfLanguage() => GetVersionOf(SLThreeAssembly, ref VersionGetted); + private static string GetVersionOfREPL() => GetVersionOf(REPLAssembly, ref REPLVersionGetted); + public static void REPLShortVersion() { Console.ForegroundColor = ConsoleColor.Green; - Console.Write("SLThree REPL "); + Console.Write("SLThree "); Console.ResetColor(); Console.ForegroundColor = ConsoleColor.White; - Console.Write($"{SLTREPLVersion.VersionWithoutRevision}"); + Console.Write($"{GetVersionOfLanguage()}"); Console.ResetColor(); Console.Write(" | "); Console.ForegroundColor = ConsoleColor.Cyan; @@ -949,7 +957,9 @@ void cancelKeyPress(object o, ConsoleCancelEventArgs e) Console.Write("... " + new string(' ', REPLSubparser.Tabs * 4)); try { - var state = REPLSubparser.Parse(Console.ReadLine()); + var rdl = Console.ReadLine(); + var state = REPLSubparser.Parse(rdl); + if (rdl == null) Console.WriteLine(); if (state == Subparser.SubparserState.WaitingText) continue; } catch (Exception e) diff --git a/slt/Subparser.cs b/slt/Subparser.cs index 86633e4..6876c0f 100644 --- a/slt/Subparser.cs +++ b/slt/Subparser.cs @@ -107,6 +107,11 @@ public SubparserState ParseNew(string s) public SubparserState Parse(string s) { + if (s == null) + { + Clear(); + return SubparserState.Ready; + } InternalParse(s); State = Brackets.Count == 0 ? SubparserState.Ready : SubparserState.WaitingText; return State; diff --git a/slt/docs/versions/develop b/slt/docs/versions/develop new file mode 100644 index 0000000..be587a1 --- /dev/null +++ b/slt/docs/versions/develop @@ -0,0 +1 @@ +------ Changes ------ [~.~.~] \ No newline at end of file diff --git a/slt/slt.csproj b/slt/slt.csproj index 017f6f1..56dde44 100644 --- a/slt/slt.csproj +++ b/slt/slt.csproj @@ -6,7 +6,7 @@ net471;net6.0;net7.0;net8.0 disable disable - 2.0.0.700 + 0.0.0-alpha ..\bin slthree.ico AnyCPU @@ -36,10 +36,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/test/executing/0.8/context.slt b/test/executing/0.8/context.slt new file mode 100644 index 0000000..7b81cfb --- /dev/null +++ b/test/executing/0.8/context.slt @@ -0,0 +1,29 @@ +ISDNAME(context c) => c.unwrap().Name.StartsWith("@"); +EQNAME(context c, string name) => c.unwrap().Name == name; + +C() => new context; +ASSERT(self, ISDNAME(C()) as is); +C() => new context A; +ASSERT(self, EQNAME(C(), "A") as is); + +C() => context A { + f(x) => 5 * x; + g(x) => 4 * x; +}; +context B: C() { + sum(x) => this.f(x) - this.g(x); +}; +ASSERT(self, (B.sum(4) == 4) as is); + +context TBase { + constructor(x) { + this.A = 5 * x; + this.B = 4 * x; + abstract this.is_rem(x); + } +}; + +context X: TBase(25) { + is_rem(x) => this.A - this.B == x; +}; +ASSERT(self, (X.is_rem(25)) as is); \ No newline at end of file diff --git a/test/executing/0.8/funcdef.slt b/test/executing/0.8/funcdef.slt new file mode 100644 index 0000000..a95a0a8 --- /dev/null +++ b/test/executing/0.8/funcdef.slt @@ -0,0 +1,502 @@ +using SLThree.Method; +GET_GENERICS(method) => method is SLThree.GenericMethod ? method.Generics.Length : 0; +IS_RET(method, retname) => retname != null ? method.ReturnType?.ToString() == retname : method.ReturnType == null; +IS_ARG(method, arg) => arg != null ? method.ParamTypes[0]?.ToString() == arg : method.ParamTypes[0] == null; +HAS_ATTR(method) => method.Recursive || !method.Implicit; +NOT_ATTR(method) => !this.HAS_ATTR(method); + +M() => recursive explicit Name(args): Ret {}; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => recursive explicit Name(args): Ret {}; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => recursive explicit (args): Ret {}; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => recursive explicit (args): Ret {}; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => recursive explicit Name(args) {}; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => recursive explicit Name(args) {}; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => recursive explicit (args) {}; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => recursive explicit (args) {}; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => Name(args): Ret {}; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => Name(args): Ret {}; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => (args): Ret {}; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => (args): Ret {}; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => Name(args) {}; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => Name(args) {}; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => (args) {}; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => (args) {}; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, (M().Statements.Statements.Length == 0) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => recursive explicit Name(args): Ret { 2; }; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => recursive explicit Name(args): Ret { 2; }; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => recursive explicit (args): Ret { 2; }; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => recursive explicit (args): Ret { 2; }; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => recursive explicit Name(args) { 2; }; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => recursive explicit Name(args) { 2; }; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => recursive explicit (args) { 2; }; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => recursive explicit (args) { 2; }; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => Name(args): Ret { 2; }; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => Name(args): Ret { 2; }; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => (args): Ret { 2; }; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => (args): Ret { 2; }; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => Name(args) { 2; }; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => Name(args) { 2; }; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => (args) { 2; }; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => (args) { 2; }; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => recursive explicit Name(args): Ret => 2; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => recursive explicit Name(args): Ret => 2; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => recursive explicit (args): Ret => 2; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => recursive explicit (args): Ret => 2; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => recursive explicit Name(args) => 2; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => recursive explicit Name(args) => 2; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => recursive explicit (args) => 2; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => recursive explicit (args) => 2; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, HAS_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => Name(args): Ret => 2; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => Name(args): Ret => 2; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => (args): Ret => 2; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => (args): Ret => 2; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => Name(args) => 2; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => Name(args) => 2; +ASSERT(self, (M().Name == "Name") as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => (args) => 2; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 1) as is); + +M() => (args) => 2; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => ArgT arg: Ret => { 2; }; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, IS_ARG(M(), "ArgT") as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => ArgT arg => { 2; }; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, IS_ARG(M(), "ArgT") as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => arg: Ret => { 2; }; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, IS_ARG(M(), null) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => arg => { 2; }; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, IS_ARG(M(), null) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ExpressionStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => ArgT arg: Ret => 2; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, IS_ARG(M(), "ArgT") as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => ArgT arg => 2; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, IS_ARG(M(), "ArgT") as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => arg: Ret => 2; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, IS_ARG(M(), null) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), "Ret") as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); + +M() => arg => 2; +ASSERT(self, (M().Name == Method.DefaultMethodName) as is); +ASSERT(self, (M().ParamNames.Length == 1) as is); +ASSERT(self, IS_ARG(M(), null) as is); +st = M().Statements.Statements; +ASSERT(self, (st.Length == 1 && st[0] is SLThree.ReturnStatement) as is); +ASSERT(self, NOT_ATTR(M()) as is); +ASSERT(self, IS_RET(M(), null) as is); +ASSERT(self, (GET_GENERICS(M()) == 0) as is); \ No newline at end of file diff --git a/test/executing/0.8/instance.slt b/test/executing/0.8/instance.slt new file mode 100644 index 0000000..4eb27de --- /dev/null +++ b/test/executing/0.8/instance.slt @@ -0,0 +1,35 @@ +I() => new any; +ASSERT(self, (I() is any) as is); +I() => new list(0o10i32); +ASSERT(self, (I().Capacity == 0o10i32) as is); +I() => new any: (new context); +ASSERT(self, (I() is any) as is); +I() => new list(0o10i32): (new context); +ASSERT(self, (I().Capacity == 0o10i32) as is); + +I() => new any { Capacity = 5i32; }; +ASSERT(self, (I() is any) as is); +I() => new list(0o10i32) { Capacity = 5i32; }; +ASSERT(self, (I().Capacity == 5i32) as is); +I() => new any: (new context) { Capacity = 5i32; }; +ASSERT(self, (I() is any) as is); +I() => new list(0o10i32): (new context) { Capacity = 5i32; }; +ASSERT(self, (I().Capacity == 5i32) as is); + +I() => new any Name; +ASSERT(self, (I() is any) as is); +I() => new list(0o10i32) Name; +ASSERT(self, (I().Capacity == 0o10i32) as is); +I() => new any Name: (new context); +ASSERT(self, (I() is any) as is); +I() => new list(0o10i32) Name: (new context); +ASSERT(self, (I().Capacity == 0o10i32) as is); + +I() => new any Name { Capacity = 5i32; }; +ASSERT(self, (I() is any) as is); +I() => new list(0o10i32) Name { Capacity = 5i32; }; +ASSERT(self, (I().Capacity == 5i32) as is); +I() => new any Name: (new context) { Capacity = 5i32; }; +ASSERT(self, (I() is any) as is); +I() => new list(0o10i32) Name: (new context) { Capacity = 5i32; }; +ASSERT(self, (I().Capacity == 5i32) as is); \ No newline at end of file diff --git a/test/executing/0.8/static.slt b/test/executing/0.8/static.slt new file mode 100644 index 0000000..cbd0235 --- /dev/null +++ b/test/executing/0.8/static.slt @@ -0,0 +1,8 @@ +ASSERT(self, ((static x = 5) as is is SLThree.BinaryAssign) as is); +ASSERT(self, ((static x(a) => 5) as is is SLThree.BinaryAssign) as is); +ASSERT(self, ((static new context x) as is is SLThree.BinaryAssign) as is); +ASSERT(self, ((static new any x) as is is SLThree.BinaryAssign) as is); + +ASSERT_THROW(self, null as is, @SLThree.LogicalError, "static f = f(x) => 2"); +ASSERT_THROW(self, null as is, @SLThree.LogicalError, "static f = new context f"); +ASSERT_THROW(self, null as is, @SLThree.LogicalError, "static f = new any f"); \ No newline at end of file diff --git a/test/executing/0.8/using.slt b/test/executing/0.8/using.slt new file mode 100644 index 0000000..3ccdff2 --- /dev/null +++ b/test/executing/0.8/using.slt @@ -0,0 +1,2 @@ +using linq as L; +ASSERT(self, (L is SLThree.ClassAccess) as is); \ No newline at end of file diff --git a/test/executing/capturing.slt b/test/executing/capturing.slt index b7c1684..7019cc2 100644 --- a/test/executing/capturing.slt +++ b/test/executing/capturing.slt @@ -1,16 +1,16 @@ -plus = left => new context { +plus = left => context { left = left; with_right = right => this.left + right; }.with_right; -mins = left => new context { +mins = left => context { left = left; with_right = right => this.left - right; }.with_right; -mult = left => new context { +mult = left => context { left = left; with_right = right => this.left * right; }.with_right; -divi = left => new context { +divi = left => context { left = left; with_right = right => this.left / right; }.with_right; diff --git a/test/executing/expressions/brackets.slt b/test/executing/expressions/brackets.slt index c16b61d..e1737db 100644 --- a/test/executing/expressions/brackets.slt +++ b/test/executing/expressions/brackets.slt @@ -1,4 +1,4 @@ -tests = new context { +tests = context { //indexator (1), call (2), tuple (3) test_111 = [[[0x111]]]; diff --git a/test/executing/expressions/creators.slt b/test/executing/expressions/creators.slt index c902fe9..535fe11 100644 --- a/test/executing/expressions/creators.slt +++ b/test/executing/expressions/creators.slt @@ -8,7 +8,7 @@ lst = [228 as tested_type, ]; ASSERT(self, (lst[0] is tested_type) as is); //context -cntxt = new context { a = 229 as tested_type; }; +cntxt = context { a = 229 as tested_type; }; ASSERT(self, (cntxt.a is tested_type) as is); //using diff --git a/test/executing/reflection.slt b/test/executing/reflection.slt index 4b2a53e..7033996 100644 --- a/test/executing/reflection.slt +++ b/test/executing/reflection.slt @@ -1,6 +1,6 @@ ASSERT(self, (@TestSuite.Program == @TestSuite.Program) as is); ASSERT(self, (@TestSuite.Program::Assert(context, SLThree.BaseExpression) == ASSERT) as is); -x = new context A { +x = context A { ASSERT = ASSERT; OWN_ASSERT = @TestSuite.Program::Assert(context, SLThree.BaseExpression); m1 = () => this.ASSERT; diff --git a/test/parsing/char_based_interface.slt b/test/parsing/char_based_interface.slt index 9d269a1..6ac9601 100644 --- a/test/parsing/char_based_interface.slt +++ b/test/parsing/char_based_interface.slt @@ -21,7 +21,7 @@ while (true) { console.write(">>> "); input = console.readln().Trim(); match (input) { - "0" ==> { break; }; + "0" ==> break; "h" ==> out_help(); "+" ==> console.writeln($"Вывод: {global.a + global.b}"); "*" ==> console.writeln($"Вывод: {global.a * global.b}"); diff --git a/test/parsing/e_abstractmethod.slt b/test/parsing/e_abstractmethod.slt new file mode 100644 index 0000000..b1a3f69 --- /dev/null +++ b/test/parsing/e_abstractmethod.slt @@ -0,0 +1 @@ +f = abstract f(x); \ No newline at end of file diff --git a/test/parsing/e_binary.slt b/test/parsing/e_binary.slt new file mode 100644 index 0000000..9286857 --- /dev/null +++ b/test/parsing/e_binary.slt @@ -0,0 +1 @@ +2 + 2 - 2 * 2 / 2 % 2 == 2 != 2 && 2 || 2 & 2 | 2 ^ 2; \ No newline at end of file diff --git a/test/parsing/e_cast.slt b/test/parsing/e_cast.slt new file mode 100644 index 0000000..9034951 --- /dev/null +++ b/test/parsing/e_cast.slt @@ -0,0 +1,3 @@ +2 as i64; +(1, 2, 3) as tuple; +new context A as context; \ No newline at end of file diff --git a/test/parsing/e_condition.slt b/test/parsing/e_condition.slt new file mode 100644 index 0000000..ace0f81 --- /dev/null +++ b/test/parsing/e_condition.slt @@ -0,0 +1,8 @@ +x = if (true) 2 else 3; +x = if (true) { 2; } else 3; +x = if (true) 2 else { 3; }; +x = if (true) { 2; } else { 3; }; +if (true) 2 else 3; +if (true) { 2; } else 3; +if (true) 2 else { 3; }; +if (true) { 2; } else { 3; }; \ No newline at end of file diff --git a/test/parsing/e_cr_array.slt b/test/parsing/e_cr_array.slt new file mode 100644 index 0000000..3cdf913 --- /dev/null +++ b/test/parsing/e_cr_array.slt @@ -0,0 +1,2 @@ +-[1, 2, 3]; +-[,]; \ No newline at end of file diff --git a/test/parsing/e_cr_context.slt b/test/parsing/e_cr_context.slt new file mode 100644 index 0000000..f3ccea1 --- /dev/null +++ b/test/parsing/e_cr_context.slt @@ -0,0 +1,9 @@ +new context; +new context A; +new context: B; +new context A: B; + +context {}; +context A {}; +context: B {}; +context A: B {}; \ No newline at end of file diff --git a/test/parsing/e_cr_dictionary.slt b/test/parsing/e_cr_dictionary.slt new file mode 100644 index 0000000..bdb10aa --- /dev/null +++ b/test/parsing/e_cr_dictionary.slt @@ -0,0 +1,3 @@ +{}; +{2:3}; +{(new context): (new context)}; \ No newline at end of file diff --git a/test/parsing/e_cr_instance.slt b/test/parsing/e_cr_instance.slt new file mode 100644 index 0000000..ce94f00 --- /dev/null +++ b/test/parsing/e_cr_instance.slt @@ -0,0 +1,17 @@ +new T; +new T(args); +new T: A; +new T(args): A; +new T {}; +new T(args) {}; +new T: A {}; +new T(args): A {}; + +new T Name; +new T(args) Name; +new T Name: A; +new T(args) Name: A; +new T Name {}; +new T(args) Name {}; +new T Name: A {}; +new T(args) Name: A {}; \ No newline at end of file diff --git a/test/parsing/e_cr_list.slt b/test/parsing/e_cr_list.slt new file mode 100644 index 0000000..e7bfd16 --- /dev/null +++ b/test/parsing/e_cr_list.slt @@ -0,0 +1,2 @@ +[1, 2, 3]; +[,]; \ No newline at end of file diff --git a/test/parsing/e_cr_newarray.slt b/test/parsing/e_cr_newarray.slt new file mode 100644 index 0000000..b90b60c --- /dev/null +++ b/test/parsing/e_cr_newarray.slt @@ -0,0 +1,2 @@ +new T[100]; +new T[new T[10].Length]; \ No newline at end of file diff --git a/test/parsing/e_cr_range.slt b/test/parsing/e_cr_range.slt new file mode 100644 index 0000000..d36afe6 --- /dev/null +++ b/test/parsing/e_cr_range.slt @@ -0,0 +1,2 @@ +1..100; +(^1..50)..(^50..100); \ No newline at end of file diff --git a/test/parsing/e_cr_tuple.slt b/test/parsing/e_cr_tuple.slt new file mode 100644 index 0000000..6ac9796 --- /dev/null +++ b/test/parsing/e_cr_tuple.slt @@ -0,0 +1,2 @@ +(1, ) == (1, ); +(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ No newline at end of file diff --git a/test/parsing/e_cr_using.slt b/test/parsing/e_cr_using.slt new file mode 100644 index 0000000..638f68d --- /dev/null +++ b/test/parsing/e_cr_using.slt @@ -0,0 +1 @@ +new using linq; \ No newline at end of file diff --git a/test/parsing/e_formatstr.slt b/test/parsing/e_formatstr.slt new file mode 100644 index 0000000..b2cb853 --- /dev/null +++ b/test/parsing/e_formatstr.slt @@ -0,0 +1,2 @@ +$"{x} {a ? b : c} {2 + 3 + 4}"; +$"{$"{$"{$""}"}"}"; \ No newline at end of file diff --git a/test/parsing/e_funcdef.slt b/test/parsing/e_funcdef.slt new file mode 100644 index 0000000..1f4606e --- /dev/null +++ b/test/parsing/e_funcdef.slt @@ -0,0 +1,57 @@ +recursive explicit Name(args): Ret {}; +recursive explicit Name(args): Ret {}; +recursive explicit (args): Ret {}; +recursive explicit (args): Ret {}; +recursive explicit Name(args) {}; +recursive explicit Name(args) {}; +recursive explicit (args) {}; +recursive explicit (args) {}; +Name(args): Ret {}; +Name(args): Ret {}; +(args): Ret {}; +(args): Ret {}; +Name(args) {}; +Name(args) {}; +(args) {}; +(args) {}; +recursive explicit Name(args): Ret => { 2; }; +recursive explicit Name(args): Ret => { 2; }; +recursive explicit (args): Ret => { 2; }; +recursive explicit (args): Ret => { 2; }; +recursive explicit Name(args) => { 2; }; +recursive explicit Name(args) => { 2; }; +recursive explicit (args) => { 2; }; +recursive explicit (args) => { 2; }; +Name(args): Ret => { 2; }; +Name(args): Ret => { 2; }; +(args): Ret => { 2; }; +(args): Ret => { 2; }; +Name(args) => { 2; }; +Name(args) => { 2; }; +(args) => { 2; }; +(args) => { 2; }; +recursive explicit Name(args): Ret => 2; +recursive explicit Name(args): Ret => 2; +recursive explicit (args): Ret => 2; +recursive explicit (args): Ret => 2; +recursive explicit Name(args) => 2; +recursive explicit Name(args) => 2; +recursive explicit (args) => 2; +recursive explicit (args) => 2; +Name(args): Ret => 2; +Name(args): Ret => 2; +(args): Ret => 2; +(args): Ret => 2; +Name(args) => 2; +Name(args) => 2; +(args) => 2; +(args) => 2; + +ArgT arg: Ret => { 2; }; +ArgT arg => { 2; }; +arg: Ret => { 2; }; +arg => { 2; }; +ArgT arg: Ret => 2; +ArgT arg => 2; +arg: Ret => 2; +arg => 2; \ No newline at end of file diff --git a/test/parsing/e_invoke.slt b/test/parsing/e_invoke.slt new file mode 100644 index 0000000..8222e78 --- /dev/null +++ b/test/parsing/e_invoke.slt @@ -0,0 +1,7 @@ +x(); +x(1, 2, 3); +x(1, 2, 3)(1, 2, 3); + +x(); +x(1, 2, 3); +x(1, 2, 3)(1, 2, 3); \ No newline at end of file diff --git a/test/parsing/e_literal.slt b/test/parsing/e_literal.slt new file mode 100644 index 0000000..34981ed --- /dev/null +++ b/test/parsing/e_literal.slt @@ -0,0 +1,13 @@ +1; 1.0; + +-128i8; -32768i16; -2147483648i32; -9223372036854775808i64; + +0b11; 0b11i8; 0b11u8; +0o11; 0o11i8; 0o11u8; +0x11; 0x11i8; 0x11u8; + +1f32; 1.0f32; 1f64; 1.0f64; + +false; true; +"str"; +null; \ No newline at end of file diff --git a/test/parsing/e_match.slt b/test/parsing/e_match.slt new file mode 100644 index 0000000..c66c561 --- /dev/null +++ b/test/parsing/e_match.slt @@ -0,0 +1,5 @@ +match (1) { 1 ==> 2; () ==> 3; }; +match (match (^50%) { false ==> 1; true ==> 2; }) { + 1 ==> 2; + () ==> 3; +}; \ No newline at end of file diff --git a/test/parsing/e_name.slt b/test/parsing/e_name.slt new file mode 100644 index 0000000..b5c13eb --- /dev/null +++ b/test/parsing/e_name.slt @@ -0,0 +1,2 @@ +a; +self; this; super; upper; parent; global; private; \ No newline at end of file diff --git a/test/parsing/e_reflection.slt b/test/parsing/e_reflection.slt new file mode 100644 index 0000000..67cb875 --- /dev/null +++ b/test/parsing/e_reflection.slt @@ -0,0 +1,2 @@ +@i64; +parse = @i64::Parse(string); \ No newline at end of file diff --git a/test/parsing/e_static.slt b/test/parsing/e_static.slt new file mode 100644 index 0000000..d417d50 --- /dev/null +++ b/test/parsing/e_static.slt @@ -0,0 +1,4 @@ +static a = 2; +static f(x) => x; +static new context A; +static new T X; \ No newline at end of file diff --git a/test/parsing/e_ternary.slt b/test/parsing/e_ternary.slt new file mode 100644 index 0000000..51a6ed4 --- /dev/null +++ b/test/parsing/e_ternary.slt @@ -0,0 +1 @@ +2 == 2 ? 2 : 2; \ No newline at end of file diff --git a/test/parsing/e_unary.slt b/test/parsing/e_unary.slt new file mode 100644 index 0000000..9aeb04a --- /dev/null +++ b/test/parsing/e_unary.slt @@ -0,0 +1 @@ ++-*^50; \ No newline at end of file diff --git a/test/parsing/e_using.slt b/test/parsing/e_using.slt new file mode 100644 index 0000000..e2a7a4c --- /dev/null +++ b/test/parsing/e_using.slt @@ -0,0 +1,2 @@ +using slt; +using slt as AAA; \ No newline at end of file diff --git a/test/parsing/get_system_types.slt b/test/parsing/get_system_types.slt deleted file mode 100644 index 30d5036..0000000 --- a/test/parsing/get_system_types.slt +++ /dev/null @@ -1,3 +0,0 @@ -using SLThree.UsingStatement; -using linq; -linq.jts(UsingStatement.SystemTypes.Keys, "\n"); \ No newline at end of file diff --git a/test/parsing/hell_callable.slt b/test/parsing/hell_callable.slt index 4ae4374..574b90e 100644 --- a/test/parsing/hell_callable.slt +++ b/test/parsing/hell_callable.slt @@ -1,4 +1,4 @@ -global.a = () => new context { r = () => global; }; +global.a = () => context { r = () => global; }; global.a().r().a().r().a().r().a(); global.a = [() => 2]; global.a[0]().ToString(); \ No newline at end of file diff --git a/test/parsing/literals.slt b/test/parsing/literals.slt deleted file mode 100644 index 46e1805..0000000 --- a/test/parsing/literals.slt +++ /dev/null @@ -1,4 +0,0 @@ --128i8; -0b1000_1000; -0o777; -0xFF__FF__FF; \ No newline at end of file diff --git a/test/parsing/recursive_fibonacci.slt b/test/parsing/recursive_fibonacci.slt index 4e9b6f4..40547b5 100644 --- a/test/parsing/recursive_fibonacci.slt +++ b/test/parsing/recursive_fibonacci.slt @@ -1,4 +1,4 @@ -global.fib = recursive n => { +global.fib = recursive (n) => { if (n < 2) { return n; } diff --git a/test/parsing/st_break.slt b/test/parsing/st_break.slt new file mode 100644 index 0000000..8cb76cf --- /dev/null +++ b/test/parsing/st_break.slt @@ -0,0 +1 @@ +break; \ No newline at end of file diff --git a/test/parsing/st_condition.slt b/test/parsing/st_condition.slt new file mode 100644 index 0000000..794c8c0 --- /dev/null +++ b/test/parsing/st_condition.slt @@ -0,0 +1,3 @@ +if (true) 2; else 3; +if (true) 2; else { 3; } +if (true) { 2; } else { 3; } \ No newline at end of file diff --git a/test/parsing/st_context.slt b/test/parsing/st_context.slt new file mode 100644 index 0000000..2bd16f4 --- /dev/null +++ b/test/parsing/st_context.slt @@ -0,0 +1,4 @@ +context {} +context A {} +context: B {} +context A: B {} \ No newline at end of file diff --git a/test/parsing/st_continue.slt b/test/parsing/st_continue.slt new file mode 100644 index 0000000..45127c0 --- /dev/null +++ b/test/parsing/st_continue.slt @@ -0,0 +1 @@ +continue; \ No newline at end of file diff --git a/test/parsing/st_empty.slt b/test/parsing/st_empty.slt new file mode 100644 index 0000000..1c8a0e7 --- /dev/null +++ b/test/parsing/st_empty.slt @@ -0,0 +1 @@ +; \ No newline at end of file diff --git a/test/parsing/st_expression.slt b/test/parsing/st_expression.slt new file mode 100644 index 0000000..e8f1808 --- /dev/null +++ b/test/parsing/st_expression.slt @@ -0,0 +1,4 @@ +{}; //dictionary +2; +1/1; +new context A; \ No newline at end of file diff --git a/test/parsing/st_foreach.slt b/test/parsing/st_foreach.slt new file mode 100644 index 0000000..2d859d4 --- /dev/null +++ b/test/parsing/st_foreach.slt @@ -0,0 +1,7 @@ +foreach (x in a) ; +foreach (x in a) { + ; +} +foreach (x in a) { + foreach (x in a) ; +} \ No newline at end of file diff --git a/test/parsing/st_intance.slt b/test/parsing/st_intance.slt new file mode 100644 index 0000000..7a2c131 --- /dev/null +++ b/test/parsing/st_intance.slt @@ -0,0 +1,9 @@ +new T {} +new T(args) {} +new T: A {} +new T(args): A {} + +new T Name {} +new T(args) Name {} +new T Name: A {} +new T(args) Name: A {} \ No newline at end of file diff --git a/test/parsing/st_return.slt b/test/parsing/st_return.slt new file mode 100644 index 0000000..0737c63 --- /dev/null +++ b/test/parsing/st_return.slt @@ -0,0 +1,6 @@ +return; +return 0xFF; +return context { + x = 2; +}; +return new T; \ No newline at end of file diff --git a/test/parsing/st_throw.slt b/test/parsing/st_throw.slt new file mode 100644 index 0000000..f598099 --- /dev/null +++ b/test/parsing/st_throw.slt @@ -0,0 +1,2 @@ +throw 2; +throw new System.Exception("234235"); \ No newline at end of file diff --git a/test/parsing/st_try.slt b/test/parsing/st_try.slt new file mode 100644 index 0000000..978d895 --- /dev/null +++ b/test/parsing/st_try.slt @@ -0,0 +1,6 @@ +try {;} catch (e) {;} finally {;} +try {;} catch (e) console.writeln(e); finally {;} +try {;} catch (e) console.writeln(e); +try {;} catch {;} finally {;} +try {;} catch {;} +try {;} \ No newline at end of file diff --git a/test/parsing/st_while.slt b/test/parsing/st_while.slt new file mode 100644 index 0000000..c07ac13 --- /dev/null +++ b/test/parsing/st_while.slt @@ -0,0 +1,4 @@ +while (true) ; +while (true) { + while (false) ; +} \ No newline at end of file diff --git a/verser/verser.exe b/verser/verser.exe new file mode 100644 index 0000000..a9c0bcf Binary files /dev/null and b/verser/verser.exe differ diff --git a/verser/verserconfig.xml b/verser/verserconfig.xml new file mode 100644 index 0000000..014065a --- /dev/null +++ b/verser/verserconfig.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file