From 3601d1fbd089497d552bf1aab5f5d2b4d3c9bfbb Mon Sep 17 00:00:00 2001 From: mystborn Date: Sun, 22 Apr 2018 01:30:07 -0600 Subject: [PATCH 01/54] Updated TsInstance to Use ClassBinder --- TaffyScript/Collections/Binder.cs | 27 ++++++++ TaffyScript/InstanceEnumerator.cs | 2 +- TaffyScript/TsInstance.cs | 65 +++++++++---------- TaffyScript/TsObject.cs | 21 ++---- .../Backend/BaseClassLibrary.cs | 2 +- .../Backend/Compiler/MsilWeakCodeGen.cs | 2 +- 6 files changed, 65 insertions(+), 54 deletions(-) diff --git a/TaffyScript/Collections/Binder.cs b/TaffyScript/Collections/Binder.cs index 1e3760b..126b648 100644 --- a/TaffyScript/Collections/Binder.cs +++ b/TaffyScript/Collections/Binder.cs @@ -31,6 +31,13 @@ public interface IBinder /// Item index. int Add(T item); + /// + /// Determines if the Binder contains an item with the specified index. + /// + /// The index of the item. + /// True if the item was found; otherwise false. + bool Contains(int index); + /// /// Removes the item at the specified index. /// @@ -104,6 +111,16 @@ public int Add(T item) return index; } + /// + /// Determines if the Binder contains an item with the specified index. + /// + /// The index of the item. + /// True if the item was found; otherwise false. + public bool Contains(int index) + { + return index >= 0 && index < _count && _binder[index] != null; + } + /// /// Returns an enumerator used to enumerate through all of the bound items. /// @@ -222,6 +239,16 @@ public int Add(T item) return index; } + /// + /// Determines if the Binder contains an item with the specified index. + /// + /// The index of the item. + /// True if the item was found; otherwise false. + public bool Contains(int index) + { + return index >= 0 && index < _count && !_binder[index].Equals(Default); + } + /// /// Returns an enumerator used to enumerate through all of the bound items. /// diff --git a/TaffyScript/InstanceEnumerator.cs b/TaffyScript/InstanceEnumerator.cs index 20fb9f1..ab17d3b 100644 --- a/TaffyScript/InstanceEnumerator.cs +++ b/TaffyScript/InstanceEnumerator.cs @@ -49,7 +49,7 @@ public bool MoveNext() { result = _backingEnumerator.MoveNext(); } - while (result == true && !TsInstance.InstanceExists(((TsImmutableValue)_backingEnumerator.Current.Value).StrongValue)); + while (result == true && !TsInstance.InstanceExists((int)_backingEnumerator.Current)); return result; } diff --git a/TaffyScript/TsInstance.cs b/TaffyScript/TsInstance.cs index f4616c6..d493647 100644 --- a/TaffyScript/TsInstance.cs +++ b/TaffyScript/TsInstance.cs @@ -14,7 +14,6 @@ namespace TaffyScript /// public class TsInstance { - private const float Start = 100000f; private const string CreateEvent = "create"; private const string DestroyEvent = "destroy"; @@ -32,15 +31,7 @@ public class TsInstance /// /// Keeps a reference to all of the instances that currently exist, to be retrieved via their id. /// - /// - /// This can be changed to be list for a speed increase. Testing needed. - /// If changed, when retrieving an instance it should go something like this: - /// var index = (int)id - Start; - /// return Pool[index]; - /// Keep in mind there will need be at least one check for null. - /// - private static Dictionary Pool = new Dictionary(); - private static Queue _availableIds = new Queue(); + private static ClassBinder _pool = new ClassBinder(); private Dictionary _vars = new Dictionary(); @@ -102,7 +93,7 @@ public TsObject this[string variableName] /// /// Gets the id of this instance. /// - public float Id { get; } + public int Id { get; } /// /// Gets the type of this instance. @@ -121,9 +112,8 @@ public TsObject this[string variableName] /// Any arguments passed to the create event. public TsInstance(string instanceType, params TsObject[] args) { - Id = GetNext(); + Id = _pool.Add(this); ObjectType = instanceType; - Pool.Add(Id, this); Init(true, args); } @@ -134,9 +124,8 @@ private TsInstance(string instanceType, bool performEvent = true, params TsObjec // This decision is easily reversable if it turns out to be wrong/unneeded. // In the meantime, you can still refer to the event by it's string representation. - Id = GetNext(); + Id = _pool.Add(this); ObjectType = instanceType; - Pool.Add(Id, this); Init(performEvent, args); } @@ -288,16 +277,30 @@ public TsInstance Copy(bool performEvents) /// public void Destroy() { - if (Pool.ContainsKey(Id)) + if(_pool.Contains(Id)) { if (TryGetDelegate(DestroyEvent, out var destroy)) destroy.Invoke(this); - Pool.Remove(Id); - _availableIds.Enqueue(Id); + _pool.Remove(Id); Destroyed?.Invoke(this); } } + public override string ToString() + { + return $"{ObjectType} {Id}"; + } + + public override int GetHashCode() + { + return Id; + } + + public override bool Equals(object obj) + { + return obj is TsInstance inst && inst.Id == Id; + } + /// /// Gets an event defined by the given type. /// @@ -389,7 +392,7 @@ public static TsObject InstanceDestroy(TsInstance target, TsObject[] args) if (args == null || args.Length == 0) target.Destroy(); else - InstanceDestroy((float)args[0]); + InstanceDestroy((int)args[0]); return TsObject.Empty(); } @@ -398,9 +401,9 @@ public static TsObject InstanceDestroy(TsInstance target, TsObject[] args) /// Destroys a previously created instance. /// /// Instance id - public static void InstanceDestroy(float id) + public static void InstanceDestroy(int id) { - if (Pool.TryGetValue(id, out var inst)) + if (_pool.TryGetValue(id, out var inst)) inst.Destroy(); } @@ -409,9 +412,9 @@ public static void InstanceDestroy(float id) /// /// Instance id /// - public static bool InstanceExists(float id) + public static bool InstanceExists(int id) { - return Pool.ContainsKey(id); + return _pool.Contains(id); } /// @@ -585,9 +588,9 @@ public static void VariableInstanceSet(TsInstance inst, string name, TsObject va /// Instance id /// If it exists, the instance with the given id /// - public static bool TryGetInstance(float id, out TsInstance inst) + public static bool TryGetInstance(int id, out TsInstance inst) { - return Pool.TryGetValue(id, out inst); + return _pool.TryGetValue(id, out inst); } /// @@ -596,7 +599,7 @@ public static bool TryGetInstance(float id, out TsInstance inst) /// public static IEnumerable Instances() { - foreach (var inst in Pool.Keys) + foreach (var inst in _pool) { yield return new TsObject(inst); } @@ -609,7 +612,7 @@ public static IEnumerable Instances() /// public static IEnumerable Instances(string type) { - foreach (var inst in Pool.Values) + foreach (var inst in _pool) if (inst.ObjectType == type || ObjectIsAncestor(inst.ObjectType, type)) yield return new TsObject(inst.Id); } @@ -618,13 +621,5 @@ private static TsInstance InitGlobal() { return new TsInstance(); } - - private static float GetNext() - { - if (_availableIds.Count == 0) - return Pool.Count + Start; - else - return _availableIds.Dequeue(); - } } } diff --git a/TaffyScript/TsObject.cs b/TaffyScript/TsObject.cs index 64502dc..0d30259 100644 --- a/TaffyScript/TsObject.cs +++ b/TaffyScript/TsObject.cs @@ -368,7 +368,7 @@ public string GetStringUnchecked() /// public TsInstance GetInstance() { - if (!TsInstance.TryGetInstance(GetFloat(), out var inst)) + if (!TsInstance.TryGetInstance(GetInt(), out var inst)) throw new InvalidInstanceException(); return inst; } @@ -437,9 +437,7 @@ public object GetValue() /// The value of the variable. public void MemberSet(string name, float value) { - if (!TsInstance.TryGetInstance(GetFloat(), out var inst)) - throw new InvalidInstanceException(); - inst[name] = new TsObject(value); + GetInstance()[name] = value; } /// @@ -449,9 +447,7 @@ public void MemberSet(string name, float value) /// The value of the variable. public void MemberSet(string name, string value) { - if (!TsInstance.TryGetInstance(GetFloat(), out var inst)) - throw new InvalidInstanceException(); - inst[name] = new TsObject(value); + GetInstance()[name] = value; } /// @@ -461,9 +457,7 @@ public void MemberSet(string name, string value) /// The value of the variable. public void MemberSet(string name, TsObject value) { - if (!TsInstance.TryGetInstance(GetFloat(), out var inst)) - throw new InvalidInstanceException(); - inst[name] = value; + GetInstance()[name] = value; } /// @@ -473,11 +467,7 @@ public void MemberSet(string name, TsObject value) /// public TsObject MemberGet(string name) { - if (!TsInstance.TryGetInstance(GetFloat(), out var inst)) - { - throw new InvalidInstanceException(); - } - return inst[name]; + return GetInstance()[name]; } #endregion @@ -1398,6 +1388,5 @@ public static string Typeof(TsObject obj) } #endregion - } } diff --git a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs b/TaffyScriptCompiler/Backend/BaseClassLibrary.cs index c727ceb..233854d 100644 --- a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs +++ b/TaffyScriptCompiler/Backend/BaseClassLibrary.cs @@ -124,7 +124,7 @@ public static string Generate() sb.AppendLine("import TsInstance.InstanceCopy(instance, array) as instance_copy"); sb.AppendLine("import TsInstance.InstanceCreate(instance, array) as instance_create"); sb.AppendLine("import TsInstance.InstanceDestroy(instance, array) as instance_destroy"); - sb.AppendLine("import TsInstance.InstanceExists(float) as instance_exists"); + sb.AppendLine("import TsInstance.InstanceExists(int) as instance_exists"); sb.AppendLine("import TsInstance.InstanceFind(string, int) as instance_find"); sb.AppendLine("import TsInstance.InstanceNumber(string) as instance_number"); diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index c4004b4..2eb4155 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -2334,7 +2334,7 @@ public void Visit(MemberAccessNode memberAccess) } emit.Call(typeof(TsObject).GetMethod("GetInstance")) .Call(typeof(TsInstance).GetMethod("get_Id")) - .New(TsTypes.Constructors[typeof(float)]); + .New(TsTypes.Constructors[typeof(int)]); } else _errors.Add(new CompileException($"Invalid syntax detected {memberAccess.Position}")); From c10aee0f056ee28fc3da51be0b4ca3052a382cb6 Mon Sep 17 00:00:00 2001 From: mystborn Date: Sun, 22 Apr 2018 23:15:12 -0600 Subject: [PATCH 02/54] Better Syntax Elements --- Samples/TestSuite/Tests/build.cfg | 4 + Samples/TestSuite/Tests/object_import.tfs | 33 ++++ Samples/TestSuite/Tests/struct.tfs | 42 +++++ TaffyScript/ITsInstance.cs | 65 +++++++ TaffyScript/TaffyScript.csproj | 1 + TaffyScript/TsInstance.cs | 12 +- .../Backend/Compiler/MsilWeakCodeGen.cs | 161 +++++++++--------- .../Backend/Compiler/MsilWeakCompiler.cs | 2 +- TaffyScriptCompiler/Syntax/ISyntaxElement.cs | 1 + TaffyScriptCompiler/Syntax/ISyntaxNode.cs | 1 - TaffyScriptCompiler/Syntax/ISyntaxToken.cs | 1 - TaffyScriptCompiler/Syntax/SyntaxNode.cs | 6 +- 12 files changed, 237 insertions(+), 92 deletions(-) create mode 100644 Samples/TestSuite/Tests/object_import.tfs create mode 100644 Samples/TestSuite/Tests/struct.tfs create mode 100644 TaffyScript/ITsInstance.cs diff --git a/Samples/TestSuite/Tests/build.cfg b/Samples/TestSuite/Tests/build.cfg index 7cb04f4..d8fc1f2 100644 --- a/Samples/TestSuite/Tests/build.cfg +++ b/Samples/TestSuite/Tests/build.cfg @@ -6,6 +6,10 @@ ..\TaffyScript.Tests\bin\Release\TaffyScript.Tests.dll ..\UnitTestLib\bin\UnitTest.dll + + struct.tfs + object_import + LanguageTests.main Debug \ No newline at end of file diff --git a/Samples/TestSuite/Tests/object_import.tfs b/Samples/TestSuite/Tests/object_import.tfs new file mode 100644 index 0000000..13c806c --- /dev/null +++ b/Samples/TestSuite/Tests/object_import.tfs @@ -0,0 +1,33 @@ +// Object imports aren't implemented yed; they may never be. +// This file shows a potential implementation. +// Currently it's excluded from the build. + +namespace LanguageTests { + //Explicitly import class and method. + import object List as obj_list { + //Import fields and properties. + Count as size; + + //Import single constructor. Doesn't have to be parameterless ctor. + new(); + + //Import methods with a new name. + Add(object) as add; + Clear() as clear; + RemoveAt(int) as delete; + get_Item(int) as get; + set_Item(int) as set; + Insert(int, object) as insert; + Sort() as sort; + } + + //Auto generate imports from class. Explicitly convert member names to specified casing. + import object(case=snake_case) Dictionary as obj_map; + + script list_add_many(list) { + for(var i = 1; i < argument_count; i++) { + list.add(argument[i]); + } + return list.count; + } +} \ No newline at end of file diff --git a/Samples/TestSuite/Tests/struct.tfs b/Samples/TestSuite/Tests/struct.tfs new file mode 100644 index 0000000..bda0375 --- /dev/null +++ b/Samples/TestSuite/Tests/struct.tfs @@ -0,0 +1,42 @@ +// Structs aren't implemented yed; they may never be. +// This file shows a potential implementation. +// Currently it's excluded from the build. + +using UnitTest; + +namespace LanguageTests { + struct point { + x : int; + y : int; + } + + script point_create(x, y) { + var p = new point(); + p.x = x; + p.y = y; + + return p; + } + + struct node { + next; + previous; + value; + } + + script node_create_after(before, value) { + var n = new node(); + n.value = value; + + if(before == noone) { + n.next = noone; + n.previous = noone; + } else { + n.next = before.next; + n.previous = before; + before.next = n; + } + + return n; + } +} \ No newline at end of file diff --git a/TaffyScript/ITsInstance.cs b/TaffyScript/ITsInstance.cs new file mode 100644 index 0000000..a15b6b7 --- /dev/null +++ b/TaffyScript/ITsInstance.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScript +{ + /// + /// Represents an instance of an object in TaffyScript. + /// + public interface ITsInstance + { + /// + /// Event that gets triggered when this instance is destroyed. + /// + event DestroyedDelegate Destroyed; + + /// + /// Gets or sets a value based on a variable name. + /// + /// The name of the variable + /// + TsObject this[string memberName] { get; set; } + + /// + /// Gets the type of this instance. + /// + string ObjectType { get; } + + /// + /// Gets the value of a member from this instance. + /// + /// The name of the member. + /// + TsObject GetMember(string name); + + /// + /// Sets the value of a member on this instance. + /// + /// The name of the member. + /// The new value. + void SetMember(string name, TsObject value); + + /// + /// Destroys this instance. + /// + void Destroy(); + + /// + /// Gets a delegate defined by this instance. + /// + /// The name of the delegate. + /// If found, the delegate. + /// True if found, false otherwise. + bool TryGetDelegate(string delegateName, out TsDelegate del); + + /// + /// Gets a delegate defined by this instance. + /// + /// The name of the delegate. + /// + TsDelegate GetDelegate(string delegateName); + } +} diff --git a/TaffyScript/TaffyScript.csproj b/TaffyScript/TaffyScript.csproj index 6da1723..3ac2fd2 100644 --- a/TaffyScript/TaffyScript.csproj +++ b/TaffyScript/TaffyScript.csproj @@ -53,6 +53,7 @@ + diff --git a/TaffyScript/TsInstance.cs b/TaffyScript/TsInstance.cs index d493647..4a26c9f 100644 --- a/TaffyScript/TsInstance.cs +++ b/TaffyScript/TsInstance.cs @@ -9,6 +9,12 @@ namespace TaffyScript { + /// + /// Delegate used to represent methods to be triggered when a TS instance is destroyed. + /// + /// The instance that was destroyed. + public delegate void DestroyedDelegate(TsInstance inst); + /// /// Represents an instance of an object in TaffyScript. /// @@ -17,12 +23,6 @@ public class TsInstance private const string CreateEvent = "create"; private const string DestroyEvent = "destroy"; - /// - /// Delegate used to represent methods to be triggered when a TS instance is destroyed. - /// - /// The instance that was destroyed. - public delegate void DestroyedDelegate(TsInstance inst); - /// /// Event that gets triggered when this instance is destroyed. /// diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index 2eb4155..bc9469e 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -782,7 +782,7 @@ private void MarkSequencePoint(ISyntaxElement element) line = element.Position.Line; if (element.IsToken) { - end = element.Position.Column + ((ISyntaxToken)element).Text.Length + 2; + end = element.Position.Column + element.Text.Length + 2; break; } else @@ -790,7 +790,7 @@ private void MarkSequencePoint(ISyntaxElement element) var node = element as ISyntaxNode; if (node.Children.Count == 0) { - end = node.Position.Column + (node.Value == null ? 0 : node.Value.Length) + 2; + end = node.Position.Column + (node.Text == null ? 0 : node.Text.Length) + 2; break; } else @@ -859,7 +859,7 @@ private void FreeLocal(LocalBuilder local) private ISyntaxElement ResolveNamespace(MemberAccessNode node) { - if (node.Left is ISyntaxToken token && _table.Defined(token.Text, out var symbol) && symbol.Type == SymbolType.Namespace) + if (node.Left.Text != null && _table.Defined(node.Left.Text, out var symbol) && symbol.Type == SymbolType.Namespace) { _table.Enter(symbol.Name); _resolveNamespace = symbol.Name; @@ -912,7 +912,7 @@ private ISyntaxElement ResolveNamespace(MemberAccessNode node) private bool TryResolveNamespace(MemberAccessNode node, out ISyntaxElement resolved) { resolved = default(ISyntaxElement); - if (node.Left is ISyntaxToken token && _table.Defined(token.Text, out var symbol) && symbol.Type == SymbolType.Namespace) + if (node.Left.Text != null && _table.Defined(node.Left.Text, out var symbol) && symbol.Type == SymbolType.Namespace) { _table.Enter(symbol.Name); _resolveNamespace = symbol.Name; @@ -1045,44 +1045,44 @@ public void Visit(AdditiveNode additive) { if (right == typeof(float)) { - if (additive.Value == "+") + if (additive.Text == "+") emit.Add(); else emit.Sub(); } else if (right == typeof(string)) { - _errors.Add(new CompileException($"Cannot {additive.Value} types {left} and {right} {additive.Position}")); + _errors.Add(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}")); return; } else if (right == typeof(TsObject)) - emit.Call(GetOperator(additive.Value, left, right, additive.Position)); + emit.Call(GetOperator(additive.Text, left, right, additive.Position)); else { - _errors.Add(new CompileException($"Cannot {additive.Value} types {left} and {right} {additive.Position}")); + _errors.Add(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}")); return; } } else if(left == typeof(string)) { - if (additive.Value != "+") + if (additive.Text != "+") { - _errors.Add(new CompileException($"Cannot {additive.Value} types {left} and {right} {additive.Position}")); + _errors.Add(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}")); return; } if (right == typeof(float)) { - _errors.Add(new CompileException($"Cannot {additive.Value} types {left} and {right} {additive.Position}")); + _errors.Add(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}")); return; } else if(right == typeof(string)) emit.Call(typeof(string).GetMethod("Concat", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string), typeof(string) }, null)); else if(right == typeof(TsObject)) - emit.Call(GetOperator(additive.Value, left, right, additive.Position)); + emit.Call(GetOperator(additive.Text, left, right, additive.Position)); } else if(left == typeof(TsObject)) { - var method = GetOperator(additive.Value, left, right, additive.Position); + var method = GetOperator(additive.Text, left, right, additive.Position); emit.Call(method); } } @@ -1151,7 +1151,7 @@ public void Visit(ArrayLiteralNode arrayLiteral) public void Visit(AssignNode assign) { - if(assign.Value != "=") + if(assign.Text != "=") { ProcessAssignExtra(assign); return; @@ -1294,7 +1294,7 @@ public void Visit(AssignNode assign) else if (top != typeof(TsObject).MakePointerType()) _errors.Add(new CompileException($"Invalid syntax detected {member.Left.Position}")); - emit.LdStr(((ISyntaxToken)member.Right).Text); + emit.LdStr(member.Right.Text); assign.Right.Accept(this); top = emit.GetTop(); if (top == typeof(int)) @@ -1319,7 +1319,7 @@ public void Visit(AssignNode assign) private void ProcessAssignExtra(AssignNode assign) { - var op = assign.Value.Replace("=", ""); + var op = assign.Text.Replace("=", ""); if (assign.Left.Type == SyntaxType.ArrayAccess || assign.Left.Type == SyntaxType.ArgumentAccess) { //Because this has to access the array location, @@ -1517,7 +1517,7 @@ public void Visit(BitwiseNode bitwise) { var leftConst = bitwise.Left as IConstantToken; if (leftConst == null) - _errors.Add(new CompileException($"Cannot perform operator {bitwise.Value} on the constant type {(bitwise.Left as IConstantToken).ConstantType} {bitwise.Position}")); + _errors.Add(new CompileException($"Cannot perform operator {bitwise.Text} on the constant type {(bitwise.Left as IConstantToken).ConstantType} {bitwise.Position}")); else emit.LdLong((long)leftConst.Value); } @@ -1526,7 +1526,7 @@ public void Visit(BitwiseNode bitwise) GetAddressIfPossible(bitwise.Left); var top = emit.GetTop(); if (top != typeof(TsObject) && top != typeof(TsObject).MakePointerType()) - _errors.Add(new CompileException($"Cannot perform operator {bitwise.Value} on the type {emit.GetTop()} {bitwise.Position}")); + _errors.Add(new CompileException($"Cannot perform operator {bitwise.Text} on the type {emit.GetTop()} {bitwise.Position}")); emit.Call(TsTypes.ObjectCasts[typeof(long)]); } @@ -1534,7 +1534,7 @@ public void Visit(BitwiseNode bitwise) { var rightConst = bitwise.Right as IConstantToken; if(rightConst == null) - _errors.Add(new CompileException($"Cannot perform operator {bitwise.Value} on the constant type {(bitwise.Right as IConstantToken).ConstantType} {bitwise.Position}")); + _errors.Add(new CompileException($"Cannot perform operator {bitwise.Text} on the constant type {(bitwise.Right as IConstantToken).ConstantType} {bitwise.Position}")); else emit.LdLong((long)rightConst.Value); } @@ -1543,11 +1543,11 @@ public void Visit(BitwiseNode bitwise) GetAddressIfPossible(bitwise.Right); var top = emit.GetTop(); if (top != typeof(TsObject) && top != typeof(TsObject).MakePointerType()) - _errors.Add(new CompileException($"Cannot perform operator {bitwise.Value} on the type {top} {bitwise.Position}")); + _errors.Add(new CompileException($"Cannot perform operator {bitwise.Text} on the type {top} {bitwise.Position}")); emit.Call(TsTypes.ObjectCasts[typeof(long)]); } - switch(bitwise.Value) + switch(bitwise.Text) { case "|": emit.Or(); @@ -1560,7 +1560,7 @@ public void Visit(BitwiseNode bitwise) break; default: //Should be impossible. - _errors.Add(new CompileException($"Invalid bitwise operator detected: {bitwise.Value} {bitwise.Position}")); + _errors.Add(new CompileException($"Invalid bitwise operator detected: {bitwise.Text} {bitwise.Position}")); break; } emit.ConvertFloat(); @@ -1650,7 +1650,7 @@ public void Visit(ContinueToken continueToken) public void Visit(DeclareNode declare) { - if (_table.Defined(declare.Value, out var symbol) && symbol.Type == SymbolType.Variable && _locals.TryGetValue(symbol, out var local)) + if (_table.Defined(declare.Text, out var symbol) && symbol.Type == SymbolType.Variable && _locals.TryGetValue(symbol, out var local)) { emit.Call(TsTypes.Empty) .StLocal(local); @@ -1704,7 +1704,7 @@ public void Visit(EndToken endToken) public void Visit(EnumNode enumNode) { - var name = $"{_namespace}.{enumNode.Value}".TrimStart('.'); + var name = $"{_namespace}.{enumNode.Text}".TrimStart('.'); var type = _module.DefineEnum(name, TypeAttributes.Public, typeof(long)); long current = 0; @@ -1718,10 +1718,10 @@ public void Visit(EnumNode enumNode) _errors.Add(new InvalidSymbolException($"Enum value must be equal to an integer constant {expr.Position}.")); } else if (expr.Type != SyntaxType.Declare) - _errors.Add(new CompileException($"Encountered error while compiling enum {enumNode.Value} {expr.Position}.")); + _errors.Add(new CompileException($"Encountered error while compiling enum {enumNode.Text} {expr.Position}.")); - _enums[name, expr.Value] = current; - type.DefineLiteral(expr.Value, current++); + _enums[name, expr.Text] = current; + type.DefineLiteral(expr.Text, current++); } type.CreateType(); @@ -1744,7 +1744,7 @@ public void Visit(EqualityNode equality) right = typeof(float); } - TestEquality(equality.Value, left, right, equality.Position); + TestEquality(equality.Text, left, right, equality.Position); } private void TestEquality(string op, Type left, Type right, TokenPosition pos) @@ -1855,13 +1855,14 @@ public void Visit(FunctionCallNode functionCall) { //explicit namespace -> function call //e.g. name.space.func_name(); - name = ((ISyntaxToken)nameElem).Text; + name = nameElem.Text; } else { //instance script call //e.g. inst.script_name(); - name = (memberAccess.Right as ISyntaxToken)?.Text; + //name = (memberAccess.Right as ISyntaxToken)?.Text; + name = (memberAccess.Right as VariableToken)?.Text; if (name == null) { _errors.Add(new CompileException($"Invalid id for script/event {memberAccess.Right.Position}")); @@ -2192,7 +2193,7 @@ public void Visit(LogicalNode logical) CallInstanceMethod(TsTypes.ObjectCasts[typeof(bool)], logical.Left.Position); else if (left != typeof(bool)) _errors.Add(new CompileException($"Encountered invalid syntax {logical.Left.Position}")); - if (logical.Value == "&&") + if (logical.Text == "&&") { emit.Dup() .BrFalse(end) @@ -2365,7 +2366,7 @@ public void Visit(MultiplicativeNode multiplicative) { if (right == typeof(float)) { - switch (multiplicative.Value) + switch (multiplicative.Text) { case "*": emit.Mul(); @@ -2379,30 +2380,30 @@ public void Visit(MultiplicativeNode multiplicative) } } else if (right == typeof(string)) - _errors.Add(new CompileException($"Cannot {multiplicative.Value} types {left} and {right} {multiplicative.Position}")); + _errors.Add(new CompileException($"Cannot {multiplicative.Text} types {left} and {right} {multiplicative.Position}")); else if (right == typeof(TsObject)) - emit.Call(GetOperator(multiplicative.Value, left, right, multiplicative.Position)); + emit.Call(GetOperator(multiplicative.Text, left, right, multiplicative.Position)); else - _errors.Add(new CompileException($"Cannot {multiplicative.Value} types {left} and {right} {multiplicative.Position}")); + _errors.Add(new CompileException($"Cannot {multiplicative.Text} types {left} and {right} {multiplicative.Position}")); } else if (left == typeof(string)) { - _errors.Add(new CompileException($"Cannot {multiplicative.Value} types {left} and {right} {multiplicative.Position}")); + _errors.Add(new CompileException($"Cannot {multiplicative.Text} types {left} and {right} {multiplicative.Position}")); } else if (left == typeof(TsObject)) - emit.Call(GetOperator(multiplicative.Value, left, right, multiplicative.Position)); + emit.Call(GetOperator(multiplicative.Text, left, right, multiplicative.Position)); } public void Visit(NamespaceNode namespaceNode) { var parent = _namespace; if (parent == "") - _namespace = namespaceNode.Value; + _namespace = namespaceNode.Text; else - _namespace += "." + namespaceNode.Value; - _table.EnterNamespace(namespaceNode.Value); + _namespace += "." + namespaceNode.Text; + _table.EnterNamespace(namespaceNode.Text); var temp = _table; _table = CopyTable(_table); - temp.ExitNamespace(namespaceNode.Value); + temp.ExitNamespace(namespaceNode.Text); CopyTable(temp, _table, namespaceNode.Position); AcceptDeclarations(namespaceNode); _namespace = parent; @@ -2411,11 +2412,11 @@ public void Visit(NamespaceNode namespaceNode) public void Visit(NewNode newNode) { - if(_table.Defined(newNode.Value, out var symbol)) + if(_table.Defined(newNode.Text, out var symbol)) { if(symbol.Type == SymbolType.Object) { - var name = newNode.Value; + var name = newNode.Text; var pos = newNode.Position; MarkSequencePoint(newNode); var ctor = typeof(TsInstance).GetConstructor(new[] { typeof(string), typeof(TsObject[]) }); @@ -2453,24 +2454,24 @@ public void Visit(NewNode newNode) } else { - _errors.Add(new CompileException($"Tried to create an instance of something that wasn't an object: {newNode.Value} {newNode.Position}")); + _errors.Add(new CompileException($"Tried to create an instance of something that wasn't an object: {newNode.Text} {newNode.Position}")); emit.Call(TsTypes.Empty); } } else { - _errors.Add(new CompileException($"Tried to create an instance of a type that doesn't exist: {newNode.Value} {newNode.Position}")); + _errors.Add(new CompileException($"Tried to create an instance of a type that doesn't exist: {newNode.Text} {newNode.Position}")); emit.Call(TsTypes.Empty); } } public void Visit(ObjectNode objectNode) { - var name = $"{_namespace}.{objectNode.Value}"; + var name = $"{_namespace}.{objectNode.Text}"; if (name.StartsWith(".")) name = name.TrimStart('.'); var type = _module.DefineType(name, TypeAttributes.Public); - _table.Enter(objectNode.Value); + _table.Enter(objectNode.Text); var parentNode = objectNode.Inherits as IConstantToken; if (parentNode == null) _errors.Add(new CompileException($"Invalid syntax detected {objectNode.Inherits.Position}")); @@ -2510,11 +2511,11 @@ public void Visit(ObjectNode objectNode) for(var i = 1; i < objectNode.Children.Count; i++) { var script = (ScriptNode)objectNode.Children[i]; - var method = type.DefineMethod(script.Value, MethodAttributes.Public | MethodAttributes.Static, typeof(TsObject), input); - ScriptStart(script.Value, method, input); + var method = type.DefineMethod(script.Text, MethodAttributes.Public | MethodAttributes.Static, typeof(TsObject), input); + ScriptStart(script.Text, method, input); emit.Call(eventType) - .LdStr(script.Value) + .LdStr(script.Text) .Call(push); ProcessScriptArguments(script); @@ -2536,11 +2537,11 @@ public void Visit(ObjectNode objectNode) init.Dup(); init.LdStr(name) - .LdStr(script.Value) + .LdStr(script.Text) .LdNull() .LdFtn(method) .New(typeof(TsScript).GetConstructor(new[] { typeof(object), typeof(IntPtr) })) - .LdStr(script.Value) + .LdStr(script.Text) .New(typeof(TsDelegate).GetConstructor(new[] { typeof(TsScript), typeof(string) })) .Call(addMethod); } @@ -2564,7 +2565,7 @@ public void Visit(PostfixNode postfix) .LdObj(typeof(TsObject)) .StLocal(secret) .LdObj(typeof(TsObject)) - .Call(GetOperator(postfix.Value, typeof(TsObject), postfix.Position)) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) .StObj(typeof(TsObject)) .LdLocal(secret); } @@ -2574,7 +2575,7 @@ public void Visit(PostfixNode postfix) emit.Call(typeof(List).GetMethod("get_Item")) .StLocal(secret) .LdLocal(secret) - .Call(GetOperator(postfix.Value, typeof(TsObject), postfix.Position)) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) .Call(typeof(List).GetMethod("set_Item")) .LdLocal(secret); } @@ -2584,7 +2585,7 @@ public void Visit(PostfixNode postfix) emit.Call(typeof(Grid).GetMethod("get_Item")) .StLocal(secret) .LdLocal(secret) - .Call(GetOperator(postfix.Value, typeof(TsObject), postfix.Position)) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) .Call(typeof(Grid).GetMethod("set_Item")) .LdLocal(secret); } @@ -2594,7 +2595,7 @@ public void Visit(PostfixNode postfix) emit.Call(typeof(Dictionary).GetMethod("get_Item")) .StLocal(secret) .LdLocal(secret) - .Call(GetOperator(postfix.Value, typeof(TsObject), postfix.Position)) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) .Call(typeof(Dictionary).GetMethod("set_Item")) .LdLocal(secret); } @@ -2603,14 +2604,14 @@ public void Visit(PostfixNode postfix) if (_table.Defined(variable.Text, out var symbol)) { if (symbol.Type != SymbolType.Variable) - _errors.Add(new CompileException($"Cannot perform {postfix.Value} on an identifier that is not a variable {postfix.Position}")); + _errors.Add(new CompileException($"Cannot perform {postfix.Text} on an identifier that is not a variable {postfix.Position}")); GetAddressIfPossible(variable); emit.Dup() .Dup() .LdObj(typeof(TsObject)) .StLocal(secret) .LdObj(typeof(TsObject)) - .Call(GetOperator(postfix.Value, typeof(TsObject), postfix.Position)) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) .StObj(typeof(TsObject)) .LdLocal(secret); } @@ -2620,7 +2621,7 @@ public void Visit(PostfixNode postfix) emit.Call(typeof(TsInstance).GetMethod("GetVariable")) .StLocal(secret) .LdLocal(secret) - .Call(GetOperator(postfix.Value, typeof(TsObject), postfix.Position)) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) .Call(typeof(TsInstance).GetMethod("set_Item", new[] { typeof(string), typeof(TsObject) })) .LdLocal(secret); } @@ -2646,7 +2647,7 @@ public void Visit(PostfixNode postfix) loadTarget() .LdStr(value.Text) .LdLocal(secret) - .Call(GetOperator(postfix.Value, typeof(TsObject), postfix.Position)) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) .Call(typeof(TsInstance).GetMethod("set_Item")); } else @@ -2662,7 +2663,7 @@ public void Visit(PostfixNode postfix) .LdLocalA(target) .LdStr(value.Text) .LdLocal(secret) - .Call(GetOperator(postfix.Value, typeof(TsObject), postfix.Position)) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) .Call(typeof(TsObject).GetMethod("MemberSet", new[] { typeof(string), typeof(TsObject) })); FreeLocal(target); @@ -2687,7 +2688,7 @@ public void Visit(PrefixNode prefix) //Todo: Only load result if not parent != block //These operators need special handling - if (prefix.Value == "++" || prefix.Value == "--") + if (prefix.Text == "++" || prefix.Text == "--") { var secret = GetLocal(); if (prefix.Child.Type == SyntaxType.ArrayAccess || prefix.Child.Type == SyntaxType.ArgumentAccess) @@ -2696,7 +2697,7 @@ public void Visit(PrefixNode prefix) emit.Dup() .Dup() .LdObj(typeof(TsObject)) - .Call(GetOperator(prefix.Value, typeof(TsObject), prefix.Position)) + .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) .StObj(typeof(TsObject)) .LdObj(typeof(TsObject)); } @@ -2704,7 +2705,7 @@ public void Visit(PrefixNode prefix) { ListAccessSet(list, 2); emit.Call(typeof(List).GetMethod("get_Item")) - .Call(GetOperator(prefix.Value, typeof(TsObject), prefix.Position)) + .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) .Dup() .StLocal(secret) .Call(typeof(List).GetMethod("set_Item")) @@ -2714,7 +2715,7 @@ public void Visit(PrefixNode prefix) { GridAccessSet(grid); emit.Call(typeof(Grid).GetMethod("get_Item")) - .Call(GetOperator(prefix.Value, typeof(TsObject), prefix.Position)) + .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) .Dup() .StLocal(secret) .Call(typeof(Grid).GetMethod("set_Item")) @@ -2724,7 +2725,7 @@ public void Visit(PrefixNode prefix) { MapAccessSet(map); emit.Call(typeof(Dictionary).GetMethod("get_Item")) - .Call(GetOperator(prefix.Value, typeof(TsObject), prefix.Position)) + .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) .Dup() .StLocal(secret) .Call(typeof(Dictionary).GetMethod("set_Item")) @@ -2737,7 +2738,7 @@ public void Visit(PrefixNode prefix) if (symbol.Type != SymbolType.Variable) _errors.Add(new CompileException($"Tried to access an identifier that wasn't a variable {prefix.Child.Position}")); variable.Accept(this); - emit.Call(GetOperator(prefix.Value, typeof(TsObject), prefix.Position)) + emit.Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) .StLocal(_locals[symbol]) .LdLocal(_locals[symbol]); } @@ -2745,7 +2746,7 @@ public void Visit(PrefixNode prefix) { SelfAccessSet(variable); emit.Call(typeof(TsInstance).GetMethod("get_Item")) - .Call(GetOperator(prefix.Value, typeof(TsObject), prefix.Position)) + .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) .StLocal(secret) .LdLocal(secret) .Call(typeof(TsInstance).GetMethod("set_Item")) @@ -2769,7 +2770,7 @@ public void Visit(PrefixNode prefix) loadTarget() .LdStr(value.Text) .Call(typeof(TsInstance).GetMethod("get_Item")) - .Call(GetOperator(prefix.Value, typeof(TsObject), prefix.Position)) + .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) .StLocal(secret) .LdLocal(secret) .Call(typeof(TsInstance).GetMethod("set_Item")) @@ -2786,7 +2787,7 @@ public void Visit(PrefixNode prefix) .LdLocalA(target) .LdStr(value.Text) .Call(typeof(TsObject).GetMethod("MemberGet")) - .Call(GetOperator(prefix.Value, typeof(TsObject), prefix.Position)) + .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) .StLocal(secret) .LdLocal(secret) .Call(typeof(TsObject).GetMethod("MemberSet", new[] { typeof(string), typeof(TsObject) })) @@ -2804,10 +2805,10 @@ public void Visit(PrefixNode prefix) { prefix.Child.Accept(this); var top = emit.GetTop(); - if (prefix.Value == "-" && (top == typeof(float) || top == typeof(int) || top == typeof(bool))) + if (prefix.Text == "-" && (top == typeof(float) || top == typeof(int) || top == typeof(bool))) emit.Neg(); - else if(prefix.Value != "+") - emit.Call(GetOperator(prefix.Value, emit.GetTop(), prefix.Position)); + else if(prefix.Text != "+") + emit.Call(GetOperator(prefix.Text, emit.GetTop(), prefix.Position)); } } @@ -2896,7 +2897,7 @@ public void Visit(RelationalNode relational) { if (right == typeof(float)) { - switch (relational.Value) + switch (relational.Text) { case "<": emit.Clt(); @@ -2911,15 +2912,15 @@ public void Visit(RelationalNode relational) emit.Cge(); break; default: - _errors.Add(new CompileException($"Cannot {relational.Value} types {left} and {right} {relational.Position}")); + _errors.Add(new CompileException($"Cannot {relational.Text} types {left} and {right} {relational.Position}")); break; } } else if (right == typeof(TsObject)) - emit.Call(GetOperator(relational.Value, left, right, relational.Position)); + emit.Call(GetOperator(relational.Text, left, right, relational.Position)); } else if (left == typeof(TsObject)) - emit.Call(GetOperator(relational.Value, left, right, relational.Position)); + emit.Call(GetOperator(relational.Text, left, right, relational.Position)); else _errors.Add(new CompileException($"Invalid syntax detected {relational.Position}")); @@ -2990,7 +2991,7 @@ public void Visit(RootNode root) public void Visit(ScriptNode script) { - var name = script.Value; + var name = script.Text; var mb = StartMethod(name, _namespace); _inGlobalScript = true; ScriptStart(name, mb, new[] { typeof(TsInstance), typeof(TsObject[]) }); @@ -3116,7 +3117,7 @@ public void Visit(ShiftNode shift) { if (right == typeof(int)) { - emit.Call(GetOperator(shift.Value, left, right, shift.Position)) + emit.Call(GetOperator(shift.Text, left, right, shift.Position)) .ConvertFloat(); } else @@ -3125,7 +3126,7 @@ public void Visit(ShiftNode shift) else if (left == typeof(TsObject)) { if (right == typeof(int)) - emit.Call(GetOperator(shift.Value, left, right, shift.Position)); + emit.Call(GetOperator(shift.Text, left, right, shift.Position)); else _errors.Add(new CompileException($"Must shift by a real value {shift.Right.Position}")); } diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCompiler.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCompiler.cs index e6cb7c6..6c8120a 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCompiler.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCompiler.cs @@ -39,7 +39,7 @@ public override CompilerResult CompileProject(string projectDir) return new CompilerResult(errors); var parser = new Parser(); - ParseFilesInProjectDirectory(projectDir, parser, new HashSet()); + ParseFilesInProjectDirectory(projectDir, parser, GetExcludeSet(projectDir, config)); if(parser.Errors.Count != 0) return new CompilerResult(parser.Errors); diff --git a/TaffyScriptCompiler/Syntax/ISyntaxElement.cs b/TaffyScriptCompiler/Syntax/ISyntaxElement.cs index 9b799a6..5b725f0 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxElement.cs +++ b/TaffyScriptCompiler/Syntax/ISyntaxElement.cs @@ -11,6 +11,7 @@ public interface ISyntaxElement { ISyntaxNode Parent { get; set; } SyntaxType Type { get; } + string Text { get; } TokenPosition Position { get; } bool IsToken { get; } void Accept(ISyntaxElementVisitor visitor); diff --git a/TaffyScriptCompiler/Syntax/ISyntaxNode.cs b/TaffyScriptCompiler/Syntax/ISyntaxNode.cs index ef5093e..ee73058 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxNode.cs +++ b/TaffyScriptCompiler/Syntax/ISyntaxNode.cs @@ -9,7 +9,6 @@ namespace TaffyScriptCompiler.Syntax public interface ISyntaxNode : ISyntaxElement { // Convert this to an enum? - string Value { get; } List Children { get; } void AddChild(ISyntaxElement child); diff --git a/TaffyScriptCompiler/Syntax/ISyntaxToken.cs b/TaffyScriptCompiler/Syntax/ISyntaxToken.cs index f0176fc..be59078 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxToken.cs +++ b/TaffyScriptCompiler/Syntax/ISyntaxToken.cs @@ -8,6 +8,5 @@ namespace TaffyScriptCompiler.Syntax { public interface ISyntaxToken : ISyntaxElement { - string Text { get; } } } diff --git a/TaffyScriptCompiler/Syntax/SyntaxNode.cs b/TaffyScriptCompiler/Syntax/SyntaxNode.cs index cc4e7c7..47c6ea0 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxNode.cs +++ b/TaffyScriptCompiler/Syntax/SyntaxNode.cs @@ -9,7 +9,7 @@ namespace TaffyScriptCompiler.Syntax public abstract class SyntaxNode : ISyntaxNode { public ISyntaxNode Parent { get; set; } - public string Value { get; } = null; + public string Text { get; } = null; public List Children { get; } = new List(); public TokenPosition Position { get; } public bool IsToken => false; @@ -18,14 +18,14 @@ public abstract class SyntaxNode : ISyntaxNode public SyntaxNode(string value, TokenPosition position) { Position = position; - Value = value; + Text = value; } public abstract void Accept(ISyntaxElementVisitor visitor); public override string ToString() { - return Type + (Value == null ? "" : (": " + Value)); + return Type + (Text == null ? "" : (": " + Text)); } public void AddChild(ISyntaxElement child) From a1a4cc6432c10efa0602ea3dd0ba9bad5a422141 Mon Sep 17 00:00:00 2001 From: mystborn Date: Mon, 23 Apr 2018 01:58:16 -0600 Subject: [PATCH 03/54] Streamlined TsInstance Method Names --- TaffyScript/Collections/FastList.cs | 141 ++++++++++++++++++ TaffyScript/References.cs | 53 +++++++ TaffyScript/TaffyScript.csproj | 2 + TaffyScript/TsInstance.cs | 41 ++++- .../Backend/Compiler/MsilWeakCodeGen.cs | 6 +- TaffyScriptCompiler/Syntax/SyntaxTree.cs | 24 +++ 6 files changed, 260 insertions(+), 7 deletions(-) create mode 100644 TaffyScript/Collections/FastList.cs create mode 100644 TaffyScript/References.cs diff --git a/TaffyScript/Collections/FastList.cs b/TaffyScript/Collections/FastList.cs new file mode 100644 index 0000000..e1a28c0 --- /dev/null +++ b/TaffyScript/Collections/FastList.cs @@ -0,0 +1,141 @@ +//Inspired by the FastList class found in Nez. +//Source: https://github.com/prime31/Nez/blob/master/Nez.Portable/Utils/Collections/FastList.cs +//License: https://github.com/prime31/Nez/blob/master/LICENSE + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScript.Collections +{ + /// + /// An unordered List with O(1) removal. + /// + /// + public class FastList : IEnumerable + { + //Use fields for performance in case property calls can't be jitted away. + + /// + /// The backing array. Use to access elements. + /// + public T[] Buffer; + + /// + /// The number of elements in the list. + /// + public int Count = 0; + + /// + /// Creates a new list with the default initial capacity. + /// + public FastList() : this(5) { } + + /// + /// Creates a new list with the specified initial capacity. + /// + /// + public FastList(int capacity) + { + Buffer = new T[capacity]; + } + + /// + /// Creates a list from a collection of items. + /// + /// + public FastList(IEnumerable items) + { + Buffer = items.ToArray(); + Count = Buffer.Length; + } + + /// + /// Clears all items from the list. + /// + public void Clear() + { + Array.Clear(Buffer, 0, Count); + Count = 0; + } + + /// + /// Resets the list size to 0, without removing any items. + /// + public void Reset() + { + Count = 0; + } + + /// + /// Adds an item to the list. + /// + /// + public void Add(T item) + { + if (Count == Buffer.Length) + Array.Resize(ref Buffer, Count << 1); + Buffer[Count++] = item; + } + + /// + /// Removes an item from the list. O(n) time. + /// + /// + public void Remove(T item) + { + var comp = EqualityComparer.Default; + for (var i = 0; i < Count; ++i) + { + if (comp.Equals(Buffer[i], item)) + { + RemoveAt(i); + return; + } + } + } + + /// + /// Removes the specified index from the list. O(1) time. + /// + /// + public void RemoveAt(int index) + { + Buffer[index] = Buffer[Count - 1]; + Buffer[--Count] = default(T); + } + + /// + /// Determines if the list contains the specified item. + /// + /// + /// + public bool Contains(T item) + { + var comp = EqualityComparer.Default; + for (var i = 0; i < Count; --i) + { + if (comp.Equals(Buffer[i], item)) + return true; + } + return false; + } + + /// + /// Gets an enumerator used to iterate through the list. + /// + /// + public IEnumerator GetEnumerator() + { + for (var i = 0; i < Count; i++) + yield return Buffer[i]; + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} diff --git a/TaffyScript/References.cs b/TaffyScript/References.cs new file mode 100644 index 0000000..27a3aef --- /dev/null +++ b/TaffyScript/References.cs @@ -0,0 +1,53 @@ +#if KeepRef + +using System; +using System.Collections.Generic; +using System.Runtime; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TaffyScript.Collections; + +namespace TaffyScript +{ + public static class References + { + private static FastList> _instances = new FastList>(); + internal static FastList> Instances => _instances; + + public static void Register(TsInstance inst) + { + _instances.Add(new WeakReference(inst)); + } + + public static IEnumerator EnumerateType(string type) + { + //Enumerate backwards so that the list can safely remove. + for(var i = _instances.Count - 1; i > -1; --i) + { + if (_instances.Buffer[i].TryGetTarget(out var inst)) + { + if(inst.ObjectType == type) + yield return inst; + } + else + _instances.RemoveAt(i); + } + } + + public static IEnumerator EnumerateAll() + { + //Enumerate backwards so that the list can safely remove. + for (var i = _instances.Count - 1; i > -1; --i) + { + if (_instances.Buffer[i].TryGetTarget(out var inst)) + { + yield return inst; + } + else + _instances.RemoveAt(i); + } + } + } +} +#endif \ No newline at end of file diff --git a/TaffyScript/TaffyScript.csproj b/TaffyScript/TaffyScript.csproj index 3ac2fd2..b1232f8 100644 --- a/TaffyScript/TaffyScript.csproj +++ b/TaffyScript/TaffyScript.csproj @@ -49,11 +49,13 @@ + + diff --git a/TaffyScript/TsInstance.cs b/TaffyScript/TsInstance.cs index 4a26c9f..9f9304b 100644 --- a/TaffyScript/TsInstance.cs +++ b/TaffyScript/TsInstance.cs @@ -18,7 +18,7 @@ namespace TaffyScript /// /// Represents an instance of an object in TaffyScript. /// - public class TsInstance + public class TsInstance : ITsInstance { private const string CreateEvent = "create"; private const string DestroyEvent = "destroy"; @@ -28,11 +28,15 @@ public class TsInstance /// public event DestroyedDelegate Destroyed; +#if !KeepRef + /// /// Keeps a reference to all of the instances that currently exist, to be retrieved via their id. /// private static ClassBinder _pool = new ClassBinder(); +#endif + private Dictionary _vars = new Dictionary(); /// @@ -86,7 +90,7 @@ public class TsInstance [System.Runtime.CompilerServices.IndexerName("Item")] public TsObject this[string variableName] { - get => GetVariable(variableName); + get => GetMember(variableName); set => _vars[variableName] = value; } @@ -112,7 +116,11 @@ public TsObject this[string variableName] /// Any arguments passed to the create event. public TsInstance(string instanceType, params TsObject[] args) { +#if KeepRef + References.Register(this); +#else Id = _pool.Add(this); +#endif ObjectType = instanceType; Init(true, args); } @@ -124,7 +132,11 @@ private TsInstance(string instanceType, bool performEvent = true, params TsObjec // This decision is easily reversable if it turns out to be wrong/unneeded. // In the meantime, you can still refer to the event by it's string representation. +#if KeepRef + References.Register(this); +#else Id = _pool.Add(this); +#endif ObjectType = instanceType; Init(performEvent, args); } @@ -232,7 +244,7 @@ public bool TryGetVariable(string name, out TsObject value) /// The name of the variable /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TsObject GetVariable(string name) + public TsObject GetMember(string name) { if (TryGetVariable(name, out var result)) return result; @@ -240,6 +252,11 @@ public TsObject GetVariable(string name) throw new MissingFieldException($"Tried to access non-existant variable {name} on object of type {ObjectType}"); } + public void SetMember(string name, TsObject value) + { + _vars[name] = value; + } + /// /// Changes the type of this instance, optionally performing the destroy and create events. /// @@ -277,6 +294,12 @@ public TsInstance Copy(bool performEvents) /// public void Destroy() { +#if KeepRef + if (TryGetDelegate(DestroyEvent, out var destroy)) + destroy.Invoke(this); + Destroyed?.Invoke(this); +#else + if(_pool.Contains(Id)) { if (TryGetDelegate(DestroyEvent, out var destroy)) @@ -284,6 +307,8 @@ public void Destroy() _pool.Remove(Id); Destroyed?.Invoke(this); } + +#endif } public override string ToString() @@ -392,11 +417,13 @@ public static TsObject InstanceDestroy(TsInstance target, TsObject[] args) if (args == null || args.Length == 0) target.Destroy(); else - InstanceDestroy((int)args[0]); + args[0].GetInstance().Destroy(); return TsObject.Empty(); } +#if !KeepRef + /// /// Destroys a previously created instance. /// @@ -444,6 +471,8 @@ public static int InstanceNumber(string obj) return Instances(obj).Count(); } +#endif + /// /// Gets the object type of an instance. /// @@ -582,6 +611,8 @@ public static void VariableInstanceSet(TsInstance inst, string name, TsObject va inst._vars[name] = value; } +#if !KeepRef + /// /// Attempts to get an instance from an id /// @@ -617,6 +648,8 @@ public static IEnumerable Instances(string type) yield return new TsObject(inst.Id); } +#endif + private static TsInstance InitGlobal() { return new TsInstance(); diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index bc9469e..e145da8 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -1372,7 +1372,7 @@ private void ProcessAssignExtra(AssignNode assign) else { SelfAccessSet(variable); - emit.Call(typeof(TsInstance).GetMethod("GetVariable")); + emit.Call(typeof(TsInstance).GetMethod("GetMember")); assign.Right.Accept(this); var result = emit.GetTop(); if (result == typeof(int) || result == typeof(bool)) @@ -2618,7 +2618,7 @@ public void Visit(PostfixNode postfix) else { SelfAccessSet(variable); - emit.Call(typeof(TsInstance).GetMethod("GetVariable")) + emit.Call(typeof(TsInstance).GetMethod("GetMember")) .StLocal(secret) .LdLocal(secret) .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) @@ -3264,7 +3264,7 @@ public void Visit(VariableToken variableToken) { emit.LdArg(0) .LdStr(variableToken.Text) - .Call(typeof(TsInstance).GetMethod("GetVariable", BindingFlags.Public | BindingFlags.Instance)); + .Call(typeof(TsInstance).GetMethod("GetMember")); } } diff --git a/TaffyScriptCompiler/Syntax/SyntaxTree.cs b/TaffyScriptCompiler/Syntax/SyntaxTree.cs index f4f23bf..24b218e 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxTree.cs +++ b/TaffyScriptCompiler/Syntax/SyntaxTree.cs @@ -19,5 +19,29 @@ public SyntaxTree(SymbolTable table) Table = table; Root = new RootNode(null, null); } + + public override string ToString() + { + var sb = new StringBuilder(); + PrintElement(sb, Root, 0); + return sb.ToString(); + } + + private void PrintElement(StringBuilder sb, ISyntaxElement element, int indent) + { + sb.Append(' ', indent); + sb.Append(element.Type); + if(element.Text != null) + { + sb.Append(" : "); + sb.Append(element.Text); + } + sb.AppendLine(); + if(element is ISyntaxNode node) + { + foreach (var child in node.Children) + PrintElement(sb, child, indent + 2); + } + } } } From d0eab9eb7a6db93011c3846592014aa3470062de Mon Sep 17 00:00:00 2001 From: mystborn Date: Mon, 23 Apr 2018 16:35:57 -0600 Subject: [PATCH 04/54] Changed TsInstance to ITsInstance --- .../TestSuite/TaffyScript.Tests/TestHelper.cs | 4 +- .../Threading/TaffyScript.Threading/Locks.cs | 2 +- .../TaffyScript.Threading/Threads.cs | 4 +- TaffyScript/BaseClassLib/BaseClassLibrary.cs | 20 +-- TaffyScript/BaseClassLib/DsList.cs | 4 +- TaffyScript/InstanceEnumerator.cs | 66 ------- TaffyScript/References.cs | 24 ++- TaffyScript/TaffyScript.csproj | 3 +- TaffyScript/TsDelegate.cs | 12 +- TaffyScript/TsInstance.cs | 77 +++----- TaffyScript/TsObject.cs | 14 +- TaffyScript/VariableType.cs | 3 +- .../Backend/BaseClassLibrary.cs | 3 - .../Backend/Compiler/MsilWeakCodeGen.cs | 167 +++++++----------- .../DotNet/TaffyScriptTypes.cs | 6 +- 15 files changed, 144 insertions(+), 265 deletions(-) delete mode 100644 TaffyScript/InstanceEnumerator.cs diff --git a/Samples/TestSuite/TaffyScript.Tests/TestHelper.cs b/Samples/TestSuite/TaffyScript.Tests/TestHelper.cs index d252eb2..9d57385 100644 --- a/Samples/TestSuite/TaffyScript.Tests/TestHelper.cs +++ b/Samples/TestSuite/TaffyScript.Tests/TestHelper.cs @@ -10,7 +10,7 @@ namespace TaffyScript.Tests public static class TestHelper { [WeakMethod] - public static TsObject Try(TsInstance target, TsObject[] args) + public static TsObject Try(ITsInstance target, TsObject[] args) { var del = (TsDelegate)args[0]; TsObject[] delArgs = null; @@ -39,7 +39,7 @@ public static TsObject Try(TsInstance target, TsObject[] args) } [WeakMethod] - public static TsObject TryExpect(TsInstance target, TsObject[] args) + public static TsObject TryExpect(ITsInstance target, TsObject[] args) { var del = (TsDelegate)args[0]; TsObject[] delArgs = null; diff --git a/Samples/Threading/TaffyScript.Threading/Locks.cs b/Samples/Threading/TaffyScript.Threading/Locks.cs index db15e1e..92fd50f 100644 --- a/Samples/Threading/TaffyScript.Threading/Locks.cs +++ b/Samples/Threading/TaffyScript.Threading/Locks.cs @@ -14,7 +14,7 @@ public static void MoniterEnter(TsObject obj) } [WeakMethod] - public static TsObject MoniterTryEnter(TsInstance inst, TsObject[] args) + public static TsObject MoniterTryEnter(ITsInstance inst, TsObject[] args) { if (args.Length < 1) throw new ArgumentOutOfRangeException("args", "There must be at least one argument to call moniter_try_enter"); diff --git a/Samples/Threading/TaffyScript.Threading/Threads.cs b/Samples/Threading/TaffyScript.Threading/Threads.cs index f8a78e8..1fa88a9 100644 --- a/Samples/Threading/TaffyScript.Threading/Threads.cs +++ b/Samples/Threading/TaffyScript.Threading/Threads.cs @@ -16,7 +16,7 @@ public static class Threads private static object _key = new object(); [WeakMethod] - public static TsObject TaskStart(TsInstance inst, TsObject[] args) + public static TsObject TaskStart(ITsInstance inst, TsObject[] args) { if (args.Length == 0) throw new ArgumentOutOfRangeException("args"); @@ -44,7 +44,7 @@ public static TsObject TaskStart(TsInstance inst, TsObject[] args) } [WeakMethod] - public static TsObject ThreadFire(TsInstance inst, TsObject[] args) + public static TsObject ThreadFire(ITsInstance inst, TsObject[] args) { if (args.Length == 0) throw new ArgumentOutOfRangeException("args"); diff --git a/TaffyScript/BaseClassLib/BaseClassLibrary.cs b/TaffyScript/BaseClassLib/BaseClassLibrary.cs index 242b2e9..47fadef 100644 --- a/TaffyScript/BaseClassLib/BaseClassLibrary.cs +++ b/TaffyScript/BaseClassLib/BaseClassLibrary.cs @@ -93,7 +93,7 @@ public static TsObject ArrayCopy(TsObject dest, int destIndex, TsObject src, int /// /// [WeakMethod] - public static TsObject ArrayCreate(TsInstance target, TsObject[] args) + public static TsObject ArrayCreate(ITsInstance target, TsObject[] args) { var size = args[0].GetInt(); var value = TsObject.Empty(); @@ -154,7 +154,7 @@ public static TsObject Base64Decode(string str) } [WeakMethod] - public static TsObject Choose(TsInstance target, TsObject[] args) + public static TsObject Choose(ITsInstance target, TsObject[] args) { if (args.Length == 0) throw new ArgumentException("There must be at least one argument passed to Choose."); @@ -177,23 +177,23 @@ public static string EnvironmentGetVariable(string name) } [WeakMethod] - public static TsObject EventInherited(TsInstance inst, TsObject[] args) + public static TsObject EventInherited(ITsInstance inst, TsObject[] args) { - if (TsInstance.TryGetDelegate(inst.Parent, TsInstance.EventType.Peek(), out var ev)) + if (TsInstance.TryGetDelegate(((TsInstance)inst).Parent, TsInstance.EventType.Peek(), out var ev)) return ev.Invoke(inst, args); return TsObject.Empty(); } [WeakMethod] - public static TsObject EventPerform(TsInstance inst, TsObject[] args) + public static TsObject EventPerform(ITsInstance inst, TsObject[] args) { - if (TsInstance.TryGetDelegate(inst.ObjectType, (string)args[0], out var ev)) + if(inst.TryGetDelegate((string)args[0], out var ev)) return ev.Invoke(inst); return TsObject.Empty(); } [WeakMethod] - public static TsObject EventPerformObject(TsInstance inst, TsObject[] args) + public static TsObject EventPerformObject(ITsInstance inst, TsObject[] args) { if (TsInstance.TryGetDelegate((string)args[0], (string)args[1], out var ev)) return ev.Invoke(inst); @@ -201,7 +201,7 @@ public static TsObject EventPerformObject(TsInstance inst, TsObject[] args) } [WeakMethod] - public static TsObject Max(TsInstance target, TsObject[] args) + public static TsObject Max(ITsInstance target, TsObject[] args) { if (args.Length == 0) throw new ArgumentOutOfRangeException("args", "You must pass in at least one value to Max"); @@ -216,7 +216,7 @@ public static TsObject Max(TsInstance target, TsObject[] args) } [WeakMethod] - public static TsObject Min(TsInstance target, TsObject[] args) + public static TsObject Min(ITsInstance target, TsObject[] args) { if (args.Length == 0) throw new ArgumentOutOfRangeException("args", "You must pass in at least one value to Max"); @@ -273,7 +273,7 @@ public static float Round(float n) } [WeakMethod] - public static TsObject ScriptExecute(TsInstance target, TsObject[] args) + public static TsObject ScriptExecute(ITsInstance target, TsObject[] args) { if (args.Length < 1) throw new ArgumentException("You must pass at least a script name to script_execute."); diff --git a/TaffyScript/BaseClassLib/DsList.cs b/TaffyScript/BaseClassLib/DsList.cs index 090c65f..3caff0c 100644 --- a/TaffyScript/BaseClassLib/DsList.cs +++ b/TaffyScript/BaseClassLib/DsList.cs @@ -18,7 +18,7 @@ public static class DsList /// Adds a value to a list. /// [WeakMethod] - public static TsObject DsListAdd(TsInstance target, TsObject[] args) + public static TsObject DsListAdd(ITsInstance target, TsObject[] args) { if (args.Length < 2) throw new ArgumentNullException("When calling ds_list_add, at least 2 arguments must be provided."); @@ -159,7 +159,7 @@ public static void DsListReplace(int id, int pos, TsObject val) /// list[| 0] = "foo"; /// [WeakMethod] - public static TsObject DsListSet(TsInstance target, TsObject[] args) + public static TsObject DsListSet(ITsInstance target, TsObject[] args) { if (args.Length < 3) throw new ArgumentException("When calling ds_list_set, at least 3 arguments must be provided."); diff --git a/TaffyScript/InstanceEnumerator.cs b/TaffyScript/InstanceEnumerator.cs deleted file mode 100644 index ab17d3b..0000000 --- a/TaffyScript/InstanceEnumerator.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace TaffyScript -{ - /// - /// Enumerator used to cycle through s. - /// - public struct InstanceEnumerator : IEnumerator - { - private IEnumerator _backingEnumerator; - - object IEnumerator.Current => _backingEnumerator.Current; - - public TsObject Current => _backingEnumerator.Current; - - public InstanceEnumerator(TsObject obj) - { - if (obj.Type == VariableType.Real) - { - var val = ((TsImmutableValue)obj.Value).StrongValue; - if (val == TsObject.All) - _backingEnumerator = TsInstance.Instances().GetEnumerator(); - else - _backingEnumerator = new List() { obj }.GetEnumerator(); - } - else if (obj.Type == VariableType.String) - _backingEnumerator = TsInstance.Instances(((TsImmutableValue)obj.Value).StrongValue).GetEnumerator(); - else - throw new InvalidOperationException("Can only enumerate on a string or real"); - } - - public InstanceEnumerator(float value) - { - if (value == TsObject.All) - _backingEnumerator = TsInstance.Instances().GetEnumerator(); - else - _backingEnumerator = new List() { new TsObject(value) }.GetEnumerator(); - } - - public bool MoveNext() - { - bool result; - do - { - result = _backingEnumerator.MoveNext(); - } - while (result == true && !TsInstance.InstanceExists((int)_backingEnumerator.Current)); - return result; - } - - public void Reset() - { - _backingEnumerator.Reset(); - } - - public void Dispose() - { - _backingEnumerator.Dispose(); - } - } -} diff --git a/TaffyScript/References.cs b/TaffyScript/References.cs index 27a3aef..190fb66 100644 --- a/TaffyScript/References.cs +++ b/TaffyScript/References.cs @@ -12,15 +12,29 @@ namespace TaffyScript { public static class References { - private static FastList> _instances = new FastList>(); - internal static FastList> Instances => _instances; + private static FastList> _instances = new FastList>(); + internal static FastList> Instances => _instances; public static void Register(TsInstance inst) { - _instances.Add(new WeakReference(inst)); + var wr = new WeakReference(inst); + inst.Destroyed += (i) => wr.SetTarget(null); + _instances.Add(wr); } - public static IEnumerator EnumerateType(string type) + public static IEnumerator GetEnumerator(TsObject val) + { + if (val.Type == VariableType.String) + return EnumerateType(val.GetStringUnchecked()); + else if (val.Type == VariableType.Instance) + return new List() { val.GetInstance() }.GetEnumerator(); + else if (val.Type == VariableType.Real && val.GetFloatUnchecked() == TsObject.All) + return EnumerateAll(); + else + throw new ArgumentException($"Could not enumerate over the value: {val}", nameof(val)); + } + + public static IEnumerator EnumerateType(string type) { //Enumerate backwards so that the list can safely remove. for(var i = _instances.Count - 1; i > -1; --i) @@ -35,7 +49,7 @@ public static IEnumerator EnumerateType(string type) } } - public static IEnumerator EnumerateAll() + public static IEnumerator EnumerateAll() { //Enumerate backwards so that the list can safely remove. for (var i = _instances.Count - 1; i > -1; --i) diff --git a/TaffyScript/TaffyScript.csproj b/TaffyScript/TaffyScript.csproj index b1232f8..35bd6d6 100644 --- a/TaffyScript/TaffyScript.csproj +++ b/TaffyScript/TaffyScript.csproj @@ -27,7 +27,7 @@ pdbonly true bin\Release\ - TRACE + TRACE;KeepRef prompt 4 bin\Release\TaffyScript.xml @@ -62,7 +62,6 @@ - diff --git a/TaffyScript/TsDelegate.cs b/TaffyScript/TsDelegate.cs index 2d2b5eb..580f280 100644 --- a/TaffyScript/TsDelegate.cs +++ b/TaffyScript/TsDelegate.cs @@ -6,7 +6,7 @@ namespace TaffyScript { - public delegate TsObject TsScript(TsInstance target, TsObject[] args); + public delegate TsObject TsScript(ITsInstance target, TsObject[] args); public enum TsScriptScope { @@ -19,7 +19,7 @@ public class TsDelegate : IEquatable { public TsScriptScope ScriptScope { get; } public TsScript Script { get; private set; } - public TsInstance Target { get; private set; } + public ITsInstance Target { get; private set; } public bool Disposed { get; private set; } = false; public string Name { get; } @@ -31,7 +31,7 @@ public TsDelegate(TsScript script, string name) Name = name; } - public TsDelegate(TsScript script, string name, TsInstance target) + public TsDelegate(TsScript script, string name, ITsInstance target) { ScriptScope = TsScriptScope.Instance; Target = target; @@ -45,7 +45,7 @@ public TsDelegate(TsScript script, string name, TsInstance target) /// /// /// - public TsDelegate(TsDelegate original, TsInstance target) + public TsDelegate(TsDelegate original, ITsInstance target) { ScriptScope = TsScriptScope.Instance; Script = original.Script; @@ -79,14 +79,14 @@ public TsObject Invoke(params TsObject[] args) return Script(Target, args); } - public TsObject Invoke(TsInstance target, params TsObject[] args) + public TsObject Invoke(ITsInstance target, params TsObject[] args) { if (target is null && ScriptScope != TsScriptScope.Global) throw new ArgumentNullException("target", "This script requires a target to invoke."); return Script(target, args); } - private void OnTargetDestroyed(TsInstance inst) + private void OnTargetDestroyed(ITsInstance inst) { Disposed = true; Target = null; diff --git a/TaffyScript/TsInstance.cs b/TaffyScript/TsInstance.cs index 9f9304b..0eb20e9 100644 --- a/TaffyScript/TsInstance.cs +++ b/TaffyScript/TsInstance.cs @@ -28,15 +28,6 @@ public class TsInstance : ITsInstance /// public event DestroyedDelegate Destroyed; -#if !KeepRef - - /// - /// Keeps a reference to all of the instances that currently exist, to be retrieved via their id. - /// - private static ClassBinder _pool = new ClassBinder(); - -#endif - private Dictionary _vars = new Dictionary(); /// @@ -116,11 +107,7 @@ public TsObject this[string variableName] /// Any arguments passed to the create event. public TsInstance(string instanceType, params TsObject[] args) { -#if KeepRef References.Register(this); -#else - Id = _pool.Add(this); -#endif ObjectType = instanceType; Init(true, args); } @@ -131,12 +118,8 @@ private TsInstance(string instanceType, bool performEvent = true, params TsObjec // However at this point in time, I've decided that it's too much of a time sink. // This decision is easily reversable if it turns out to be wrong/unneeded. // In the meantime, you can still refer to the event by it's string representation. - -#if KeepRef + References.Register(this); -#else - Id = _pool.Add(this); -#endif ObjectType = instanceType; Init(performEvent, args); } @@ -265,7 +248,7 @@ public void SetMember(string name, TsObject value) public void ChangeType(string type, bool performEvents) { if (performEvents && TryGetDelegate(DestroyEvent, out var destroy)) - destroy.Invoke(this); + destroy.Invoke(this, null); ObjectType = type; Init(performEvents); @@ -281,7 +264,7 @@ public TsInstance Copy(bool performEvents) var copy = new TsInstance(ObjectType, false); copy._vars = new Dictionary(_vars); if (performEvents && TryGetDelegate(ObjectType, out var create)) - create.Invoke(copy); + create.Invoke(copy, null); return copy; } @@ -294,21 +277,9 @@ public TsInstance Copy(bool performEvents) /// public void Destroy() { -#if KeepRef if (TryGetDelegate(DestroyEvent, out var destroy)) - destroy.Invoke(this); + destroy.Invoke(this, null); Destroyed?.Invoke(this); -#else - - if(_pool.Contains(Id)) - { - if (TryGetDelegate(DestroyEvent, out var destroy)) - destroy.Invoke(this); - _pool.Remove(Id); - Destroyed?.Invoke(this); - } - -#endif } public override string ToString() @@ -364,9 +335,9 @@ public static bool TryGetDelegate(string type, string name, out TsDelegate del) /// The name of the new type /// Determines whether or not to perform the destroy and create events when changing. [WeakMethod] - public static TsObject InstanceChange(TsInstance inst, TsObject[] args) + public static TsObject InstanceChange(ITsInstance inst, TsObject[] args) { - inst.ChangeType((string)args[0], (bool)args[1]); + ((TsInstance)inst).ChangeType((string)args[0], (bool)args[1]); return TsObject.Empty(); } @@ -375,9 +346,10 @@ public static TsObject InstanceChange(TsInstance inst, TsObject[] args) /// /// Determines whther or not to perform the create event on the copy. /// - public static float InstanceCopy(TsInstance inst, TsObject[] args) + [WeakMethod] + public static float InstanceCopy(ITsInstance inst, TsObject[] args) { - return inst.Copy((bool)args[0]).Id; + return ((TsInstance)inst).Copy((bool)args[0]).Id; } /// @@ -391,7 +363,7 @@ public static float InstanceCopy(TsInstance inst, TsObject[] args) /// /// [WeakMethod] - public static TsObject InstanceCreate(TsInstance target, TsObject[] args) + public static TsObject InstanceCreate(ITsInstance target, TsObject[] args) { TsInstance inst; if (args.Length > 1) @@ -412,7 +384,7 @@ public static TsObject InstanceCreate(TsInstance target, TsObject[] args) /// Currently executing instance if any. /// Optionally contains the id of the instance. [WeakMethod] - public static TsObject InstanceDestroy(TsInstance target, TsObject[] args) + public static TsObject InstanceDestroy(ITsInstance target, TsObject[] args) { if (args == null || args.Length == 0) target.Destroy(); @@ -478,7 +450,7 @@ public static int InstanceNumber(string obj) /// /// Instance to get the type from. /// - public static string ObjectGetName(TsInstance inst) + public static string ObjectGetName(ITsInstance inst) { return inst.ObjectType; } @@ -488,7 +460,7 @@ public static string ObjectGetName(TsInstance inst) /// /// Instance to get the parent type from. /// - public static string ObjectGetParent(TsInstance inst) + public static string ObjectGetParent(ITsInstance inst) { if (Inherits.TryGetValue(inst.ObjectType, out var parent)) return parent; @@ -566,9 +538,9 @@ public static void VariableGlobalSet(string name, TsObject value) /// The instance to check /// The name of the variable /// - public static bool VariableInstanceExists(TsInstance inst, string name) + public static bool VariableInstanceExists(ITsInstance inst, string name) { - return inst._vars.ContainsKey(name); + throw new NotImplementedException(); } /// @@ -577,12 +549,9 @@ public static bool VariableInstanceExists(TsInstance inst, string name) /// The instance to get the value from /// The name of the variable /// - public static TsObject VariableInstanceGet(TsInstance inst, string name) + public static TsObject VariableInstanceGet(ITsInstance inst, string name) { - if (inst._vars.TryGetValue(name, out var result)) - return result; - - return TsObject.Empty(); + throw new NotImplementedException(); } /// @@ -590,14 +559,15 @@ public static TsObject VariableInstanceGet(TsInstance inst, string name) /// /// The instance to get the variable names from /// - public static TsObject[] VariableInstanceGetNames(TsInstance inst) + public static TsObject[] VariableInstanceGetNames(ITsInstance inst) { - var arr = new TsObject[inst._vars.Count]; + throw new NotImplementedException(); + /*var arr = new TsObject[inst._vars.Count]; var i = 0; foreach (var key in inst._vars.Keys) arr[i++] = key; - return arr; + return arr;*/ } /// @@ -606,9 +576,10 @@ public static TsObject[] VariableInstanceGetNames(TsInstance inst) /// The instance to set the variable on /// The name of the variable /// The value to set - public static void VariableInstanceSet(TsInstance inst, string name, TsObject value) + public static void VariableInstanceSet(ITsInstance inst, string name, TsObject value) { - inst._vars[name] = value; + throw new NotImplementedException(); + //inst._vars[name] = value; } #if !KeepRef diff --git a/TaffyScript/TsObject.cs b/TaffyScript/TsObject.cs index 0d30259..e1a38c3 100644 --- a/TaffyScript/TsObject.cs +++ b/TaffyScript/TsObject.cs @@ -167,10 +167,10 @@ public TsObject(string value) /// Creates a TaffyScript object from an instances id. /// /// The instance to get the id from. - public TsObject(TsInstance instance) + public TsObject(ITsInstance instance) { - Type = VariableType.Real; - Value = new TsImmutableValue(instance.Id); + Type = VariableType.Instance; + Value = new TsImmutableValue(instance); } /// @@ -366,11 +366,9 @@ public string GetStringUnchecked() /// Gets the instance that has an id matching the value held by this object. /// /// - public TsInstance GetInstance() + public ITsInstance GetInstance() { - if (!TsInstance.TryGetInstance(GetInt(), out var inst)) - throw new InvalidInstanceException(); - return inst; + return (ITsInstance)Value.WeakValue; } /// @@ -764,7 +762,7 @@ public static explicit operator string(TsObject right) public static explicit operator TsInstance(TsObject right) { - return right.GetInstance(); + return (TsInstance)right.GetInstance(); } public static explicit operator TsDelegate(TsObject right) diff --git a/TaffyScript/VariableType.cs b/TaffyScript/VariableType.cs index 86723f4..8269bf3 100644 --- a/TaffyScript/VariableType.cs +++ b/TaffyScript/VariableType.cs @@ -13,6 +13,7 @@ public enum VariableType String, Array1, Array2, - Delegate + Delegate, + Instance } } diff --git a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs b/TaffyScriptCompiler/Backend/BaseClassLibrary.cs index 233854d..ce2b0a8 100644 --- a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs +++ b/TaffyScriptCompiler/Backend/BaseClassLibrary.cs @@ -124,9 +124,6 @@ public static string Generate() sb.AppendLine("import TsInstance.InstanceCopy(instance, array) as instance_copy"); sb.AppendLine("import TsInstance.InstanceCreate(instance, array) as instance_create"); sb.AppendLine("import TsInstance.InstanceDestroy(instance, array) as instance_destroy"); - sb.AppendLine("import TsInstance.InstanceExists(int) as instance_exists"); - sb.AppendLine("import TsInstance.InstanceFind(string, int) as instance_find"); - sb.AppendLine("import TsInstance.InstanceNumber(string) as instance_number"); sb.AppendLine("import TsObject.IsArray(object) as is_array"); sb.AppendLine("import TsObject.IsReal(object) as is_real"); diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index e145da8..8d685b4 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -29,6 +29,8 @@ internal partial class MsilWeakCodeGen : ISyntaxElementVisitor /// private const float All = -3f; + private static readonly Type[] ScriptArgs = { typeof(ITsInstance), typeof(TsObject[]) }; + #endregion #region Fields @@ -400,7 +402,7 @@ private void ReadResources(Assembly asm) var owner = external.Remove(external.LastIndexOf('.')); var methodName = external.Substring(owner.Length + 1); var type = _typeParser.GetType(owner); - var method = GetMethodToImport(type, methodName, new[] { typeof(TsInstance), typeof(TsObject[]) }); + var method = GetMethodToImport(type, methodName, ScriptArgs); var count = _table.EnterNamespace(input[0]); _table.AddLeaf(input[1], SymbolType.Script, SymbolScope.Global); _table.Exit(count); @@ -422,7 +424,7 @@ private bool IsMethodValid(MethodInfo method) return false; var args = method.GetParameters(); - if (args.Length != 2 || args[0].ParameterType != typeof(TsInstance) || args[1].ParameterType != typeof(TsObject[])) + if (args.Length != 2 || args[0].ParameterType != typeof(ITsInstance) || args[1].ParameterType != typeof(TsObject[])) return false; return true; @@ -457,7 +459,7 @@ private MethodBuilder StartMethod(string name, string ns) _errors.Add(new CompileException($"Tried to call an undefined function: {name}")); return null; } - var mb = GetBaseType(GetAssetNamespace(symbol)).DefineMethod(name, MethodAttributes.Public | MethodAttributes.Static, typeof(TsObject), new[] { typeof(TsInstance), typeof(TsObject[]) }); + var mb = GetBaseType(GetAssetNamespace(symbol)).DefineMethod(name, MethodAttributes.Public | MethodAttributes.Static, typeof(TsObject), ScriptArgs); mb.DefineParameter(1, ParameterAttributes.None, "__target_"); mb.DefineParameter(2, ParameterAttributes.None, "__args_"); _methods.Add(ns, name, mb); @@ -487,7 +489,7 @@ private TypeBuilder GetBaseType(string ns) private void GenerateWeakMethodForImport(MethodInfo method, string importName) { var mb = StartMethod(importName, _namespace); - var emit = new ILEmitter(mb, new[] { typeof(TsInstance), typeof(TsObject[]) }); + var emit = new ILEmitter(mb, ScriptArgs); var paramArray = method.GetParameters(); var paramTypes = new Type[paramArray.Length]; for (var i = 0; i < paramArray.Length; ++i) @@ -1020,6 +1022,17 @@ private string GetAssetNamespace(ISymbol symbol) return sb.ToString().TrimEnd('.'); } + private void ConvertTopToObject() + { + var top = emit.GetTop(); + if(top != typeof(TsObject)) + { + if (typeof(ITsInstance).IsAssignableFrom(top)) + top = typeof(ITsInstance); + emit.New(TsTypes.Constructors[top]); + } + } + #endregion #region Visitor @@ -1141,9 +1154,7 @@ public void Visit(ArrayLiteralNode arrayLiteral) .LdInt(i); arrayLiteral.Children[i].Accept(this); - var type = emit.GetTop(); - if (type != typeof(TsObject)) - emit.New(TsTypes.Constructors[type]); + ConvertTopToObject(); emit.StElem(typeof(TsObject)); } emit.New(TsTypes.Constructors[typeof(TsObject[])]); @@ -1161,9 +1172,7 @@ public void Visit(AssignNode assign) { GetAddressIfPossible(arg); assign.Right.Accept(this); - var top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[top]); + ConvertTopToObject(); emit.StObj(typeof(TsObject)); } else if (assign.Left is ArrayAccessNode array) @@ -1186,10 +1195,8 @@ public void Visit(AssignNode assign) } assign.Right.Accept(this); - var top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[top]); - argTypes[argTypes.Length - 1] = emit.GetTop(); + ConvertTopToObject(); + argTypes[argTypes.Length - 1] = typeof(TsObject); emit.Call(typeof(TsObject).GetMethod("ArraySet", argTypes)); } else if(assign.Left is ListAccessNode list) @@ -1197,9 +1204,7 @@ public void Visit(AssignNode assign) LoadElementAsInt(list.Left); LoadElementAsInt(list.Right); assign.Right.Accept(this); - var top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[top]); + ConvertTopToObject(); emit.Call(typeof(DsList).GetMethod("DsListSet", new[] { typeof(int), typeof(int), typeof(TsObject) })); } else if(assign.Left is GridAccessNode grid) @@ -1208,22 +1213,16 @@ public void Visit(AssignNode assign) LoadElementAsInt(grid.X); LoadElementAsInt(grid.Y); assign.Right.Accept(this); - var top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[top]); + ConvertTopToObject(); emit.Call(typeof(DsGrid).GetMethod("DsGridSet")); } else if(assign.Left is MapAccessNode map) { LoadElementAsInt(map.Left); map.Right.Accept(this); - var top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[top]); + ConvertTopToObject(); assign.Right.Accept(this); - top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[top]); + ConvertTopToObject(); emit.Call(typeof(DsMap).GetMethod("DsMapReplace")); } else if (assign.Left is VariableToken variable) @@ -1236,9 +1235,7 @@ public void Visit(AssignNode assign) _errors.Add(new CompileException($"Cannot assign to the value {symbol.Name} {variable.Position}")); assign.Right.Accept(this); - var result = emit.GetTop(); - if (result != typeof(TsObject)) - emit.New(TsTypes.Constructors[result]); + ConvertTopToObject(); emit.StLocal(_locals[symbol]); } else @@ -1246,10 +1243,8 @@ public void Visit(AssignNode assign) emit.LdArg(0) .LdStr(variable.Text); assign.Right.Accept(this); - var result = emit.GetTop(); - if (result != typeof(TsObject)) - emit.New(TsTypes.Constructors[result]); - emit.Call(typeof(TsInstance).GetMethod("set_Item", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(string), typeof(TsObject) }, null)); + ConvertTopToObject(); + emit.Call(typeof(ITsInstance).GetMethod("set_Item")); } } else if (assign.Left is MemberAccessNode member) @@ -1272,9 +1267,7 @@ public void Visit(AssignNode assign) } emit.LdStr(right.Text); assign.Right.Accept(this); - var top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[top]); + ConvertTopToObject(); emit.Call(typeof(TsInstance).GetMethod("set_Item")); } else @@ -1372,13 +1365,13 @@ private void ProcessAssignExtra(AssignNode assign) else { SelfAccessSet(variable); - emit.Call(typeof(TsInstance).GetMethod("GetMember")); + emit.Call(typeof(ITsInstance).GetMethod("get_Item")); assign.Right.Accept(this); var result = emit.GetTop(); if (result == typeof(int) || result == typeof(bool)) emit.ConvertFloat(); emit.Call(GetOperator(op, typeof(TsObject), emit.GetTop(), assign.Position)); - emit.Call(typeof(TsInstance).GetMethod("set_Item", new[] { typeof(string), typeof(TsObject) })); + emit.Call(typeof(ITsInstance).GetMethod("set_Item")); } } else if(assign.Left is MemberAccessNode member) @@ -1396,7 +1389,7 @@ private void ProcessAssignExtra(AssignNode assign) .LdStr(value.Text); loadTarget() .LdStr(value.Text) - .Call(typeof(TsInstance).GetMethod("get_Item")); + .Call(typeof(ITsInstance).GetMethod("get_Item")); assign.Right.Accept(this); var top = emit.GetTop(); @@ -1407,7 +1400,7 @@ private void ProcessAssignExtra(AssignNode assign) } emit.Call(GetOperator(op, typeof(TsObject), top, assign.Position)) - .Call(typeof(TsInstance).GetMethod("set_Item")); + .Call(typeof(ITsInstance).GetMethod("set_Item")); } else { @@ -1490,9 +1483,7 @@ private void MapAccessSet(MapAccessNode map) .StLocal(id); map.Right.Accept(this); - var top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[top]); + ConvertTopToObject(); emit.StLocal(key); emit.LdLocal(id) .LdLocal(key) @@ -1608,17 +1599,13 @@ public void Visit(ConditionalNode conditionalNode) // undefined behaviour. conditionalNode.Left.Accept(this); - top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[top]); + ConvertTopToObject(); emit.Br(brFinal) .MarkLabel(brFalse); conditionalNode.Right.Accept(this); - top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[top]); + ConvertTopToObject(); // This unbalances the execution stack. // Maunually pop the top value off the stack. @@ -1844,7 +1831,7 @@ public void Visit(ForNode forNode) public void Visit(FunctionCallNode functionCall) { //All methods callable from GML should have the same sig: - //TsObject func_name(TsInstance target, TsObject[] args); + //TsObject func_name(ITsInstance target, TsObject[] args); var nameElem = functionCall.Children[0]; string name; if (nameElem is ISyntaxToken token) @@ -1970,9 +1957,7 @@ private void LoadFunctionArguments(FunctionCallNode functionCall) .LdInt(i); functionCall.Children[i + 1].Accept(this); - var top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[top]); + ConvertTopToObject(); emit.StElem(typeof(TsObject)); } @@ -1991,8 +1976,8 @@ private void CallEvent(string name, bool loadId, FunctionCallNode functionCall, var top = emit.GetTop(); if (top == typeof(TsObject) || top == typeof(TsObject).MakePointerType()) - CallInstanceMethod(TsTypes.ObjectCasts[typeof(TsInstance)], start); - else if (top != typeof(TsInstance)) + CallInstanceMethod(TsTypes.ObjectCasts[typeof(ITsInstance)], start); + else if (!typeof(ITsInstance).IsAssignableFrom(top)) { _errors.Add(new CompileException($"Internal Compile Exception encountered {start}")); emit.Call(TsTypes.Empty); @@ -2002,14 +1987,14 @@ private void CallEvent(string name, bool loadId, FunctionCallNode functionCall, if(name == "destroy") { //Syntactic sugar for instance_destroy(inst); - emit.Call(typeof(TsInstance).GetMethod("Destroy")) + emit.Call(typeof(ITsInstance).GetMethod("Destroy")) .Call(TsTypes.Empty); } else { //The object returned by GetDelegate should already have a target. emit.LdStr(name) - .Call(typeof(TsInstance).GetMethod("GetDelegate", BindingFlags.Instance | BindingFlags.Public)); + .Call(typeof(ITsInstance).GetMethod("GetDelegate", BindingFlags.Instance | BindingFlags.Public)); LoadFunctionArguments(functionCall); emit.Call(typeof(TsDelegate).GetMethod("Invoke", new[] { typeof(TsObject[]) })); } @@ -2224,12 +2209,7 @@ public void Visit(MapAccessNode mapAccess) { LoadElementAsInt(mapAccess.Left); mapAccess.Right.Accept(this); - var top = emit.GetTop(); - if(top != typeof(TsObject)) - { - emit.New(TsTypes.Constructors[top]); - top = typeof(TsObject); - } + ConvertTopToObject(); emit.Call(typeof(DsMap).GetMethod("DsMapFindValue")); } @@ -2292,7 +2272,7 @@ public void Visit(MemberAccessNode memberAccess) return; } emit.LdStr(right.Text) - .Call(typeof(TsInstance).GetMethod("get_Item")); + .Call(typeof(ITsInstance).GetMethod("get_Item")); } else { @@ -2333,9 +2313,7 @@ public void Visit(MemberAccessNode memberAccess) emit.Call(TsTypes.Empty); return; } - emit.Call(typeof(TsObject).GetMethod("GetInstance")) - .Call(typeof(TsInstance).GetMethod("get_Id")) - .New(TsTypes.Constructors[typeof(int)]); + emit.Call(typeof(TsObject).GetMethod("GetInstance")); } else _errors.Add(new CompileException($"Invalid syntax detected {memberAccess.Position}")); @@ -2436,9 +2414,7 @@ public void Visit(NewNode newNode) .LdInt(i); newNode.Arguments[i].Accept(this); - var top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[top]); + ConvertTopToObject(); emit.StElem(typeof(TsObject)); } @@ -2450,7 +2426,7 @@ public void Visit(NewNode newNode) if (newNode.Parent.Type == SyntaxType.Block) emit.Pop(); else - emit.New(TsTypes.Constructors[typeof(TsInstance)]); + emit.New(TsTypes.Constructors[typeof(ITsInstance)]); } else { @@ -2484,9 +2460,6 @@ public void Visit(ObjectNode objectNode) _errors.Add(new CompileException($"Tried to inherit from non object identifier {objectNode.Inherits.Position}")); } - - - var input = new[] { typeof(TsInstance), typeof(TsObject[]) }; var addMethod = typeof(LookupTable).GetMethod("Add", new[] { typeof(string), typeof(string), typeof(TsDelegate) }); var eventType = typeof(TsInstance).GetMethod("get_EventType"); var push = typeof(Stack).GetMethod("Push"); @@ -2511,8 +2484,8 @@ public void Visit(ObjectNode objectNode) for(var i = 1; i < objectNode.Children.Count; i++) { var script = (ScriptNode)objectNode.Children[i]; - var method = type.DefineMethod(script.Text, MethodAttributes.Public | MethodAttributes.Static, typeof(TsObject), input); - ScriptStart(script.Text, method, input); + var method = type.DefineMethod(script.Text, MethodAttributes.Public | MethodAttributes.Static, typeof(TsObject), ScriptArgs); + ScriptStart(script.Text, method, ScriptArgs); emit.Call(eventType) .LdStr(script.Text) @@ -2618,11 +2591,11 @@ public void Visit(PostfixNode postfix) else { SelfAccessSet(variable); - emit.Call(typeof(TsInstance).GetMethod("GetMember")) + emit.Call(typeof(ITsInstance).GetMethod("GetMember")) .StLocal(secret) .LdLocal(secret) .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) - .Call(typeof(TsInstance).GetMethod("set_Item", new[] { typeof(string), typeof(TsObject) })) + .Call(typeof(ITsInstance).GetMethod("set_Item", new[] { typeof(string), typeof(TsObject) })) .LdLocal(secret); } } @@ -2641,14 +2614,14 @@ public void Visit(PostfixNode postfix) loadTarget() .LdStr(value.Text) - .Call(typeof(TsInstance).GetMethod("get_Item")) + .Call(typeof(ITsInstance).GetMethod("get_Item")) .StLocal(secret) .LdLocal(secret); loadTarget() .LdStr(value.Text) .LdLocal(secret) .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) - .Call(typeof(TsInstance).GetMethod("set_Item")); + .Call(typeof(ITsInstance).GetMethod("set_Item")); } else { @@ -2745,11 +2718,11 @@ public void Visit(PrefixNode prefix) else { SelfAccessSet(variable); - emit.Call(typeof(TsInstance).GetMethod("get_Item")) + emit.Call(typeof(ITsInstance).GetMethod("get_Item")) .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) .StLocal(secret) .LdLocal(secret) - .Call(typeof(TsInstance).GetMethod("set_Item")) + .Call(typeof(ITsInstance).GetMethod("set_Item")) .LdLocal(secret); } } @@ -2769,11 +2742,11 @@ public void Visit(PrefixNode prefix) .LdStr(value.Text); loadTarget() .LdStr(value.Text) - .Call(typeof(TsInstance).GetMethod("get_Item")) + .Call(typeof(ITsInstance).GetMethod("get_Item")) .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) .StLocal(secret) .LdLocal(secret) - .Call(typeof(TsInstance).GetMethod("set_Item")) + .Call(typeof(ITsInstance).GetMethod("set_Item")) .LdLocal(secret); } else @@ -2849,11 +2822,6 @@ public void Visit(ReadOnlyToken readOnlyToken) case "pi": emit.LdFloat((float)Math.PI); break; - case "instance_count": - emit.LdFld(typeof(TsInstance).GetField("Pool", BindingFlags.Static | BindingFlags.NonPublic)) - .Call(typeof(Dictionary).GetMethod("get_Count")) - .ConvertFloat(); - break; case "noone": emit.LdFloat(-4f); break; @@ -2968,8 +2936,7 @@ public void Visit(ReturnNode returnNode) if (!emit.TryGetTop(out var returnType)) _errors.Add(new CompileException($"Tried to return without a return value. If this is expected, use exit instead {returnNode.Position}")); - if (returnType != null && returnType != typeof(TsObject)) - emit.New(TsTypes.Constructors[returnType]); + ConvertTopToObject(); if (_inInstanceScript) { @@ -2994,7 +2961,7 @@ public void Visit(ScriptNode script) var name = script.Text; var mb = StartMethod(name, _namespace); _inGlobalScript = true; - ScriptStart(name, mb, new[] { typeof(TsInstance), typeof(TsObject[]) }); + ScriptStart(name, mb, ScriptArgs); //Process arguments ProcessScriptArguments(script); @@ -3062,9 +3029,7 @@ private void ProcessScriptArguments(ScriptNode script) .MarkLabel(lte); //Must be ConstantToken assign.Right.Accept(this); - var top = emit.GetTop(); - if (top != typeof(TsObject)) - emit.New(TsTypes.Constructors[emit.GetTop()]); + ConvertTopToObject(); emit.StLocal(_locals[symbol]) .MarkLabel(end); @@ -3264,7 +3229,7 @@ public void Visit(VariableToken variableToken) { emit.LdArg(0) .LdStr(variableToken.Text) - .Call(typeof(TsInstance).GetMethod("GetMember")); + .Call(typeof(ITsInstance).GetMethod("get_Item")); } } @@ -3297,22 +3262,22 @@ public void Visit(WithNode with) } var start = emit.DefineLabel(); var end = emit.DefineLabel(); - var gen = GetLocal(typeof(InstanceEnumerator)); - var other = GetLocal(typeof(TsInstance)); + var gen = GetLocal(typeof(IEnumerator)); + var other = GetLocal(typeof(ITsInstance)); _loopStart.Push(start); _loopEnd.Push(end); emit.Call(typeof(TsInstance).GetMethod("get_Other")) .StLocal(other) .LdArg(0) .Call(typeof(TsInstance).GetMethod("set_Other")) - .New(typeof(InstanceEnumerator).GetConstructor(new[] { top })) + .Call(typeof(References).GetMethod("GetEnumerator")) .StLocal(gen) .MarkLabel(start) .LdLocalA(gen) - .Call(typeof(InstanceEnumerator).GetMethod("MoveNext")) + .Call(typeof(IEnumerator).GetMethod("MoveNext")) .BrFalse(end) .LdLocalA(gen) - .Call(typeof(InstanceEnumerator).GetMethod("get_Current")) + .Call(typeof(IEnumerator).GetMethod("get_Current")) .StArg(0); with.Body.Accept(this); emit.MarkLabel(end) diff --git a/TaffyScriptCompiler/DotNet/TaffyScriptTypes.cs b/TaffyScriptCompiler/DotNet/TaffyScriptTypes.cs index b107980..58b278c 100644 --- a/TaffyScriptCompiler/DotNet/TaffyScriptTypes.cs +++ b/TaffyScriptCompiler/DotNet/TaffyScriptTypes.cs @@ -33,7 +33,7 @@ static TsTypes() { typeof(float), objType.GetMethod("GetFloat") }, { typeof(double), objType.GetMethod("GetDouble") }, { typeof(string), objType.GetMethod("GetString") }, - { typeof(TsInstance), objType.GetMethod("GetInstance") }, + { typeof(ITsInstance), objType.GetMethod("GetInstance") }, { typeof(TsDelegate), objType.GetMethod("GetDelegate") }, { typeof(TsObject[]), objType.GetMethod("GetArray1D") }, { typeof(TsObject[][]), objType.GetMethod("GetArray2D") } @@ -54,7 +54,7 @@ static TsTypes() { typeof(float), objType.GetConstructor(new[] { typeof(float) }) }, { typeof(double), objType.GetConstructor(new[] { typeof(double) }) }, { typeof(string), objType.GetConstructor(new[] { typeof(string) }) }, - { typeof(TsInstance), objType.GetConstructor(new[] { typeof(TsInstance) }) }, + { typeof(ITsInstance), objType.GetConstructor(new[] { typeof(ITsInstance) }) }, { typeof(TsDelegate), objType.GetConstructor(new[] { typeof(TsDelegate) }) }, { typeof(TsObject[]), objType.GetConstructor(new[] { typeof(TsObject[]) }) }, { typeof(TsObject[][]), objType.GetConstructor(new[] { typeof(TsObject[][]) }) } @@ -75,7 +75,7 @@ static TsTypes() { "float", typeof(float) }, { "double", typeof(double) }, { "string", typeof(string) }, - { "instance", typeof(TsInstance) }, + { "instance", typeof(ITsInstance) }, { "delegate", typeof(TsDelegate) }, { "array1d", typeof(TsObject[]) }, { "array2d", typeof(TsObject[][]) }, From f81a6908656511fc3a6fa091a2165a32c9cd993a Mon Sep 17 00:00:00 2001 From: mystborn Date: Mon, 23 Apr 2018 17:38:26 -0600 Subject: [PATCH 05/54] Final Commit Before Removing With --- .../TestSuite/TaffyScript.Tests/TestHelper.cs | 27 +++++++ Samples/TestSuite/Tests/build.cfg | 2 +- Samples/TestSuite/Tests/tests.tfs | 21 +++++ Samples/TestSuite/Tests/time_tests.tfs | 20 +++++ .../TestSuite/UnitTestLib/test_imports.tfs | 6 ++ Samples/TestSuite/UnitTestLib/unit_test.tfs | 3 - TaffyScript/References.cs | 2 +- TaffyScript/TaffyScript.csproj | 2 +- TaffyScript/TsInstance.cs | 81 ++++--------------- .../Backend/Compiler/MsilWeakCodeGen.cs | 5 +- 10 files changed, 95 insertions(+), 74 deletions(-) create mode 100644 Samples/TestSuite/Tests/time_tests.tfs create mode 100644 Samples/TestSuite/UnitTestLib/test_imports.tfs diff --git a/Samples/TestSuite/TaffyScript.Tests/TestHelper.cs b/Samples/TestSuite/TaffyScript.Tests/TestHelper.cs index 9d57385..06c64bd 100644 --- a/Samples/TestSuite/TaffyScript.Tests/TestHelper.cs +++ b/Samples/TestSuite/TaffyScript.Tests/TestHelper.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -60,5 +61,31 @@ public static TsObject TryExpect(ITsInstance target, TsObject[] args) return false; } + + [WeakMethod] + public static TsObject TimeInvoke(ITsInstance target, TsObject[] args) + { + var del = (TsDelegate)args[0]; + TsObject[] delArgs = null; + if(args.Length > 1) + { + delArgs = new TsObject[args.Length - 1]; + Array.Copy(args, 1, delArgs, 0, delArgs.Length); + } + + var timer = new Stopwatch(); + timer.Start(); + del.Invoke(delArgs); + timer.Stop(); + var result = new TsInstance("obj_timer_result"); + result["ms"] = timer.ElapsedMilliseconds; + result["ticks"] = timer.ElapsedTicks; + return result; + } + + public static void CollectGarbage() + { + GC.Collect(); + } } } diff --git a/Samples/TestSuite/Tests/build.cfg b/Samples/TestSuite/Tests/build.cfg index d8fc1f2..abfabca 100644 --- a/Samples/TestSuite/Tests/build.cfg +++ b/Samples/TestSuite/Tests/build.cfg @@ -10,6 +10,6 @@ struct.tfs object_import - LanguageTests.main + LanguageTests.timer_entry Debug \ No newline at end of file diff --git a/Samples/TestSuite/Tests/tests.tfs b/Samples/TestSuite/Tests/tests.tfs index 8ac7bb3..5de3643 100644 --- a/Samples/TestSuite/Tests/tests.tfs +++ b/Samples/TestSuite/Tests/tests.tfs @@ -19,6 +19,27 @@ namespace LanguageTests { run_ternary_tests(); } + script timer_entry { + var time_result = time_invoke(scr_object_cycle, 100000); + show_debug_message("Object Cycle:"); + show_debug_message(" Milliseconds: " + string(time_result.ms)); + show_debug_message(" Ticks: " + string(time_result.ticks)); + time_result = time_invoke(gc_collect); + show_debug_message("Collect Garbage:"); + show_debug_message(" Milliseconds: " + string(time_result.ms)); + show_debug_message(" Ticks: " + string(time_result.ticks)); + time_result = time_invoke(scr_obj_create, 100000); + show_debug_message("Object Create:"); + show_debug_message(" Milliseconds: " + string(time_result.ms)); + show_debug_message(" Ticks: " + string(time_result.ticks)); + time_result = time_invoke(gc_collect); + show_debug_message("Collect Garbage:"); + show_debug_message(" Milliseconds: " + string(time_result.ms)); + show_debug_message(" Ticks: " + string(time_result.ticks)); + + + } + script array_literal() { test_it("Array Literal"); var arr = [0, 1, 6]; diff --git a/Samples/TestSuite/Tests/time_tests.tfs b/Samples/TestSuite/Tests/time_tests.tfs new file mode 100644 index 0000000..b8b5fe7 --- /dev/null +++ b/Samples/TestSuite/Tests/time_tests.tfs @@ -0,0 +1,20 @@ +using UnitTest; + +namespace LanguageTests { + script scr_object_cycle(iter) { + for(var i = 0; i < iter; i++) { + var obj = new obj_time(); + obj.destroy(); + } + } + + script scr_obj_create(iter) { + for(var i = 0; i < iter; i++) { + var obj = new obj_time(); + } + } + + object obj_time { + + } +} \ No newline at end of file diff --git a/Samples/TestSuite/UnitTestLib/test_imports.tfs b/Samples/TestSuite/UnitTestLib/test_imports.tfs new file mode 100644 index 0000000..3fe07c6 --- /dev/null +++ b/Samples/TestSuite/UnitTestLib/test_imports.tfs @@ -0,0 +1,6 @@ +namespace UnitTest { + import TestHelper.Try(instance, array) as try; + import TestHelper.TryExpect(instance, array) as try_expect; + import TestHelper.CollectGarbage() as gc_collect; + import TestHelper.TimeInvoke(instance, array) as time_invoke; +} \ No newline at end of file diff --git a/Samples/TestSuite/UnitTestLib/unit_test.tfs b/Samples/TestSuite/UnitTestLib/unit_test.tfs index ce35b8c..d5accf0 100644 --- a/Samples/TestSuite/UnitTestLib/unit_test.tfs +++ b/Samples/TestSuite/UnitTestLib/unit_test.tfs @@ -138,7 +138,4 @@ namespace UnitTest { global._unit_test.tests_failed = true; } - - import TestHelper.Try(instance, array) as try; - import TestHelper.TryExpect(instance, array) as try_expect; } \ No newline at end of file diff --git a/TaffyScript/References.cs b/TaffyScript/References.cs index 190fb66..1e84469 100644 --- a/TaffyScript/References.cs +++ b/TaffyScript/References.cs @@ -12,7 +12,7 @@ namespace TaffyScript { public static class References { - private static FastList> _instances = new FastList>(); + private static FastList> _instances = new FastList>(100000); internal static FastList> Instances => _instances; public static void Register(TsInstance inst) diff --git a/TaffyScript/TaffyScript.csproj b/TaffyScript/TaffyScript.csproj index 35bd6d6..fb49d16 100644 --- a/TaffyScript/TaffyScript.csproj +++ b/TaffyScript/TaffyScript.csproj @@ -27,7 +27,7 @@ pdbonly true bin\Release\ - TRACE;KeepRef + TRACE prompt 4 bin\Release\TaffyScript.xml diff --git a/TaffyScript/TsInstance.cs b/TaffyScript/TsInstance.cs index 0eb20e9..9a02bf1 100644 --- a/TaffyScript/TsInstance.cs +++ b/TaffyScript/TsInstance.cs @@ -107,7 +107,9 @@ public TsObject this[string variableName] /// Any arguments passed to the create event. public TsInstance(string instanceType, params TsObject[] args) { +#if KeepRef References.Register(this); +#endif ObjectType = instanceType; Init(true, args); } @@ -118,8 +120,10 @@ private TsInstance(string instanceType, bool performEvent = true, params TsObjec // However at this point in time, I've decided that it's too much of a time sink. // This decision is easily reversable if it turns out to be wrong/unneeded. // In the meantime, you can still refer to the event by it's string representation. - + +#if KeepRef References.Register(this); +#endif ObjectType = instanceType; Init(performEvent, args); } @@ -394,28 +398,7 @@ public static TsObject InstanceDestroy(ITsInstance target, TsObject[] args) return TsObject.Empty(); } -#if !KeepRef - - /// - /// Destroys a previously created instance. - /// - /// Instance id - public static void InstanceDestroy(int id) - { - if (_pool.TryGetValue(id, out var inst)) - inst.Destroy(); - } - - /// - /// Determines if an instance with the given id exists. - /// - /// Instance id - /// - public static bool InstanceExists(int id) - { - return _pool.Contains(id); - } - +#if KeepRef /// /// Finds the nth occurence of the specified instance. /// @@ -425,10 +408,11 @@ public static bool InstanceExists(int id) public static TsObject InstanceFind(string obj, int n) { var i = 0; - foreach(var inst in Instances(obj)) + var iter = References.EnumerateType(obj); + while(iter.MoveNext()) { if (i++ == n) - return inst; + return new TsObject(iter.Current); } return TsObject.NooneObject(); } @@ -440,7 +424,13 @@ public static TsObject InstanceFind(string obj, int n) /// public static int InstanceNumber(string obj) { - return Instances(obj).Count(); + var i = 0; + var iter = References.EnumerateType(obj); + while(iter.MoveNext()) + { + i++; + } + return i; } #endif @@ -582,45 +572,6 @@ public static void VariableInstanceSet(ITsInstance inst, string name, TsObject v //inst._vars[name] = value; } -#if !KeepRef - - /// - /// Attempts to get an instance from an id - /// - /// Instance id - /// If it exists, the instance with the given id - /// - public static bool TryGetInstance(int id, out TsInstance inst) - { - return _pool.TryGetValue(id, out inst); - } - - /// - /// Gets a collection of all of the current instances - /// - /// - public static IEnumerable Instances() - { - foreach (var inst in _pool) - { - yield return new TsObject(inst); - } - } - - /// - /// Gets a collection of all of the instances of a specified type. - /// - /// The type to get the instances of - /// - public static IEnumerable Instances(string type) - { - foreach (var inst in _pool) - if (inst.ObjectType == type || ObjectIsAncestor(inst.ObjectType, type)) - yield return new TsObject(inst.Id); - } - -#endif - private static TsInstance InitGlobal() { return new TsInstance(); diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index 8d685b4..bd1910a 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -3248,6 +3248,7 @@ public void Visit(WhileNode whileNode) public void Visit(WithNode with) { + throw new NotImplementedException();/* with.Condition.Accept(this); var top = emit.GetTop(); if(top == typeof(int) || top == typeof(bool)) @@ -3287,9 +3288,7 @@ public void Visit(WithNode with) .Call(typeof(TsInstance).GetMethod("set_Other")); FreeLocal(other); - FreeLocal(gen); - - + FreeLocal(gen);*/ } #endregion From 96b46b537375d41479ca0440cbb1fc865b44c667 Mon Sep 17 00:00:00 2001 From: mystborn Date: Mon, 23 Apr 2018 17:56:14 -0600 Subject: [PATCH 06/54] Removed References --- TaffyScript/References.cs | 67 ---------------------------------- TaffyScript/TaffyScript.csproj | 1 - TaffyScript/TsInstance.cs | 45 +---------------------- 3 files changed, 1 insertion(+), 112 deletions(-) delete mode 100644 TaffyScript/References.cs diff --git a/TaffyScript/References.cs b/TaffyScript/References.cs deleted file mode 100644 index 1e84469..0000000 --- a/TaffyScript/References.cs +++ /dev/null @@ -1,67 +0,0 @@ -#if KeepRef - -using System; -using System.Collections.Generic; -using System.Runtime; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using TaffyScript.Collections; - -namespace TaffyScript -{ - public static class References - { - private static FastList> _instances = new FastList>(100000); - internal static FastList> Instances => _instances; - - public static void Register(TsInstance inst) - { - var wr = new WeakReference(inst); - inst.Destroyed += (i) => wr.SetTarget(null); - _instances.Add(wr); - } - - public static IEnumerator GetEnumerator(TsObject val) - { - if (val.Type == VariableType.String) - return EnumerateType(val.GetStringUnchecked()); - else if (val.Type == VariableType.Instance) - return new List() { val.GetInstance() }.GetEnumerator(); - else if (val.Type == VariableType.Real && val.GetFloatUnchecked() == TsObject.All) - return EnumerateAll(); - else - throw new ArgumentException($"Could not enumerate over the value: {val}", nameof(val)); - } - - public static IEnumerator EnumerateType(string type) - { - //Enumerate backwards so that the list can safely remove. - for(var i = _instances.Count - 1; i > -1; --i) - { - if (_instances.Buffer[i].TryGetTarget(out var inst)) - { - if(inst.ObjectType == type) - yield return inst; - } - else - _instances.RemoveAt(i); - } - } - - public static IEnumerator EnumerateAll() - { - //Enumerate backwards so that the list can safely remove. - for (var i = _instances.Count - 1; i > -1; --i) - { - if (_instances.Buffer[i].TryGetTarget(out var inst)) - { - yield return inst; - } - else - _instances.RemoveAt(i); - } - } - } -} -#endif \ No newline at end of file diff --git a/TaffyScript/TaffyScript.csproj b/TaffyScript/TaffyScript.csproj index fb49d16..1b813aa 100644 --- a/TaffyScript/TaffyScript.csproj +++ b/TaffyScript/TaffyScript.csproj @@ -55,7 +55,6 @@ - diff --git a/TaffyScript/TsInstance.cs b/TaffyScript/TsInstance.cs index 9a02bf1..58e6fa7 100644 --- a/TaffyScript/TsInstance.cs +++ b/TaffyScript/TsInstance.cs @@ -107,9 +107,6 @@ public TsObject this[string variableName] /// Any arguments passed to the create event. public TsInstance(string instanceType, params TsObject[] args) { -#if KeepRef - References.Register(this); -#endif ObjectType = instanceType; Init(true, args); } @@ -120,10 +117,7 @@ private TsInstance(string instanceType, bool performEvent = true, params TsObjec // However at this point in time, I've decided that it's too much of a time sink. // This decision is easily reversable if it turns out to be wrong/unneeded. // In the meantime, you can still refer to the event by it's string representation. - -#if KeepRef - References.Register(this); -#endif + ObjectType = instanceType; Init(performEvent, args); } @@ -398,43 +392,6 @@ public static TsObject InstanceDestroy(ITsInstance target, TsObject[] args) return TsObject.Empty(); } -#if KeepRef - /// - /// Finds the nth occurence of the specified instance. - /// - /// The object type to find - /// The index of the object - /// - public static TsObject InstanceFind(string obj, int n) - { - var i = 0; - var iter = References.EnumerateType(obj); - while(iter.MoveNext()) - { - if (i++ == n) - return new TsObject(iter.Current); - } - return TsObject.NooneObject(); - } - - /// - /// Gets the number of instances of a given type. - /// - /// The name of the object type - /// - public static int InstanceNumber(string obj) - { - var i = 0; - var iter = References.EnumerateType(obj); - while(iter.MoveNext()) - { - i++; - } - return i; - } - -#endif - /// /// Gets the object type of an instance. /// From 77c6a967dfb597016fd356b461928a519d91cf3f Mon Sep 17 00:00:00 2001 From: mystborn Date: Wed, 25 Apr 2018 21:35:36 -0700 Subject: [PATCH 07/54] Class Wrapping --- Samples/TestSuite/Tests/build.cfg | 4 +- Samples/TestSuite/Tests/object_import.tfs | 19 +- .../TestSuite/Tests/script_composition.tfs | 2 +- Samples/TestSuite/Tests/tests.tfs | 2 - TaffyScript/Collections/TsList.cs | 148 ++++ .../Exceptions/MemberAccessException.cs | 26 + TaffyScript/ITsInstance.cs | 8 + TaffyScript/TaffyScript.csproj | 3 + TaffyScript/TsInstance.cs | 13 +- TaffyScript/TsWrapper.cs | 22 + .../Backend/Compiler/MsilWeakCodeGen.cs | 761 +++++++++++++++++- TaffyScriptCompiler/Backend/ILEmitter.cs | 91 ++- TaffyScriptCompiler/DotNet/TypeParser.cs | 1 - TaffyScriptCompiler/Front End/Parser.cs | 237 +++++- TaffyScriptCompiler/Program.cs | 2 + TaffyScriptCompiler/StringUtils.cs | 37 + .../Concrete/ImportObject/ImportCasing.cs | 16 + .../Concrete/ImportObject/ImportObject.cs | 105 +++ .../ImportObject/ImportObjectConstructor.cs | 19 + .../ImportObject/ImportObjectField.cs | 28 + .../ImportObject/ImportObjectMethod.cs | 51 ++ TaffyScriptCompiler/Syntax/Concrete/With.cs | 18 - .../Syntax/ISyntaxElementVisitor.cs | 2 +- .../Syntax/SyntaxElementFactory.cs | 2 - TaffyScriptCompiler/Syntax/SyntaxType.cs | 4 + .../TaffyScriptCompiler.csproj | 7 +- 26 files changed, 1503 insertions(+), 125 deletions(-) create mode 100644 TaffyScript/Collections/TsList.cs create mode 100644 TaffyScript/Exceptions/MemberAccessException.cs create mode 100644 TaffyScript/TsWrapper.cs create mode 100644 TaffyScriptCompiler/StringUtils.cs create mode 100644 TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportCasing.cs create mode 100644 TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObject.cs create mode 100644 TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectConstructor.cs create mode 100644 TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectField.cs create mode 100644 TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectMethod.cs delete mode 100644 TaffyScriptCompiler/Syntax/Concrete/With.cs diff --git a/Samples/TestSuite/Tests/build.cfg b/Samples/TestSuite/Tests/build.cfg index abfabca..8ba3185 100644 --- a/Samples/TestSuite/Tests/build.cfg +++ b/Samples/TestSuite/Tests/build.cfg @@ -8,8 +8,8 @@ struct.tfs - object_import + - LanguageTests.timer_entry + LanguageTests.main Debug \ No newline at end of file diff --git a/Samples/TestSuite/Tests/object_import.tfs b/Samples/TestSuite/Tests/object_import.tfs index 13c806c..a5102c5 100644 --- a/Samples/TestSuite/Tests/object_import.tfs +++ b/Samples/TestSuite/Tests/object_import.tfs @@ -1,8 +1,5 @@ -// Object imports aren't implemented yed; they may never be. -// This file shows a potential implementation. -// Currently it's excluded from the build. - namespace LanguageTests { + //Explicitly import class and method. import object List as obj_list { //Import fields and properties. @@ -16,18 +13,10 @@ namespace LanguageTests { Clear() as clear; RemoveAt(int) as delete; get_Item(int) as get; - set_Item(int) as set; + set_Item(int, object) as set; Insert(int, object) as insert; - Sort() as sort; } - //Auto generate imports from class. Explicitly convert member names to specified casing. - import object(case=snake_case) Dictionary as obj_map; - - script list_add_many(list) { - for(var i = 1; i < argument_count; i++) { - list.add(argument[i]); - } - return list.count; - } + //Auto generate wrapper class. + import object(typing=strong, case=snake_case) HashSet as ds_set; } \ No newline at end of file diff --git a/Samples/TestSuite/Tests/script_composition.tfs b/Samples/TestSuite/Tests/script_composition.tfs index 61ad4e6..a0b1481 100644 --- a/Samples/TestSuite/Tests/script_composition.tfs +++ b/Samples/TestSuite/Tests/script_composition.tfs @@ -28,7 +28,7 @@ namespace LanguageTests { } event ev_comp2 { - + } event moo() { diff --git a/Samples/TestSuite/Tests/tests.tfs b/Samples/TestSuite/Tests/tests.tfs index 5de3643..0337db0 100644 --- a/Samples/TestSuite/Tests/tests.tfs +++ b/Samples/TestSuite/Tests/tests.tfs @@ -36,8 +36,6 @@ namespace LanguageTests { show_debug_message("Collect Garbage:"); show_debug_message(" Milliseconds: " + string(time_result.ms)); show_debug_message(" Ticks: " + string(time_result.ticks)); - - } script array_literal() { diff --git a/TaffyScript/Collections/TsList.cs b/TaffyScript/Collections/TsList.cs new file mode 100644 index 0000000..9bcf86f --- /dev/null +++ b/TaffyScript/Collections/TsList.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScript.Collections +{ + public class TsList : ObjectWrapper, ITsInstance + { + private List _source = new List(); + + public TsObject this[string memberName] + { + get => GetMember(memberName); + set => SetMember(memberName, value); + } + + public string ObjectType => "ds_list"; + + public event DestroyedDelegate Destroyed; + + public TsObject Call(string scriptName, params TsObject[] args) + { + switch(scriptName) + { + case "add": + if (args.Length == 1) + _source.Add(args[0]); + else + _source.AddRange(args); + break; + case "clear": + _source.Clear(); + break; + case "delete": + _source.RemoveAt((int)args[0]); + break; + case "_get": + return _source[(int)args[0]]; + case "_set": + _source[(int)args[0]] = args[1]; + break; + case "insert": + _source.Insert((int)args[0], args[1]); + break; + default: + if (Members.TryGetValue(scriptName, out var member) && member.Type == VariableType.Delegate) + return member.GetDelegateUnchecked().Invoke(args); + else + throw new MemberAccessException($"The type {ObjectType} does not define a script called {scriptName}"); + } + return TsObject.Empty(); + } + + public void Destroy() + { + Destroyed?.Invoke(this); + _source = null; + } + + public TsDelegate GetDelegate(string scriptName) + { + if (TryGetDelegate(scriptName, out var del)) + return del; + + throw new MemberAccessException($"The type {ObjectType} does not define a script called {scriptName}"); + } + + public TsObject GetMember(string name) + { + switch(name) + { + case "size": + return _source.Count; + default: + if (TryGetDelegate(name, out var del)) + return del; + + if (Members.TryGetValue(name, out var member)) + return member; + + throw new MemberAccessException($"Couldn't find member with the name {name}"); + } + } + + public void SetMember(string name, TsObject value) + { + switch(name) + { + case "size": + case "add": + case "clear": + case "delete": + case "_get": + case "_set": + case "insert": + throw new MemberAccessException($"Member {name} on type {ObjectType} is readonly"); + default: + Members[name] = value; + break; + } + } + + public bool TryGetDelegate(string scriptName, out TsDelegate del) + { + switch(scriptName) { + case "add": + del = new TsDelegate(add, "add", this); + return true; + case "clear": + del = new TsDelegate((i, a) => { _source.Clear(); return TsObject.Empty(); }, "clear", this); + return true; + case "delete": + del = new TsDelegate((i, a) => { _source.RemoveAt((int)a[0]); return TsObject.Empty(); }, "delete", this); + return true; + case "_get": + del = new TsDelegate((i, a) => _source[(int)a[0]], "_get", this); + return true; + case "_set": + del = new TsDelegate((i, a) => { _source[(int)a[0]] = a[1]; return TsObject.Empty(); }, "_set", this); + return true; + case "insert": + del = new TsDelegate((i, a) => { _source.Insert((int)a[0], a[1]); return TsObject.Empty(); }, "insert", this); + return true; + default: + if(Members.TryGetValue(scriptName, out var member) && member.Type == VariableType.Delegate) + { + del = member.GetDelegateUnchecked(); + return true; + } + del = null; + return false; + } + } + + public static TsList New(params TsObject[] args) + { + return new TsList(); + } + + public TsObject add(ITsInstance isnt, TsObject[] args) + { + _source.AddRange(args); + return TsObject.Empty(); + } + } +} diff --git a/TaffyScript/Exceptions/MemberAccessException.cs b/TaffyScript/Exceptions/MemberAccessException.cs new file mode 100644 index 0000000..56a07e1 --- /dev/null +++ b/TaffyScript/Exceptions/MemberAccessException.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScript.Exceptions +{ + public class MemberAccessException : Exception + { + public MemberAccessException() + : base() + { + } + + public MemberAccessException(string message) + : base(message) + { + } + + public MemberAccessException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/TaffyScript/ITsInstance.cs b/TaffyScript/ITsInstance.cs index a15b6b7..d9e3867 100644 --- a/TaffyScript/ITsInstance.cs +++ b/TaffyScript/ITsInstance.cs @@ -61,5 +61,13 @@ public interface ITsInstance /// The name of the delegate. /// TsDelegate GetDelegate(string delegateName); + + /// + /// Calls a script defined or assigned to the instance. + /// + /// The name of the script to call. + /// Any arguments to pass to the script. + /// Script result. + TsObject Call(string scriptName, params TsObject[] args); } } diff --git a/TaffyScript/TaffyScript.csproj b/TaffyScript/TaffyScript.csproj index 1b813aa..5b80b84 100644 --- a/TaffyScript/TaffyScript.csproj +++ b/TaffyScript/TaffyScript.csproj @@ -51,6 +51,8 @@ + + @@ -64,6 +66,7 @@ + diff --git a/TaffyScript/TsInstance.cs b/TaffyScript/TsInstance.cs index 58e6fa7..a2fe16c 100644 --- a/TaffyScript/TsInstance.cs +++ b/TaffyScript/TsInstance.cs @@ -13,7 +13,7 @@ namespace TaffyScript /// Delegate used to represent methods to be triggered when a TS instance is destroyed. /// /// The instance that was destroyed. - public delegate void DestroyedDelegate(TsInstance inst); + public delegate void DestroyedDelegate(ITsInstance inst); /// /// Represents an instance of an object in TaffyScript. @@ -197,6 +197,17 @@ public TsDelegate GetDelegate(string name) return result; } + /// + /// Calls a script defined or assigned to the instance. + /// + /// The name of the script to call. + /// Any arguments to pass to the script. + /// Script result. + public TsObject Call(string scriptName, params TsObject[] args) + { + return GetDelegate(scriptName).Invoke(args); + } + /// /// Gets the value of a variable from this instance. /// diff --git a/TaffyScript/TsWrapper.cs b/TaffyScript/TsWrapper.cs new file mode 100644 index 0000000..f7d76ec --- /dev/null +++ b/TaffyScript/TsWrapper.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScript +{ + public abstract class ObjectWrapper + { + private Dictionary _members = null; + protected Dictionary Members + { + get + { + if (_members is null) + _members = new Dictionary(); + return _members; + } + } + } +} diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index bd1910a..2552913 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -228,6 +228,7 @@ public MsilWeakCodeGen(SymbolTable table, BuildConfig config) // Initialize the basic assemblies needed to compile. _assemblyLoader.InitializeAssembly(Assembly.GetAssembly(typeof(TsObject))); _assemblyLoader.InitializeAssembly(Assembly.GetAssembly(typeof(Console))); + _assemblyLoader.InitializeAssembly(Assembly.GetAssembly(typeof(HashSet))); // Initialize all specified references. foreach (var asm in config.References.Select(s => _assemblyLoader.LoadAssembly(s))) @@ -633,7 +634,8 @@ private void InitTsMethods() SyntaxType.Import, SyntaxType.Namespace, SyntaxType.Object, - SyntaxType.Script + SyntaxType.Script, + SyntaxType.ImportObject }; var table = new LookupTable @@ -1033,6 +1035,17 @@ private void ConvertTopToObject() } } + private void ConvertTopToObject(ILEmitter emitter) + { + var top = emitter.GetTop(); + if(top != typeof(TsObject)) + { + if (typeof(ITsInstance).IsAssignableFrom(top)) + top = typeof(ITsInstance); + emitter.New(TsTypes.Constructors[top]); + } + } + #endregion #region Visitor @@ -1268,7 +1281,7 @@ public void Visit(AssignNode assign) emit.LdStr(right.Text); assign.Right.Accept(this); ConvertTopToObject(); - emit.Call(typeof(TsInstance).GetMethod("set_Item")); + emit.Call(typeof(ITsInstance).GetMethod("set_Item")); } else _errors.Add(new CompileException($"Cannot access readonly value from global {member.Right.Position}")); @@ -1993,10 +2006,9 @@ private void CallEvent(string name, bool loadId, FunctionCallNode functionCall, else { //The object returned by GetDelegate should already have a target. - emit.LdStr(name) - .Call(typeof(ITsInstance).GetMethod("GetDelegate", BindingFlags.Instance | BindingFlags.Public)); + emit.LdStr(name); LoadFunctionArguments(functionCall); - emit.Call(typeof(TsDelegate).GetMethod("Invoke", new[] { typeof(TsObject[]) })); + emit.Call(typeof(ITsInstance).GetMethod("Call")); } } @@ -3246,49 +3258,714 @@ public void Visit(WhileNode whileNode) .MarkLabel(end); } - public void Visit(WithNode with) + public void Visit(ImportObjectNode importNode) { - throw new NotImplementedException();/* - with.Condition.Accept(this); - var top = emit.GetTop(); - if(top == typeof(int) || top == typeof(bool)) + var importType = _typeParser.GetType(importNode.Text); + + if (importType.IsAbstract || importType.IsEnum || !importType.IsClass) + _errors.Add(new CompileException($"Could not import the type {importType.Name}. Imported types must be concrete and currently must be a class.")); + + var name = $"{_namespace}.{importNode.ImportName.Value}".TrimStart('.'); + Console.WriteLine(name); + var type = _module.DefineType(name, TypeAttributes.Public, importNode.WeaklyTyped ? typeof(ObjectWrapper) : typeof(Object), new[] { typeof(ITsInstance) }); + + var source = type.DefineField("_source", importType, FieldAttributes.Private); + var objectType = type.DefineProperty("ObjectType", PropertyAttributes.None, typeof(string), null); + var getObjectType = type.DefineMethod("get_ObjectType", + MethodAttributes.Public | + MethodAttributes.HideBySig | + MethodAttributes.NewSlot | + MethodAttributes.SpecialName | + MethodAttributes.Virtual | + MethodAttributes.Final, + typeof(string), + Type.EmptyTypes); + var gen = getObjectType.GetILGenerator(); + gen.Emit(OpCodes.Ldstr, name); + gen.Emit(OpCodes.Ret); + + objectType.SetGetMethod(getObjectType); + var destroyedField = type.DefineField("Destroyed", typeof(DestroyedDelegate), FieldAttributes.Private); + var destroyedEvent = type.DefineEvent("Destroyed", EventAttributes.None, typeof(DestroyedDelegate)); + var eventArgs = new[] { typeof(DestroyedDelegate) }; + + var addDestroyed = type.DefineMethod("add_Destroyed", + MethodAttributes.Public | + MethodAttributes.HideBySig | + MethodAttributes.NewSlot | + MethodAttributes.SpecialName | + MethodAttributes.Virtual | + MethodAttributes.Final, + typeof(void), + eventArgs); + + emit = new ILEmitter(addDestroyed, eventArgs); + + + emit.LdArg(0) + .Dup() + .LdFld(destroyedField) + .LdArg(1) + .Call(typeof(Delegate).GetMethod("Combine", new[] { typeof(Delegate), typeof(Delegate) })) + .CastClass(typeof(DestroyedDelegate)) + .StFld(destroyedField) + .Ret(); + + destroyedEvent.SetAddOnMethod(addDestroyed); + + var removeDestroyed = type.DefineMethod("remove_Destroyed", + MethodAttributes.Public | + MethodAttributes.HideBySig | + MethodAttributes.NewSlot | + MethodAttributes.SpecialName | + MethodAttributes.Virtual | + MethodAttributes.Final, + typeof(void), + eventArgs); + + emit = new ILEmitter(removeDestroyed, eventArgs); + emit.LdArg(0) + .Dup() + .LdFld(destroyedField) + .LdArg(1) + .Call(typeof(Delegate).GetMethod("Remove", new[] { typeof(Delegate), typeof(Delegate) })) + .CastClass(typeof(DestroyedDelegate)) + .StFld(destroyedField) + .Ret(); + + destroyedEvent.SetRemoveOnMethod(removeDestroyed); + + var methodFlags = MethodAttributes.Public | + MethodAttributes.HideBySig | + MethodAttributes.NewSlot | + MethodAttributes.Virtual | + MethodAttributes.Final; + + var weakFlags = MethodAttributes.Public | + MethodAttributes.HideBySig; + + + + var destroy = type.DefineMethod("Destroy", methodFlags); + + emit = new ILEmitter(destroy, Type.EmptyTypes); + var notNull = emit.DefineLabel(); + var end = emit.DefineLabel(); + + emit.LdArg(0) + .LdFld(destroyedField) + .Dup() + .BrTrue(notNull) + .Pop() + .Br(end) + .MarkLabel(notNull) + .PushType(destroyedField.FieldType) + .LdArg(0) + .Call(typeof(DestroyedDelegate).GetMethod("Invoke", new[] { typeof(ITsInstance) })) + .MarkLabel(end) + .LdArg(0) + .LdNull() //<- this will have to be changed when importing valuetype + .StFld(source) + .Ret(); + + var callMethod = type.DefineMethod("Call", methodFlags, typeof(TsObject), new[] { typeof(string), typeof(TsObject[]) }); + var getMemberMethod = type.DefineMethod("GetMember", methodFlags, typeof(TsObject), new[] { typeof(string) }); + var setMemberMethod = type.DefineMethod("SetMember", methodFlags, typeof(void), new[] { typeof(string), typeof(TsObject) }); + var tryGetDelegateMethod = type.DefineMethod("TryGetDelegate", methodFlags, typeof(bool), new[] { typeof(string), typeof(TsDelegate).MakeByRefType() }); + + var call = new ILEmitter(callMethod, new[] { typeof(string), typeof(TsObject[]) }); + var getm = new ILEmitter(getMemberMethod, new[] { typeof(string) }); + var setm = new ILEmitter(setMemberMethod, new[] { typeof(string), typeof(TsObject) }); + var tryd = new ILEmitter(tryGetDelegateMethod, new[] { typeof(string), typeof(TsDelegate) }); + tryGetDelegateMethod.DefineParameter(2, ParameterAttributes.Out, "del"); + var paramsAttribute = new CustomAttributeBuilder(typeof(ParamArrayAttribute).GetConstructor(Type.EmptyTypes), new object[] { }); + callMethod.DefineParameter(2, ParameterAttributes.None, "args").SetCustomAttribute(paramsAttribute); + + var writeOnly = new List(); + var readOnly = new List(); + var members = typeof(ObjectWrapper).GetMethod("get_Members", BindingFlags.NonPublic | BindingFlags.Instance); + var del = getm.DeclareLocal(typeof(TsDelegate), "del"); + + Label getError; + + if (!importNode.AutoImplement) { - emit.New(TsTypes.Constructors[typeof(int)]); - top = typeof(TsObject); + foreach(var fld in importNode.Fields) + { + var field = importType.GetMember(fld.ExternalName, MemberTypes.Field | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(); + if(field == null) + { + _errors.Add(new CompileException($"Could not find the Field or Property {fld.ExternalName} on the type {importType.Name} {fld.Position}")); + continue; + } + switch(field) + { + case FieldInfo fi: + AddFieldToTypeWrapper(fi, type, fld.ImportName, fld.Position, source, getm, setm); + break; + case PropertyInfo pi: + AddPropertyToTypeWrapper(pi, type, fld.ImportName, fld.Position, source, getm, setm, writeOnly, readOnly); + break; + } + } + + foreach(var mthd in importNode.Methods) + { + var args = new Type[mthd.ArgumentTypes.Count]; + for(var i = 0; i < args.Length; i++) + { + if (TsTypes.BasicTypes.TryGetValue(mthd.ArgumentTypes[i], out var argType)) + args[i] = argType; + else + _errors.Add(new CompileException($"Could not import the method {mthd.ExternalName} because one of the arguments was invalid {mthd.ArgumentTypes[i]} {mthd.Position}")); + } + + var method = importType.GetMethod(mthd.ExternalName, BindingFlags.Public | BindingFlags.Instance, null, args, null); + AddMethodToTypeWrapper(method, weakFlags, type, mthd.ImportName, mthd.Position, source, call, tryd, readOnly); + } + + var ctorArgNames = importNode.Constructor.ArgumentTypes; + var ctorArgs = new Type[ctorArgNames.Count]; + for (var i = 0; i < ctorArgs.Length; i++) + { + if (TsTypes.BasicTypes.TryGetValue(ctorArgNames[i], out var argType)) + ctorArgs[i] = argType; + else + _errors.Add(new CompileException($"Could not import the constructor for the type {name} because one of the arguments was invalid {ctorArgs[i]} {importNode.Constructor.Position}")); + } + + var ctor = importType.GetConstructor(ctorArgs); + if (ctor is null) + _errors.Add(new CompileException($"Could not find ctor on the type {name} with the arguments {string.Join(", ", ctorArgNames)}")); + else + AddConstructorToTypeWrapper(ctor, type, source, importNode.WeaklyTyped); } - if(top == typeof(float)) + else { - emit.New(TsTypes.Constructors[typeof(float)]); - top = typeof(TsObject); + var publicMembers = importType.GetMembers(BindingFlags.Public | BindingFlags.Instance); + Func transformName; + switch(importNode.Casing) + { + case ImportCasing.Camel: + transformName = StringUtils.ConvertToCamelCase; + break; + case ImportCasing.Pascal: + transformName = StringUtils.ConvertToPascalCase; + break; + case ImportCasing.Snake: + transformName = StringUtils.ConvertToSnakeCase; + break; + default: + transformName = (s) => s; + break; + } + bool foundIndexer = false; + bool foundConstructor = false; + Type memberType; + var validMethods = new HashSet(); + var ignoreMethods = new HashSet(); + foreach(var publicMember in publicMembers) + { + switch(publicMember) + { + case FieldInfo fi: + memberType = fi.FieldType; + if (typeof(ITsInstance).IsAssignableFrom(memberType)) + memberType = typeof(ITsInstance); + if (memberType == typeof(TsObject) || TsTypes.ObjectCasts.ContainsKey(memberType)) + AddFieldToTypeWrapper(fi, type, transformName(fi.Name), importNode.Position, source, getm, setm); + break; + case PropertyInfo pi: + memberType = pi.PropertyType; + if (typeof(ITsInstance).IsAssignableFrom(memberType)) + memberType = typeof(ITsInstance); + if (memberType == typeof(TsObject) || TsTypes.ObjectCasts.ContainsKey(memberType)) + { + if((pi.CanRead && pi.GetMethod.GetParameters().Length > 0) || + (pi.CanWrite && pi.SetMethod.GetParameters().Length > 1)) + { + if (foundIndexer) + continue; + if(pi.CanRead && IsMethodSupported(pi.GetMethod)) + { + foundIndexer = true; + AddMethodToTypeWrapper(pi.GetMethod, weakFlags, type, transformName("get"), importNode.Position, source, call, tryd, readOnly); + } + if(pi.CanWrite && IsMethodSupported(pi.SetMethod)) + { + foundIndexer = true; + AddMethodToTypeWrapper(pi.SetMethod, weakFlags, type, transformName("set"), importNode.Position, source, call, tryd, readOnly); + } + } + else + { + AddPropertyToTypeWrapper(pi, type, transformName(pi.Name), importNode.Position, source, getm, setm, writeOnly, readOnly); + } + if(pi.CanRead) + { + validMethods.Remove(pi.GetMethod); + ignoreMethods.Add(pi.GetMethod.Name); + } + if(pi.CanWrite) + { + validMethods.Remove(pi.SetMethod); + ignoreMethods.Add(pi.SetMethod.Name); + } + } + break; + case MethodInfo mi: + if (!ignoreMethods.Contains(mi.Name) && IsMethodSupported(mi)) + { + validMethods.Add(mi); + ignoreMethods.Add(mi.Name); + } + break; + case ConstructorInfo ci: + if(!foundConstructor && AreMethodParametersSupported(ci.GetParameters())) + { + AddConstructorToTypeWrapper(ci, type, source, importNode.WeaklyTyped); + foundConstructor = true; + } + break; + } + } + foreach(var mi in validMethods) + AddMethodToTypeWrapper(mi, weakFlags, type, transformName(mi.Name), importNode.Position, source, call, tryd, readOnly); + + if (!foundConstructor) + _errors.Add(new CompileException($"No valid constructor was found for the imported type {importType} {importNode.Position}")); } - var start = emit.DefineLabel(); - var end = emit.DefineLabel(); - var gen = GetLocal(typeof(IEnumerator)); - var other = GetLocal(typeof(ITsInstance)); - _loopStart.Push(start); - _loopEnd.Push(end); - emit.Call(typeof(TsInstance).GetMethod("get_Other")) - .StLocal(other) + + if (importNode.WeaklyTyped) + { + if (readOnly.Count > 0) + { + var setError = setm.DefineLabel(); + for (var i = 0; i < readOnly.Count; i++) + { + setm.LdArg(1) + .LdStr(readOnly[i]) + .Call(GetOperator("==", typeof(string), typeof(string), new TokenPosition(0, 0, 0, null))) + .BrTrue(setError); + } + setm.LdArg(0) + .Call(members) + .LdArg(1) + .LdArg(2) + .Call(typeof(Dictionary).GetMethod("set_Item")) + .Ret() + .MarkLabel(setError) + .LdStr($"Member {{0}} on type {name} is readonly") + .LdArg(1) + .Call(typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object) })) + .New(typeof(MemberAccessException).GetConstructor(new[] { typeof(string) })) + .Throw(); + } + else + { + setm.LdArg(0) + .Call(members) + .LdArg(1) + .LdArg(2) + .Call(typeof(Dictionary).GetMethod("set_Item")) + .Ret(); + } + var member = call.DeclareLocal(typeof(TsObject), "member"); + var callError = call.DefineLabel(); + call.LdArg(0) + .Call(members) + .LdArg(1) + .LdLocalA(member) + .Call(typeof(Dictionary).GetMethod("TryGetValue")) + .BrFalse(callError) + .LdLocalA(member) + .Call(typeof(TsObject).GetMethod("get_Type")) + .LdInt((int)VariableType.Delegate) + .Bne(callError) + .LdLocalA(member) + .Call(typeof(TsObject).GetMethod("GetDelegateUnchecked")) + .LdArg(2) + .Call(typeof(TsDelegate).GetMethod("Invoke", new[] { typeof(TsObject[]) })) + .Ret() + .MarkLabel(callError) + .LdStr($"The type {name} does not define a script called {{0}}") + .LdArg(1) + .Call(typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object) })) + .New(typeof(MemberAccessException).GetConstructor(new[] { typeof(string) })) + .Throw(); + + member = tryd.DeclareLocal(typeof(TsObject), "member"); + var tryFail = tryd.DefineLabel(); + tryd.LdArg(0) + .Call(members) + .LdArg(1) + .LdLocalA(member) + .Call(typeof(Dictionary).GetMethod("TryGetValue")) + .BrFalse(tryFail) + .LdLocalA(member) + .Call(typeof(TsObject).GetMethod("get_Type")) + .LdInt((int)VariableType.Delegate) + .Bne(tryFail) + .LdArg(2) + .LdLocalA(member) + .Call(typeof(TsObject).GetMethod("GetDelegateUnchecked")) + .StIndRef() + .LdBool(true) + .Ret() + .MarkLabel(tryFail) + .LdArg(2) + .LdNull() + .StIndRef() + .LdBool(false) + .Ret(); + + getError = getm.DefineLabel(); + var getMember = getm.DefineLabel(); + member = getm.DeclareLocal(typeof(TsObject), "member"); + foreach (var wo in writeOnly) + { + getm.LdArg(1) + .LdStr(wo) + .Call(GetOperator("==", typeof(string), typeof(string), new TokenPosition(0, 0, 0, null))) + .BrTrue(getError); + } + getm.LdArg(0) + .LdArg(1) + .LdLocalA(del) + .Call(tryGetDelegateMethod, 3, typeof(bool)) + .BrFalse(getMember) + .LdLocal(del) + .New(TsTypes.Constructors[typeof(TsDelegate)]) + .Ret() + .MarkLabel(getMember) + .LdArg(0) + .Call(members) + .LdArg(1) + .LdLocalA(member) + .Call(typeof(Dictionary).GetMethod("TryGetValue")) + .BrFalse(getError) + .LdLocal(member) + .Ret() + .MarkLabel(getError) + .LdStr($"Member with the name {{0}} is readonly or doesn't exist on the type {name}") + .LdArg(1) + .Call(typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object) })) + .New(typeof(MemberAccessException).GetConstructor(new[] { typeof(string) })) + .Throw(); + } + else + { + setm.LdStr($"Member {{0}} on type {name} is readonly or doesn't exist") + .LdArg(1) + .Call(typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object) })) + .New(typeof(MemberAccessException).GetConstructor(new[] { typeof(string) })) + .Throw(); + + call.LdStr($"The type {name} does not define a script called {{0}}.") + .LdArg(1) + .Call(typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object) })) + .New(typeof(MemberAccessException).GetConstructor(new[] { typeof(string) })) + .Throw(); + + tryd.LdArg(2) + .LdNull() + .StIndRef() + .LdBool(false) + .Ret(); + + getError = getm.DefineLabel(); + getm.LdArg(0) + .LdArg(1) + .LdLocalA(del) + .Call(tryGetDelegateMethod, 3, typeof(bool)) + .BrFalse(getError) + .LdLocal(del) + .New(TsTypes.Constructors[typeof(TsDelegate)]) + .Ret() + .MarkLabel(getError) + .LdStr($"Couldn't find member with the name {{0}} on the type {name}") + .LdArg(1) + .Call(typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object) })) + .New(typeof(MemberAccessException).GetConstructor(new[] { typeof(string) })) + .Throw(); + } + + var getDelegate = type.DefineMethod("GetDelegate", methodFlags, typeof(TsDelegate), new[] { typeof(string) }); + emit = new ILEmitter(getDelegate, new[] { typeof(string) }); + del = emit.DeclareLocal(typeof(TsDelegate), "del"); + getError = emit.DefineLabel(); + + emit.LdArg(0) + .LdArg(1) + .LdLocalA(del) + .Call(tryGetDelegateMethod, 3, typeof(bool)) + .BrFalse(getError) + .LdLocal(del) + .Ret() + .MarkLabel(getError) + .LdStr($"The type {name} does not define a script called {{0}}") + .LdArg(1) + .Call(typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object) })) + .New(typeof(MemberAccessException).GetConstructor(new[] { typeof(string) })) + .Throw(); + + var indexer = type.DefineProperty("Item", PropertyAttributes.None, typeof(TsObject), new[] { typeof(string) }); + var indexGet = type.DefineMethod("get_Item", + MethodAttributes.Public | + MethodAttributes.HideBySig | + MethodAttributes.NewSlot | + MethodAttributes.SpecialName | + MethodAttributes.Virtual | + MethodAttributes.Final, + typeof(TsObject), + new[] { typeof(string) }); + emit = new ILEmitter(indexGet, new[] { typeof(string) }); + emit.LdArg(0) + .LdArg(1) + .Call(getMemberMethod, 2, typeof(TsObject)) + .Ret(); + + indexer.SetGetMethod(indexGet); + + var indexSet = type.DefineMethod("set_Item", + MethodAttributes.Public | + MethodAttributes.HideBySig | + MethodAttributes.NewSlot | + MethodAttributes.SpecialName | + MethodAttributes.Virtual | + MethodAttributes.Final, + typeof(void), + new[] { typeof(string), typeof(TsObject) }); + emit = new ILEmitter(indexSet, new[] { typeof(string), typeof(TsObject) }); + emit.LdArg(0) + .LdArg(1) + .LdArg(2) + .Call(setMemberMethod, 3, typeof(void)) + .Ret(); + + indexer.SetSetMethod(indexSet); + var defaultMember = new CustomAttributeBuilder(typeof(DefaultMemberAttribute).GetConstructor(new[] { typeof(string) }), new[] { "Item" }); + type.SetCustomAttribute(defaultMember); + + type.CreateType(); + } + + private void AddFieldToTypeWrapper(FieldInfo field, TypeBuilder type, string importName, TokenPosition position, FieldInfo source, ILEmitter getm, ILEmitter setm) + { + var next = getm.DefineLabel(); + getm.LdArg(1) + .LdStr(importName) + .Call(GetOperator("==", typeof(string), typeof(string), position)) + .BrFalse(next) .LdArg(0) - .Call(typeof(TsInstance).GetMethod("set_Other")) - .Call(typeof(References).GetMethod("GetEnumerator")) - .StLocal(gen) - .MarkLabel(start) - .LdLocalA(gen) - .Call(typeof(IEnumerator).GetMethod("MoveNext")) - .BrFalse(end) - .LdLocalA(gen) - .Call(typeof(IEnumerator).GetMethod("get_Current")) - .StArg(0); - with.Body.Accept(this); - emit.MarkLabel(end) - .Call(typeof(TsInstance).GetMethod("get_Other")) - .StArg(0) - .LdLocal(other) - .Call(typeof(TsInstance).GetMethod("set_Other")); - - FreeLocal(other); - FreeLocal(gen);*/ + .LdFld(source) + .LdFld(field); + + ConvertTopToObject(getm); + getm.Ret() + .MarkLabel(next); + + next = setm.DefineLabel(); + setm.LdArg(1) + .LdStr(importName) + .Call(GetOperator("==", typeof(string), typeof(string), position)) + .BrFalse(next) + .LdArg(0) + .LdFld(source) + .LdArg(2) + .StFld(field) + .Ret() + .MarkLabel(next); + } + + private void AddPropertyToTypeWrapper(PropertyInfo property, + TypeBuilder type, + string importName, + TokenPosition position, + FieldInfo source, + ILEmitter getm, + ILEmitter setm, + List writeOnly, + List readOnly) + { + if (!property.CanRead) + writeOnly.Add(importName); + else + { + var next = getm.DefineLabel(); + getm.LdArg(1) + .LdStr(importName) + .Call(GetOperator("==", typeof(string), typeof(string), position)) + .BrFalse(next) + .LdArg(0) + .LdFld(source) + .Call(property.GetMethod); + ConvertTopToObject(getm); + getm.Ret() + .MarkLabel(next); + } + + if (!property.CanWrite) + readOnly.Add(importName); + else + { + var next = setm.DefineLabel(); + setm.LdArg(1) + .LdStr(importName) + .Call(GetOperator("==", typeof(string), typeof(string), position)) + .BrFalse(next) + .LdArg(0) + .LdFld(source) + .LdArg(2) + .Call(property.SetMethod) + .Ret() + .MarkLabel(next); + } + } + + private void AddMethodToTypeWrapper(MethodInfo method, + MethodAttributes weakFlags, + TypeBuilder type, + string importName, + TokenPosition methodPosition, + FieldInfo source, + ILEmitter call, + ILEmitter tryd, + List readOnly) + { + var weakMethod = type.DefineMethod(importName, weakFlags, typeof(TsObject), ScriptArgs); + var weak = new ILEmitter(weakMethod, ScriptArgs); + weak.LdArg(0) + .LdFld(source); + + var parameters = method.GetParameters(); + for (var i = 0; i < parameters.Length; i++) + { + weak.LdArg(2) + .LdInt(i); + + if (parameters[i].ParameterType == typeof(object)) + { + weak.LdElem(typeof(TsObject)) + .Box(typeof(TsObject)); + } + else if (parameters[i].ParameterType != typeof(TsObject)) + { + weak.LdElemA(typeof(TsObject)) + .Call(TsTypes.ObjectCasts[parameters[i].ParameterType]); + } + else + weak.LdElem(typeof(TsObject)); + } + + weak.Call(method); + if (method.ReturnType == typeof(void)) + weak.Call(TsTypes.Empty); + else if (TsTypes.Constructors.TryGetValue(method.ReturnType, out var objCtor)) + weak.New(objCtor); + else if (method.ReturnType != typeof(TsObject)) + _errors.Add(new CompileException($"Imported method { method.Name } had an invalid return type { method.ReturnType}.")); + weak.Ret(); + + var next = call.DefineLabel(); + call.LdArg(1) + .LdStr(importName) + .Call(GetOperator("==", typeof(string), typeof(string), methodPosition)) + .BrFalse(next) + .LdArg(0) + .LdArg(0) + .LdArg(2) + .Call(weakMethod, 3, typeof(TsObject)) + .Ret() + .MarkLabel(next); + + next = tryd.DefineLabel(); + tryd.LdArg(1) + .LdStr(importName) + .Call(GetOperator("==", typeof(string), typeof(string), methodPosition)) + .BrFalse(next) + .LdArg(2) + .LdArg(0) + .LdFtn(weakMethod) + .New(typeof(TsScript).GetConstructor(new[] { typeof(object), typeof(IntPtr) })) + .LdStr(importName) + .LdArg(0) + .New(typeof(TsDelegate).GetConstructor(new[] { typeof(TsScript), typeof(string), typeof(ITsInstance) })) + .StIndRef() + .LdBool(true) + .Ret() + .MarkLabel(next); + + readOnly.Add(importName); + } + + private void AddConstructorToTypeWrapper(ConstructorInfo ctor, TypeBuilder type, FieldInfo source, bool isWeaklyTyped) + { + var createMethod = type.DefineConstructor(MethodAttributes.Public | + MethodAttributes.HideBySig | + MethodAttributes.SpecialName | + MethodAttributes.RTSpecialName, + CallingConventions.Standard, + new[] { typeof(TsObject) }); + + emit = new ILEmitter(createMethod, new[] { typeof(TsObject[]) }); + emit.LdArg(0); + + var ctorParams = ctor.GetParameters(); + for (var i = 0; i < ctorParams.Length; i++) + { + emit.LdArg(1) + .LdInt(i); + + if (ctorParams[i].ParameterType == typeof(object)) + { + emit.LdElem(typeof(TsObject)) + .Box(typeof(TsObject)); + } + else if (ctorParams[i].ParameterType != typeof(TsObject)) + { + emit.LdElemA(typeof(TsObject)) + .Call(TsTypes.ObjectCasts[ctorParams[i].ParameterType]); + } + else + emit.LdElem(typeof(TsObject)); + } + emit.New(ctor) + .StFld(source) + .LdArg(0); + if (isWeaklyTyped) + emit.CallBase(typeof(ObjectWrapper).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null)); + else + emit.CallBase(typeof(Object).GetConstructor(Type.EmptyTypes)); + + emit.Ret(); + } + + private bool IsMethodSupported(MethodInfo method) + { + var type = method.ReturnType; + if(type != typeof(void)) + { + if (typeof(ITsInstance).IsAssignableFrom(type)) + type = typeof(ITsInstance); + if (type != typeof(TsObject) && !TsTypes.Constructors.ContainsKey(type)) + return false; + } + var parameters = method.GetParameters(); + return AreMethodParametersSupported(method.GetParameters()); + } + + private bool AreMethodParametersSupported(ParameterInfo[] parameters) + { + foreach (var parameter in parameters) + { + var type = parameter.ParameterType; + if (typeof(ITsInstance).IsAssignableFrom(type)) + type = typeof(ITsInstance); + if (type != typeof(TsObject) && !TsTypes.Constructors.ContainsKey(type)) + return false; + } + return true; } #endregion diff --git a/TaffyScriptCompiler/Backend/ILEmitter.cs b/TaffyScriptCompiler/Backend/ILEmitter.cs index fa248f9..7ac219e 100644 --- a/TaffyScriptCompiler/Backend/ILEmitter.cs +++ b/TaffyScriptCompiler/Backend/ILEmitter.cs @@ -36,7 +36,14 @@ public class ILEmitter public ILEmitter(MethodBuilder builder, Type[] input) { _generator = builder.GetILGenerator(); - _paramTypes = input; + if(builder.CallingConvention.HasFlag(CallingConventions.HasThis)) + { + _paramTypes = new Type[input.Length + 1]; + Array.Copy(input, 0, _paramTypes, 1, input.Length); + _paramTypes[0] = builder.DeclaringType; + } + else + _paramTypes = input; Method = builder; } @@ -135,6 +142,14 @@ public ILEmitter Blt(Label label) return this; } + public ILEmitter Bne(Label label) + { + _types.Pop(); + _types.Pop(); + _generator.Emit(OpCodes.Bne_Un, label); + return this; + } + public ILEmitter Box(Type valueType) { _types.Pop(); @@ -202,6 +217,26 @@ public ILEmitter Call(MethodInfo method, int input, Type output) return this; } + public ILEmitter CallBase(ConstructorInfo ctor) + { + _types.Pop(); + var length = ctor.GetParameters().Length; + for (var i = 0; i < length; i++) + _types.Pop(); + + _generator.Emit(OpCodes.Call, ctor); + + return this; + } + + public ILEmitter CastClass(Type type) + { + _types.Pop(); + _generator.Emit(OpCodes.Castclass, type); + _types.Push(type); + return this; + } + public ILEmitter Ceq() { _types.Pop(); @@ -416,16 +451,26 @@ public ILEmitter LdElemA(Type type) public ILEmitter LdFld(FieldInfo field) { - var code = field.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld; - _generator.Emit(code, field); + if (field.IsStatic) + _generator.Emit(OpCodes.Ldsfld, field); + else + { + _types.Pop(); + _generator.Emit(OpCodes.Ldfld, field); + } _types.Push(field.FieldType); return this; } public ILEmitter LdFldA(FieldInfo field) { - var code = field.IsStatic ? OpCodes.Ldsflda : OpCodes.Ldflda; - _generator.Emit(code, field); + if (field.IsStatic) + _generator.Emit(OpCodes.Ldsflda, field); + else + { + _types.Pop(); + _generator.Emit(OpCodes.Ldflda, field); + } var type = field.FieldType; if (type.IsValueType) type = type.MakePointerType(); @@ -716,6 +761,29 @@ public ILEmitter StElem(Type elementType) return this; } + public ILEmitter StFld(FieldInfo field) + { + _types.Pop(); + if (field.IsStatic) + { + _generator.Emit(OpCodes.Stsfld, field); + } + else + { + _types.Pop(); + _generator.Emit(OpCodes.Stfld, field); + } + return this; + } + + public ILEmitter StIndRef() + { + _types.Pop(); + _types.Pop(); + _generator.Emit(OpCodes.Stind_Ref); + return this; + } + public ILEmitter StLocal(LocalBuilder local) { _types.Pop(); @@ -777,6 +845,13 @@ public ILEmitter Sub() return this; } + public ILEmitter Throw() + { + _types.Pop(); + _generator.Emit(OpCodes.Throw); + return this; + } + public ILEmitter WriteLine(string value) { _generator.EmitWriteLine(value); @@ -804,6 +879,12 @@ public ILEmitter PopTop() return this; } + public ILEmitter PushType(Type type) + { + _types.Push(type); + return this; + } + public bool TryGetTop(out Type top) { top = default(Type); diff --git a/TaffyScriptCompiler/DotNet/TypeParser.cs b/TaffyScriptCompiler/DotNet/TypeParser.cs index 9fe64b2..f3f118e 100644 --- a/TaffyScriptCompiler/DotNet/TypeParser.cs +++ b/TaffyScriptCompiler/DotNet/TypeParser.cs @@ -77,7 +77,6 @@ public Type GetType(string typeName) TypeDef(type, typeName); return type; - } else throw new InvalidOperationException($"The type {typeName} could not be found."); } diff --git a/TaffyScriptCompiler/Front End/Parser.cs b/TaffyScriptCompiler/Front End/Parser.cs index 89f1d54..c84f20e 100644 --- a/TaffyScriptCompiler/Front End/Parser.cs +++ b/TaffyScriptCompiler/Front End/Parser.cs @@ -213,51 +213,186 @@ private ISyntaxElement Declaration() return node; case TokenType.Import: var import = Confirm(TokenType.Import); - node = _factory.CreateNode(SyntaxType.Import, import.Position); - var start = Confirm(TokenType.Identifier); - var baseType = new StringBuilder(start.Value); + if (Try(TokenType.Object)) + return ImportObject(import.Position); + else + return ImportScript(import.Position); + case TokenType.Script: + return Script(SymbolScope.Global); + case TokenType.SemiColon: + Confirm(TokenType.SemiColon); + return null; + default: + Throw(new InvalidTokenException(_stream.Peek(), $"Expected declaration, got {_stream.Read().Type}")); + return null; + } + } + + private ISyntaxElement ImportObject(TokenPosition pos) + { + Confirm(TokenType.Object); + List importArgs = new List(); + if(Validate(TokenType.OpenParen)) + { + if (!Try(TokenType.CloseParen)) + { do { - baseType.Append(Confirm(TokenType.Dot).Value); - baseType.Append(Confirm(TokenType.Identifier).Value); + var argName = _stream.Read(); + Confirm(TokenType.Assign); + var argValue = Confirm(TokenType.Identifier).Value; + importArgs.Add(new ObjectImportArgument(argName.Value, argValue, argName.Position)); } - while (Try(TokenType.Dot)); - node.AddChild(_factory.CreateConstant(ConstantType.String, baseType.ToString(), start.Position)); - Confirm(TokenType.OpenParen); - if(!Try(TokenType.CloseParen)) + while (Validate(TokenType.Comma)); + } + Confirm(TokenType.CloseParen); + } + var sb = new StringBuilder(); + var startPos = GetImportType(sb); + ImportObjectNode node; + if (Validate(TokenType.As)) + { + var importName = Confirm(TokenType.Identifier); + node = new ImportObjectNode((IConstantToken)_factory.CreateConstant(ConstantType.String, importName.Value, importName.Position), sb.ToString(), startPos); + } + else + node = new ImportObjectNode(sb.ToString(), startPos); + + node.ParseArguments(importArgs); + if(!Try(TokenType.OpenBrace)) + { + node.AutoImplement = true; + return node; + } + Confirm(TokenType.OpenBrace); + if(!Try(TokenType.CloseBrace)) + { + bool hasCtor = false; + do + { + if(Try(TokenType.New, out var newToken)) { - do + if (hasCtor) + Throw(new InvalidTokenException(newToken, $"Import types can only define one constructor")); + var newNode = new ImportObjectConstructor(newToken.Position); + Confirm(TokenType.OpenParen); + if (!Try(TokenType.CloseParen)) + { + do + { + var token = _stream.Read(); + var type = token.Value; + if (type == "array") + type = "array1d"; + if (!TsTypes.BasicTypes.ContainsKey(type)) + Throw(new InvalidTokenException(token, $"Import type must be one of the following: {string.Join(", ", TsTypes.BasicTypes.Keys)}\n")); + else + newNode.ArgumentTypes.Add(type); + } + while (Validate(TokenType.Comma)); + } + Confirm(TokenType.CloseParen); + node.Constructor = newNode; + } + else + { + var memberName = Confirm(TokenType.Identifier); + if (Try(TokenType.OpenParen)) + { + var methodNode = new ImportObjectMethod(memberName.Value, memberName.Position); + if (Validate(TokenType.LessThan)) + { + do + { + sb.Clear(); + pos = GetImportType(sb); + methodNode.Generics.Add((IConstantToken)_factory.CreateConstant(ConstantType.String, sb.ToString(), pos)); + } + while (Validate(TokenType.Comma)); + Confirm(TokenType.GreaterThan); + } + Confirm(TokenType.OpenParen); + if (!Try(TokenType.CloseParen)) + { + do + { + var token = _stream.Read(); + var type = token.Value; + if (type == "array") + type = "array1d"; + if (!TsTypes.BasicTypes.ContainsKey(type)) + Throw(new InvalidTokenException(token, $"Import type must be one of the following: {string.Join(", ", TsTypes.BasicTypes.Keys)}\n")); + else + methodNode.ArgumentTypes.Add(type); + } + while (Validate(TokenType.Comma)); + } + Confirm(TokenType.CloseParen); + + if (Validate(TokenType.As)) + methodNode.ImportName = Confirm(TokenType.Identifier).Value; + + node.Methods.Add(methodNode); + } + else { - token = _stream.Read(); - var type = token.Value; - if (type == "array") - type = "array1d"; - if (!TsTypes.BasicTypes.ContainsKey(type)) + if (Validate(TokenType.As)) { - Throw(new InvalidTokenException(token, $"Import type must be one of the following: {string.Join(", ", TsTypes.BasicTypes.Keys)}\n")); - node.AddChild(null); + var importName = Confirm(TokenType.Identifier).Value; + node.Fields.Add(new ImportObjectField(memberName.Value, importName, memberName.Position)); } else - node.AddChild(_factory.CreateConstant(ConstantType.String, type, token.Position)); + node.Fields.Add(new ImportObjectField(memberName.Value, memberName.Position)); } - while (Validate(TokenType.Comma)); } - Confirm(TokenType.CloseParen); - Confirm(TokenType.As); - var importName = Confirm(TokenType.Identifier); - _table.AddChild(new ImportLeaf(_table.Current, importName.Value, SymbolScope.Global, (ImportNode)node)); - //_table.AddLeaf(importName.Value, SymbolType.Script, SymbolScope.Global); - node.AddChild(_factory.CreateConstant(ConstantType.String, importName.Value, importName.Position)); - return node; - case TokenType.Script: - return Script(SymbolScope.Global); - case TokenType.SemiColon: - Confirm(TokenType.SemiColon); - return null; - default: - Throw(new InvalidTokenException(_stream.Peek(), $"Expected declaration, got {_stream.Read().Type}")); - return null; + + while (Validate(TokenType.SemiColon)) ; + } + while (!Try(TokenType.CloseBrace)); } + Confirm(TokenType.CloseBrace); + + return node; + } + + private ISyntaxElement ImportScript(TokenPosition pos) + { + var node = _factory.CreateNode(SyntaxType.Import, pos); + var start = Confirm(TokenType.Identifier); + var baseType = new StringBuilder(start.Value); + do + { + baseType.Append(Confirm(TokenType.Dot).Value); + baseType.Append(Confirm(TokenType.Identifier).Value); + } + while (Try(TokenType.Dot)); + node.AddChild(_factory.CreateConstant(ConstantType.String, baseType.ToString(), start.Position)); + Confirm(TokenType.OpenParen); + if (!Try(TokenType.CloseParen)) + { + do + { + var token = _stream.Read(); + var type = token.Value; + if (type == "array") + type = "array1d"; + if (!TsTypes.BasicTypes.ContainsKey(type)) + { + Throw(new InvalidTokenException(token, $"Import type must be one of the following: {string.Join(", ", TsTypes.BasicTypes.Keys)}\n")); + node.AddChild(null); + } + else + node.AddChild(_factory.CreateConstant(ConstantType.String, type, token.Position)); + } + while (Validate(TokenType.Comma)); + } + Confirm(TokenType.CloseParen); + Confirm(TokenType.As); + var importName = Confirm(TokenType.Identifier); + _table.AddChild(new ImportLeaf(_table.Current, importName.Value, SymbolScope.Global, (ImportNode)node)); + //_table.AddLeaf(importName.Value, SymbolType.Script, SymbolScope.Global); + node.AddChild(_factory.CreateConstant(ConstantType.String, importName.Value, importName.Position)); + return node; } private ISyntaxElement Script(SymbolScope scope) @@ -1034,6 +1169,40 @@ private ISyntaxToken Constant() return null; } + private TokenPosition GetImportType(StringBuilder sb) + { + var start = Confirm(TokenType.Identifier); + sb.Append(start.Value); + while(Validate(TokenType.Dot)) + { + sb.Append("."); + sb.Append(Confirm(TokenType.Identifier).Value); + } + if(Validate(TokenType.LessThan)) + { + sb.Append("<"); + do + { + if (Validate(TokenType.Comma)) + sb.Append(","); + GetImportType(sb); + } + while (Try(TokenType.Comma)); + + Confirm(TokenType.GreaterThan); + sb.Append(">"); + } + if(Validate(TokenType.OpenBracket)) + { + sb.Append("["); + while (Validate(TokenType.Comma)) + sb.Append(","); + Confirm(TokenType.CloseBracket); + sb.Append("]"); + } + return start.Position; + } + private bool IsAssignment() { var type = _stream.Peek().Type; diff --git a/TaffyScriptCompiler/Program.cs b/TaffyScriptCompiler/Program.cs index 1eed878..63b91cd 100644 --- a/TaffyScriptCompiler/Program.cs +++ b/TaffyScriptCompiler/Program.cs @@ -26,6 +26,8 @@ static void Main(string[] args) if (extra.Count != 0) path = extra[0]; + path = @"C:\Users\Chris\Source\Repos\GmParser\Samples\TestSuite\Tests"; + if (generateBuild) { var build = new BuildConfig(); diff --git a/TaffyScriptCompiler/StringUtils.cs b/TaffyScriptCompiler/StringUtils.cs new file mode 100644 index 0000000..d8f026c --- /dev/null +++ b/TaffyScriptCompiler/StringUtils.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScriptCompiler +{ + public static class StringUtils + { + public static string ConvertToCamelCase(string value) + { + var sb = new StringBuilder(); + var split = value.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries); + for(var i = 0; i < split.Length; i++) + { + if (i == 0) + sb.Append(char.ToLower(split[0][0])); + else + sb.Append(char.ToUpper(split[i][0])); + + sb.Append(split[0].Substring(1, split[0].Length - 1)); + } + return sb.ToString(); + } + + public static string ConvertToPascalCase(string value) + { + return value.Split(new[] { "_" }, StringSplitOptions.RemoveEmptyEntries).Select(s => char.ToUpper(s[0]) + s.Substring(1, s.Length - 1)).Aggregate(string.Empty, (s1, s2) => s1 + s2); + } + + public static string ConvertToSnakeCase(string value) + { + return string.Concat(value.Select((x, i) => i == 0 ? char.ToLower(x).ToString() : char.IsUpper(x) ? "_" + char.ToLower(x) : x.ToString())); + } + } +} diff --git a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportCasing.cs b/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportCasing.cs new file mode 100644 index 0000000..5cca909 --- /dev/null +++ b/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportCasing.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScriptCompiler.Syntax +{ + public enum ImportCasing + { + Native, + Camel, + Pascal, + Snake + } +} diff --git a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObject.cs b/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObject.cs new file mode 100644 index 0000000..e01a0f5 --- /dev/null +++ b/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObject.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; + +namespace TaffyScriptCompiler.Syntax +{ + public class ImportObjectNode : SyntaxNode + { + public override SyntaxType Type => SyntaxType.ImportObject; + public IConstantToken ImportName { get; } + public bool AutoImplement { get; set; } + public ImportCasing Casing { get; private set; } = ImportCasing.Native; + public bool WeaklyTyped { get; private set; } = true; + public List Fields { get; private set; } = new List(); + public ImportObjectConstructor Constructor { get; set; } + public List Methods { get; private set; } = new List(); + + public ImportObjectNode(string value, TokenPosition position) + : base(value, position) + { + ImportName = new ConstantToken(value, position, ConstantType.String, value); + } + + public ImportObjectNode(IConstantToken importName, string value, TokenPosition position) + : base(value, position) + { + ImportName = importName; + } + + public override void Accept(ISyntaxElementVisitor visitor) + { + visitor.Visit(this); + } + + public List ParseArguments(IEnumerable arguments) + { + var set = new HashSet(); + var errors = new List(); + foreach(var arg in arguments) + { + if (set.Contains(arg.Name)) + { + errors.Add(new InvalidOperationException($"Tried to add the same import argument multiple times {arg.Position}")); + continue; + } + + switch(arg.Name) + { + case "case": + switch(arg.Value) + { + case "pascal_case": + Casing = ImportCasing.Pascal; + break; + case "snake_case": + Casing = ImportCasing.Snake; + break; + case "camel_case": + Casing = ImportCasing.Camel; + break; + case "native_case": + Casing = ImportCasing.Native; + break; + default: + errors.Add(new ArgumentException($"Invalid case option: {arg.Value} {arg.Position}")); + break; + } + break; + case "typing": + switch(arg.Value) + { + case "weak": + WeaklyTyped = true; + break; + case "strong": + WeaklyTyped = false; + break; + default: + errors.Add(new ArgumentException($"Invalid typing option: {arg.Value} {arg.Position}")); + break; + } + break; + default: + errors.Add(new ArgumentException($"Invalid import argument: {arg.Name} {arg.Position}")); + break; + } + } + + return errors; + } + } + + public struct ObjectImportArgument + { + public string Name; + public string Value; + public TokenPosition Position; + + public ObjectImportArgument(string name, string value, TokenPosition pos) + { + Name = name; + Value = value; + Position = pos; + } + } +} diff --git a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectConstructor.cs b/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectConstructor.cs new file mode 100644 index 0000000..6265e8d --- /dev/null +++ b/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectConstructor.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScriptCompiler.Syntax +{ + public class ImportObjectConstructor + { + public List ArgumentTypes { get; } = new List(); + public TokenPosition Position { get; } + + public ImportObjectConstructor(TokenPosition position) + { + Position = position; + } + } +} diff --git a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectField.cs b/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectField.cs new file mode 100644 index 0000000..5a52c0f --- /dev/null +++ b/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectField.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScriptCompiler.Syntax +{ + public class ImportObjectField + { + public TokenPosition Position { get; } + public string ExternalName { get; } + public string ImportName { get; } + + public ImportObjectField(string name, TokenPosition position) + { + Position = position; + ImportName = ExternalName = name; + } + + public ImportObjectField(string externalName, string importName, TokenPosition position) + { + Position = position; + ExternalName = externalName; + ImportName = importName; + } + } +} diff --git a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectMethod.cs b/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectMethod.cs new file mode 100644 index 0000000..ddf8094 --- /dev/null +++ b/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectMethod.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScriptCompiler.Syntax +{ + public class ImportObjectMethod + { + private List _args; + private List> _generics; + + public string ExternalName { get; } + public string ImportName { get; set; } + public TokenPosition Position { get; } + + public List ArgumentTypes + { + get + { + if (_args == null) + _args = new List(); + return _args; + } + } + + public List> Generics + { + get + { + if (_generics == null) + _generics = new List>(); + return _generics; + } + } + + public ImportObjectMethod(string name, TokenPosition position) + { + ImportName = ExternalName = name; + Position = position; + } + + public ImportObjectMethod(string externalName, string importName, TokenPosition position) + { + ExternalName = externalName; + ImportName = importName; + Position = position; + } + } +} diff --git a/TaffyScriptCompiler/Syntax/Concrete/With.cs b/TaffyScriptCompiler/Syntax/Concrete/With.cs deleted file mode 100644 index 1f20236..0000000 --- a/TaffyScriptCompiler/Syntax/Concrete/With.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace TaffyScriptCompiler.Syntax -{ - public class WithNode : SyntaxNode - { - public ISyntaxElement Condition => Children[0]; - public ISyntaxElement Body => Children[1]; - public override SyntaxType Type => SyntaxType.With; - - public WithNode(string value, TokenPosition position) : base(value, position) - { - } - - public override void Accept(ISyntaxElementVisitor visitor) - { - visitor.Visit(this); - } - } -} diff --git a/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs b/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs index 83a37c5..69b8c58 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs +++ b/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs @@ -14,6 +14,7 @@ public interface ISyntaxElementVisitor void Visit(ExitToken exitToken); void Visit(NewNode newNode); void Visit(NamespaceNode namespaceNode); + void Visit(ImportObjectNode importObjectNode); void Visit(ObjectNode objectNode); void Visit(ContinueToken continueToken); void Visit(UsingsNode usingsNode); @@ -32,7 +33,6 @@ public interface ISyntaxElementVisitor void Visit(IConstantToken constantToken); void Visit(ForNode @for); void Visit(DoNode @do); - void Visit(WithNode with); void Visit(WhileNode @while); void Visit(DefaultNode @default); void Visit(PrefixNode prefix); diff --git a/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs b/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs index fbd9df0..89befc2 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs +++ b/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs @@ -52,8 +52,6 @@ public ISyntaxNode CreateNode(SyntaxType type, TokenPosition position) return new WhileNode(null, position); case SyntaxType.Repeat: return new RepeatNode(null, position); - case SyntaxType.With: - return new WithNode(null, position); case SyntaxType.Do: return new DoNode(null, position); case SyntaxType.If: diff --git a/TaffyScriptCompiler/Syntax/SyntaxType.cs b/TaffyScriptCompiler/Syntax/SyntaxType.cs index 5c0a29b..bf5b78e 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxType.cs +++ b/TaffyScriptCompiler/Syntax/SyntaxType.cs @@ -50,6 +50,10 @@ public enum SyntaxType Usings, Namespace, New, + ImportObject, + ImportObjectMember, + ImportObjectMethod, + ImportObjectConstructor, //Token Constant, diff --git a/TaffyScriptCompiler/TaffyScriptCompiler.csproj b/TaffyScriptCompiler/TaffyScriptCompiler.csproj index 991adb6..28f884a 100644 --- a/TaffyScriptCompiler/TaffyScriptCompiler.csproj +++ b/TaffyScriptCompiler/TaffyScriptCompiler.csproj @@ -80,6 +80,7 @@ + @@ -110,11 +111,16 @@ + + + + + @@ -135,7 +141,6 @@ - From 85d42e2190cebd1b9dafff47e76b45f374d592ec Mon Sep 17 00:00:00 2001 From: mystborn Date: Wed, 25 Apr 2018 21:37:43 -0700 Subject: [PATCH 08/54] Deprecate With --- .../Front End/LexicalAnalysis/TokenType.cs | 1 - .../Front End/LexicalAnalysis/Tokenizer.cs | 1 - TaffyScriptCompiler/Front End/Parser.cs | 10 ---------- 3 files changed, 12 deletions(-) diff --git a/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs b/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs index 717eaa5..9e5fa1e 100644 --- a/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs +++ b/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs @@ -79,7 +79,6 @@ public enum TokenType Using, Var, While, - With, Xor, XorEquals } diff --git a/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs b/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs index 3907ac6..b88d720 100644 --- a/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs +++ b/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs @@ -82,7 +82,6 @@ static Tokenizer() { "case", TokenType.Case }, { "default", TokenType.Default }, { "enum", TokenType.Enum }, - { "with", TokenType.With }, { "import", TokenType.Import }, { "script", TokenType.Script }, { "argument", TokenType.Argument }, diff --git a/TaffyScriptCompiler/Front End/Parser.cs b/TaffyScriptCompiler/Front End/Parser.cs index c84f20e..3484009 100644 --- a/TaffyScriptCompiler/Front End/Parser.cs +++ b/TaffyScriptCompiler/Front End/Parser.cs @@ -561,16 +561,6 @@ private ISyntaxElement SimpleStatement() temp.AddChild(BodyStatement()); result = temp; break; - case TokenType.With: - Confirm(TokenType.With); - temp = _factory.CreateNode(SyntaxType.With, next.Position); - paren = Validate(TokenType.OpenParen); - temp.AddChild(Expression()); - if (paren) - Confirm(TokenType.CloseParen); - temp.AddChild(BodyStatement()); - result = temp; - break; case TokenType.Do: Confirm(TokenType.Do); temp = _factory.CreateNode(SyntaxType.Do, next.Position); From 9492c92222af1ebdb212832c4166ded946c6d177 Mon Sep 17 00:00:00 2001 From: mystborn Date: Wed, 25 Apr 2018 23:16:18 -0700 Subject: [PATCH 09/54] Create Imported Object --- Samples/TestSuite/Tests/object_import.tfs | 15 +++++++ Samples/TestSuite/Tests/tests.tfs | 3 ++ .../Backend/Compiler/MsilWeakCodeGen.cs | 45 ++++++++++++++----- TaffyScriptCompiler/Front End/Parser.cs | 2 + .../Symbols/ImportObjectLeaf.cs | 23 ++++++++++ .../TaffyScriptCompiler.csproj | 1 + 6 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 TaffyScriptCompiler/Symbols/ImportObjectLeaf.cs diff --git a/Samples/TestSuite/Tests/object_import.tfs b/Samples/TestSuite/Tests/object_import.tfs index a5102c5..9500b1f 100644 --- a/Samples/TestSuite/Tests/object_import.tfs +++ b/Samples/TestSuite/Tests/object_import.tfs @@ -1,4 +1,19 @@ +using UnitTest; + namespace LanguageTests { + + script run_import_tests() { + var tests = new obj_unit_test("Import Tests", import_create_ds_list); + tests.run_tests(); + } + + script import_create_ds_list() { + test_it("import new ds_list"); + var list = new obj_list(); + list.add("Hello"); + var value = list.get(0); + assert_equal(value, "Hello"); + } //Explicitly import class and method. import object List as obj_list { diff --git a/Samples/TestSuite/Tests/tests.tfs b/Samples/TestSuite/Tests/tests.tfs index 0337db0..e7d464b 100644 --- a/Samples/TestSuite/Tests/tests.tfs +++ b/Samples/TestSuite/Tests/tests.tfs @@ -17,6 +17,9 @@ namespace LanguageTests { run_prefix_tests(); show_debug_message(""); run_ternary_tests(); + show_debug_message(""); + run_import_tests(); + show_debug_message(""); } script timer_entry { diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index 2552913..aa2b50b 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -2406,15 +2406,29 @@ public void Visit(NewNode newNode) { if(symbol.Type == SymbolType.Object) { - var name = newNode.Text; - var pos = newNode.Position; MarkSequencePoint(newNode); - var ctor = typeof(TsInstance).GetConstructor(new[] { typeof(string), typeof(TsObject[]) }); - var ns = GetAssetNamespace(symbol); - if (ns != "") - name = $"{ns}.{name}"; - emit.LdStr(name); + ConstructorInfo ctor; + if(symbol is ImportObjectLeaf leaf) + { + if (!leaf.HasImportedObject) + { + var temp = emit; + leaf.ImportObject.Accept(this); + emit = temp; + } + ctor = leaf.Constructor; + } + else + { + var name = newNode.Text; + var pos = newNode.Position; + ctor = typeof(TsInstance).GetConstructor(new[] { typeof(string), typeof(TsObject[]) }); + var ns = GetAssetNamespace(symbol); + if (ns != "") + name = $"{ns}.{name}"; + emit.LdStr(name); + } if (newNode.Arguments.Count > 0) { emit.LdInt(newNode.Arguments.Count) @@ -3260,13 +3274,18 @@ public void Visit(WhileNode whileNode) public void Visit(ImportObjectNode importNode) { + ImportObjectLeaf leaf = (ImportObjectLeaf)_table.Defined(importNode.ImportName.Value); + if (leaf.HasImportedObject) + return; + + leaf.HasImportedObject = true; + var importType = _typeParser.GetType(importNode.Text); if (importType.IsAbstract || importType.IsEnum || !importType.IsClass) _errors.Add(new CompileException($"Could not import the type {importType.Name}. Imported types must be concrete and currently must be a class.")); - var name = $"{_namespace}.{importNode.ImportName.Value}".TrimStart('.'); - Console.WriteLine(name); + var name = $"{GetAssetNamespace(leaf)}.{importNode.ImportName.Value}".TrimStart('.'); var type = _module.DefineType(name, TypeAttributes.Public, importNode.WeaklyTyped ? typeof(ObjectWrapper) : typeof(Object), new[] { typeof(ITsInstance) }); var source = type.DefineField("_source", importType, FieldAttributes.Private); @@ -3438,7 +3457,7 @@ public void Visit(ImportObjectNode importNode) if (ctor is null) _errors.Add(new CompileException($"Could not find ctor on the type {name} with the arguments {string.Join(", ", ctorArgNames)}")); else - AddConstructorToTypeWrapper(ctor, type, source, importNode.WeaklyTyped); + AddConstructorToTypeWrapper(ctor, type, source, importNode.WeaklyTyped, leaf); } else { @@ -3523,7 +3542,7 @@ public void Visit(ImportObjectNode importNode) case ConstructorInfo ci: if(!foundConstructor && AreMethodParametersSupported(ci.GetParameters())) { - AddConstructorToTypeWrapper(ci, type, source, importNode.WeaklyTyped); + AddConstructorToTypeWrapper(ci, type, source, importNode.WeaklyTyped, leaf); foundConstructor = true; } break; @@ -3899,7 +3918,7 @@ private void AddMethodToTypeWrapper(MethodInfo method, readOnly.Add(importName); } - private void AddConstructorToTypeWrapper(ConstructorInfo ctor, TypeBuilder type, FieldInfo source, bool isWeaklyTyped) + private void AddConstructorToTypeWrapper(ConstructorInfo ctor, TypeBuilder type, FieldInfo source, bool isWeaklyTyped, ImportObjectLeaf leaf) { var createMethod = type.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | @@ -3939,6 +3958,8 @@ private void AddConstructorToTypeWrapper(ConstructorInfo ctor, TypeBuilder type, emit.CallBase(typeof(Object).GetConstructor(Type.EmptyTypes)); emit.Ret(); + + leaf.Constructor = createMethod; } private bool IsMethodSupported(MethodInfo method) diff --git a/TaffyScriptCompiler/Front End/Parser.cs b/TaffyScriptCompiler/Front End/Parser.cs index 3484009..6ce6690 100644 --- a/TaffyScriptCompiler/Front End/Parser.cs +++ b/TaffyScriptCompiler/Front End/Parser.cs @@ -258,6 +258,8 @@ private ISyntaxElement ImportObject(TokenPosition pos) else node = new ImportObjectNode(sb.ToString(), startPos); + _table.AddChild(new ImportObjectLeaf(_table.Current, node.ImportName.Value, node)); + node.ParseArguments(importArgs); if(!Try(TokenType.OpenBrace)) { diff --git a/TaffyScriptCompiler/Symbols/ImportObjectLeaf.cs b/TaffyScriptCompiler/Symbols/ImportObjectLeaf.cs new file mode 100644 index 0000000..665a550 --- /dev/null +++ b/TaffyScriptCompiler/Symbols/ImportObjectLeaf.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TaffyScriptCompiler.Syntax; + +namespace TaffyScriptCompiler +{ + public class ImportObjectLeaf : SymbolLeaf + { + public ImportObjectNode ImportObject { get; } + public System.Reflection.ConstructorInfo Constructor { get; set; } + public bool HasImportedObject { get; set; } = false; + + + public ImportObjectLeaf(SymbolNode parent, string name, ImportObjectNode importObject) + : base(parent, name, SymbolType.Object, SymbolScope.Global) + { + ImportObject = importObject; + } + } +} diff --git a/TaffyScriptCompiler/TaffyScriptCompiler.csproj b/TaffyScriptCompiler/TaffyScriptCompiler.csproj index 28f884a..b5f3f4e 100644 --- a/TaffyScriptCompiler/TaffyScriptCompiler.csproj +++ b/TaffyScriptCompiler/TaffyScriptCompiler.csproj @@ -83,6 +83,7 @@ + From a8ab8fd0050cb2e30902c3bf83d2722cfea1d1d6 Mon Sep 17 00:00:00 2001 From: mystborn Date: Wed, 25 Apr 2018 23:36:44 -0700 Subject: [PATCH 10/54] Import Native ITsInstance --- .../Backend/Compiler/MsilWeakCodeGen.cs | 54 +++++++++++++++---- TaffyScriptCompiler/Backend/ImportType.cs | 14 +++++ TaffyScriptCompiler/Program.cs | 2 - .../TaffyScriptCompiler.csproj | 1 + 4 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 TaffyScriptCompiler/Backend/ImportType.cs diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index aa2b50b..d172f15 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -399,15 +399,33 @@ private void ReadResources(Assembly asm) { var line = reader.ReadLine(); var input = line.Split(':'); - var external = input[2]; - var owner = external.Remove(external.LastIndexOf('.')); - var methodName = external.Substring(owner.Length + 1); - var type = _typeParser.GetType(owner); - var method = GetMethodToImport(type, methodName, ScriptArgs); - var count = _table.EnterNamespace(input[0]); - _table.AddLeaf(input[1], SymbolType.Script, SymbolScope.Global); - _table.Exit(count); - _methods[input[0], input[1]] = method; + var importType = (ImportType)byte.Parse(input[0]); + switch(importType) + { + case ImportType.Script: + var external = input[3]; + var owner = external.Remove(external.LastIndexOf('.')); + var methodName = external.Substring(owner.Length + 1); + var type = _typeParser.GetType(owner); + var method = GetMethodToImport(type, methodName, ScriptArgs); + var count = _table.EnterNamespace(input[1]); + _table.AddLeaf(input[2], SymbolType.Script, SymbolScope.Global); + _table.Exit(count); + _methods[input[1], input[2]] = method; + break; + case ImportType.Object: + external = input[3]; + type = _typeParser.GetType(external); + count = _table.EnterNamespace(input[1]); + var leaf = new ImportObjectLeaf(_table.Current, input[2], null) + { + HasImportedObject = true, + Constructor = type.GetConstructors().First() + }; + _table.AddChild(leaf); + _table.Exit(count); + break; + } } } } @@ -2081,8 +2099,10 @@ public void Visit(ImportNode import) if(IsMethodValid(method)) { _methods.Add(_namespace, internalName, method); + SpecialImports.Write((byte)ImportType.Script); + SpecialImports.Write(':'); SpecialImports.Write(_namespace); - SpecialImports.Write(":"); + SpecialImports.Write(':'); SpecialImports.Write(internalName); SpecialImports.Write(':'); SpecialImports.WriteLine(externalName); @@ -3285,7 +3305,19 @@ public void Visit(ImportObjectNode importNode) if (importType.IsAbstract || importType.IsEnum || !importType.IsClass) _errors.Add(new CompileException($"Could not import the type {importType.Name}. Imported types must be concrete and currently must be a class.")); - var name = $"{GetAssetNamespace(leaf)}.{importNode.ImportName.Value}".TrimStart('.'); + var ns = GetAssetNamespace(leaf); + if(typeof(ITsInstance).IsAssignableFrom(importType)) + { + SpecialImports.Write((byte)ImportType.Object); + SpecialImports.Write(':'); + SpecialImports.Write(ns); + SpecialImports.Write(':'); + SpecialImports.Write(importNode.ImportName.Text); + SpecialImports.Write(':'); + SpecialImports.WriteLine(importType.Name); + } + + var name = $"{ns}.{importNode.ImportName.Value}".TrimStart('.'); var type = _module.DefineType(name, TypeAttributes.Public, importNode.WeaklyTyped ? typeof(ObjectWrapper) : typeof(Object), new[] { typeof(ITsInstance) }); var source = type.DefineField("_source", importType, FieldAttributes.Private); diff --git a/TaffyScriptCompiler/Backend/ImportType.cs b/TaffyScriptCompiler/Backend/ImportType.cs new file mode 100644 index 0000000..e5f85d6 --- /dev/null +++ b/TaffyScriptCompiler/Backend/ImportType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScriptCompiler.Backend +{ + public enum ImportType : byte + { + Script, + Object + } +} diff --git a/TaffyScriptCompiler/Program.cs b/TaffyScriptCompiler/Program.cs index 63b91cd..1eed878 100644 --- a/TaffyScriptCompiler/Program.cs +++ b/TaffyScriptCompiler/Program.cs @@ -26,8 +26,6 @@ static void Main(string[] args) if (extra.Count != 0) path = extra[0]; - path = @"C:\Users\Chris\Source\Repos\GmParser\Samples\TestSuite\Tests"; - if (generateBuild) { var build = new BuildConfig(); diff --git a/TaffyScriptCompiler/TaffyScriptCompiler.csproj b/TaffyScriptCompiler/TaffyScriptCompiler.csproj index b5f3f4e..a71e623 100644 --- a/TaffyScriptCompiler/TaffyScriptCompiler.csproj +++ b/TaffyScriptCompiler/TaffyScriptCompiler.csproj @@ -69,6 +69,7 @@ + From 6313ca5bd7c2ddf664ed2757966047f4bb35a73c Mon Sep 17 00:00:00 2001 From: mystborn Date: Mon, 30 Apr 2018 10:25:48 -0700 Subject: [PATCH 11/54] Get Accessor --- Samples/TestSuite/Tests/object_import.tfs | 5 +- TaffyScript/Collections/TsList.cs | 126 ++++++++++-------- TaffyScript/TsObject.cs | 14 +- .../Backend/BaseClassLibrary.cs | 4 + .../Backend/Compiler/MsilWeakCodeGen.cs | 54 +++++++- 5 files changed, 148 insertions(+), 55 deletions(-) diff --git a/Samples/TestSuite/Tests/object_import.tfs b/Samples/TestSuite/Tests/object_import.tfs index 9500b1f..ca99e03 100644 --- a/Samples/TestSuite/Tests/object_import.tfs +++ b/Samples/TestSuite/Tests/object_import.tfs @@ -1,4 +1,5 @@ using UnitTest; +using TaffyScript.Collections; namespace LanguageTests { @@ -9,13 +10,15 @@ namespace LanguageTests { script import_create_ds_list() { test_it("import new ds_list"); - var list = new obj_list(); + var list = new ds_list(); list.add("Hello"); var value = list.get(0); assert_equal(value, "Hello"); } //Explicitly import class and method. + //Please note that this is an example created for the tests + //The BCL already has a ds_list import that should be used instead. import object List as obj_list { //Import fields and properties. Count as size; diff --git a/TaffyScript/Collections/TsList.cs b/TaffyScript/Collections/TsList.cs index 9bcf86f..be680ab 100644 --- a/TaffyScript/Collections/TsList.cs +++ b/TaffyScript/Collections/TsList.cs @@ -6,7 +6,7 @@ namespace TaffyScript.Collections { - public class TsList : ObjectWrapper, ITsInstance + public class TsList : ITsInstance { private List _source = new List(); @@ -20,35 +20,40 @@ public TsObject this[string memberName] public event DestroyedDelegate Destroyed; + public List Source => _source; + + public TsList(TsObject[] args) + { + } + public TsObject Call(string scriptName, params TsObject[] args) { switch(scriptName) { case "add": - if (args.Length == 1) - _source.Add(args[0]); - else - _source.AddRange(args); + _source.AddRange(args); break; case "clear": _source.Clear(); break; - case "delete": - _source.RemoveAt((int)args[0]); - break; - case "_get": + case "get": return _source[(int)args[0]]; - case "_set": - _source[(int)args[0]] = args[1]; - break; case "insert": _source.Insert((int)args[0], args[1]); break; + case "index_of": + return _source.IndexOf(args[0]); + case "remove": + _source.RemoveAt((int)args[0]); + break; + case "set": + var index = (int)args[0]; + while (_source.Count <= index) + _source.Add(TsObject.Empty()); + _source[index] = args[1]; + break; default: - if (Members.TryGetValue(scriptName, out var member) && member.Type == VariableType.Delegate) - return member.GetDelegateUnchecked().Invoke(args); - else - throw new MemberAccessException($"The type {ObjectType} does not define a script called {scriptName}"); + throw new MemberAccessException($"The type {ObjectType} does not define a script called {scriptName}"); } return TsObject.Empty(); } @@ -71,35 +76,19 @@ public TsObject GetMember(string name) { switch(name) { - case "size": + case "count": return _source.Count; default: if (TryGetDelegate(name, out var del)) return del; - if (Members.TryGetValue(name, out var member)) - return member; - throw new MemberAccessException($"Couldn't find member with the name {name}"); } } public void SetMember(string name, TsObject value) { - switch(name) - { - case "size": - case "add": - case "clear": - case "delete": - case "_get": - case "_set": - case "insert": - throw new MemberAccessException($"Member {name} on type {ObjectType} is readonly"); - default: - Members[name] = value; - break; - } + throw new MemberAccessException($"Member {name} on type {ObjectType} is readonly"); } public bool TryGetDelegate(string scriptName, out TsDelegate del) @@ -109,39 +98,72 @@ public bool TryGetDelegate(string scriptName, out TsDelegate del) del = new TsDelegate(add, "add", this); return true; case "clear": - del = new TsDelegate((i, a) => { _source.Clear(); return TsObject.Empty(); }, "clear", this); + del = new TsDelegate(clear, "clear", this); return true; - case "delete": - del = new TsDelegate((i, a) => { _source.RemoveAt((int)a[0]); return TsObject.Empty(); }, "delete", this); + case "get": + del = new TsDelegate(get, "get", this); return true; - case "_get": - del = new TsDelegate((i, a) => _source[(int)a[0]], "_get", this); + case "insert": + del = new TsDelegate(insert, "insert", this); return true; - case "_set": - del = new TsDelegate((i, a) => { _source[(int)a[0]] = a[1]; return TsObject.Empty(); }, "_set", this); + case "index_of": + del = new TsDelegate(index_of, "index_of", this); return true; - case "insert": - del = new TsDelegate((i, a) => { _source.Insert((int)a[0], a[1]); return TsObject.Empty(); }, "insert", this); + case "remove": + del = new TsDelegate(remove, "remove", this); + return true; + case "set": + del = new TsDelegate(set, "set", this); + return true; + case "delete": + del = new TsDelegate((i, a) => { _source.RemoveAt((int)a[0]); return TsObject.Empty(); }, "delete", this); return true; default: - if(Members.TryGetValue(scriptName, out var member) && member.Type == VariableType.Delegate) - { - del = member.GetDelegateUnchecked(); - return true; - } del = null; return false; } } - public static TsList New(params TsObject[] args) + public TsObject add(ITsInstance inst, TsObject[] args) + { + _source.AddRange(args); + return TsObject.Empty(); + } + + public TsObject clear(ITsInstance inst, TsObject[] args) { - return new TsList(); + _source.Clear(); + return TsObject.Empty(); } - public TsObject add(ITsInstance isnt, TsObject[] args) + public TsObject get(ITsInstance inst, TsObject[] args) { - _source.AddRange(args); + return _source[(int)args[0]]; + } + + public TsObject insert(ITsInstance inst, TsObject[] args) + { + _source.Insert((int)args[0], args[1]); + return TsObject.Empty(); + } + + public TsObject index_of(ITsInstance inst, TsObject[] args) + { + return _source.IndexOf(args[0]); + } + + public TsObject remove(ITsInstance inst, TsObject[] args) + { + _source.RemoveAt((int)args[0]); + return TsObject.Empty(); + } + + public TsObject set(ITsInstance inst, TsObject[] args) + { + var index = (int)args[0]; + while (_source.Count <= index) + _source.Add(TsObject.Empty()); + _source[index] = args[1]; return TsObject.Empty(); } } diff --git a/TaffyScript/TsObject.cs b/TaffyScript/TsObject.cs index e1a38c3..a6ecc28 100644 --- a/TaffyScript/TsObject.cs +++ b/TaffyScript/TsObject.cs @@ -363,10 +363,22 @@ public string GetStringUnchecked() } /// - /// Gets the instance that has an id matching the value held by this object. + /// Gets the instance held by this object. /// /// public ITsInstance GetInstance() + { + if (Type != VariableType.Instance) + throw new InvalidTsTypeException($"Variable is supposed to be of type Instance, is {Type} instead."); + + return (ITsInstance)Value.WeakValue; + } + + /// + /// Gets the instance held by this object without checking its type. + /// + /// + public ITsInstance GetInstanceUnchecked() { return (ITsInstance)Value.WeakValue; } diff --git a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs b/TaffyScriptCompiler/Backend/BaseClassLibrary.cs index ce2b0a8..fe75784 100644 --- a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs +++ b/TaffyScriptCompiler/Backend/BaseClassLibrary.cs @@ -193,6 +193,10 @@ public static string Generate() sb.AppendLine("import TsInstance.VariableInstanceGetNames(instance) as variable_instance_get_names"); sb.AppendLine("import TsInstance.VariableInstanceSet(instance, string, object) as variable_instance_set"); + sb.AppendLine("namespace TaffyScript.Collections {"); + sb.AppendLine("import object TsList as ds_list"); + sb.AppendLine("}"); + return sb.ToString(); } } diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index d172f15..730232a 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -1153,6 +1153,56 @@ public void Visit(ArrayAccessNode arrayAccess) var address = _needAddress; _needAddress = false; GetAddressIfPossible(arrayAccess.Left); + LocalBuilder secret = null; + var top = emit.GetTop(); + if (top == typeof(TsObject)) + { + secret = GetLocal(); + emit.StLocal(secret) + .LdLocalA(secret); + FreeLocal(secret); + } + else if (top != typeof(TsObject).MakePointerType()) + { + _errors.Add(new CompileException($"Encountered invalid syntax {arrayAccess.Position}")); + return; + } + + var isArray = emit.DefineLabel(); + var end = emit.DefineLabel(); + + emit.Dup() + .Call(typeof(TsObject).GetMethod("get_Type")) + .LdInt((int)VariableType.Instance) + .Bne(isArray) + .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .LdStr("get") + .LdInt(arrayAccess.Children.Count - 1) + .NewArr(typeof(TsObject)); + + for(var i = 1; i < arrayAccess.Children.Count; i++) + { + emit.Dup() + .LdInt(i - 1); + arrayAccess.Children[i].Accept(this); + ConvertTopToObject(); + emit.StElem(typeof(TsObject)); + } + + emit.Call(typeof(ITsInstance).GetMethod("Call")); + if(address) + { + secret = GetLocal(); + emit.StLocal(secret) + .LdLocalA(secret); + FreeLocal(secret); + } + + emit.Br(end) + .MarkLabel(isArray) + .PopTop() //The stack would get imbalanced here otherwise. + .PushType(typeof(TsObject).MakePointerType()); + CallInstanceMethod(TsTypes.ObjectCasts[arrayAccess.Children.Count == 2 ? typeof(TsObject[]) : typeof(TsObject[][])], arrayAccess.Position); LoadElementAsInt(arrayAccess.Children[1]); @@ -1173,6 +1223,7 @@ public void Visit(ArrayAccessNode arrayAccess) else emit.LdElem(typeof(TsObject)); } + emit.MarkLabel(end); } public void Visit(ArrayLiteralNode arrayLiteral) @@ -3011,7 +3062,7 @@ public void Visit(ScriptNode script) //Process arguments ProcessScriptArguments(script); - + script.Body.Accept(this); if (!emit.TryGetTop(out _)) @@ -3315,6 +3366,7 @@ public void Visit(ImportObjectNode importNode) SpecialImports.Write(importNode.ImportName.Text); SpecialImports.Write(':'); SpecialImports.WriteLine(importType.Name); + return; } var name = $"{ns}.{importNode.ImportName.Value}".TrimStart('.'); From 51ceb8c744cc204b5fa16b58c9c56ca673fdbac8 Mon Sep 17 00:00:00 2001 From: mystborn Date: Mon, 30 Apr 2018 17:51:37 -0700 Subject: [PATCH 12/54] Get/Set Accessors --- Samples/TestSuite/Tests/array.tfs | 141 +++++++ Samples/TestSuite/Tests/list.tfs | 154 +++++++ Samples/TestSuite/Tests/postfix.tfs | 91 +++-- Samples/TestSuite/Tests/tests.tfs | 4 + TaffyScript/Collections/TsList.cs | 3 - TaffyScript/TsObject.cs | 2 +- .../Backend/Compiler/MsilWeakCodeGen.cs | 377 +++++++++++++++++- TaffyScriptCompiler/Program.cs | 2 + .../Syntax/Concrete/ArrayAccess.cs | 16 +- 9 files changed, 728 insertions(+), 62 deletions(-) create mode 100644 Samples/TestSuite/Tests/array.tfs create mode 100644 Samples/TestSuite/Tests/list.tfs diff --git a/Samples/TestSuite/Tests/array.tfs b/Samples/TestSuite/Tests/array.tfs new file mode 100644 index 0000000..cb76186 --- /dev/null +++ b/Samples/TestSuite/Tests/array.tfs @@ -0,0 +1,141 @@ +using UnitTest; + +namespace LanguageTests { + script run_array_tests() { + var tests = new obj_unit_test("Array Tests", + run_array_faulty_tests, + array1_create_literal, + array1_create_script, + array1_create_variable, + array1_set_in_bounds, + array1_set_out_of_bounds, + array1_get_in_bounds, + array2_create_variable, + array2_set_left_ib_right_ib, + array2_set_left_ib_right_oob, + array2_set_left_oob_right_ib, + array2_set_left_oob_right_oob, + array2_get_left_ib_right_ib); + + tests.run_tests(); + } + + script run_array_faulty_tests() { + assert(try_expect(array1_get_out_of_bounds, "IndexOutOfRangeException")); + assert(try_expect(array2_get_left_ib_right_oob, "IndexOutOfRangeException")); + assert(try_expect(array2_get_left_oob_right_ib, "IndexOutOfRangeException")); + assert(try_expect(array2_get_left_oob_right_oob, "IndexOutOfRangeException")); + test_it("Faulty Array"); + + } + + script array1_create_literal { + test_it("arr = []"); + var arr = []; + assert_equal(typeof(arr), "array") + } + + script array1_create_script { + test_it("arr = array_create()"); + var arr = array_create(1); + assert_equal(typeof(arr), "array"); + } + + script array1_create_variable { + test_it("var arr; arr[0] = 0"); + var arr; + arr[0] = 0; + assert_equal(typeof(arr), "array"); + } + + script array1_set_in_bounds { + test_it("arr[0] = val (in bounds)"); + var arr = [0, 1]; + arr[0] = "moo"; + assert_equal(arr[0], "moo"); + } + + script array1_set_out_of_bounds { + test_it("arr[2] = val (oob)"); + var arr = [0, 1]; + arr[2] = "moo"; + assert_equal(arr[2], "moo"); + } + + script array1_get_in_bounds { + test_it("i = arr[0] (in bounds)"); + var arr = [0, 2]; + var i = arr[1]; + assert_equal(i, 2); + } + + script array1_get_out_of_bounds { + var arr = [0, 2]; + var i = arr[2]; + } + + script array2_create_variable { + test_it("var arr; arr[0,1] = val"); + var arr; + arr[0, 1] = "moo"; + assert_equal(typeof(arr), "array"); + } + + script array2_set_left_ib_right_ib() { + test_it("arr[0 (ib), 0 (ib)] = val") + var arr; + arr[0, 0] = 0; + arr[0, 0] = 33; + assert_equal(arr[0, 0], 33); + } + + script array2_set_left_ib_right_oob() { + test_it("arr[0 (ib), 1 (oob)] = val"); + var arr; + arr[0, 0] = 0; + arr[0, 1] = 33; + assert_equal(arr[0, 1], 33); + } + + script array2_set_left_oob_right_ib() { + test_it("arr[1 (oob), 0 (ib)] = val") + var arr; + arr[0, 0] = 0; + arr[1, 0] = 33; + assert_equal(arr[1, 0], 33); + } + + script array2_set_left_oob_right_oob() { + test_it("arr[1 (oob), 1 (oob)] = val"); + var arr; + arr[0, 0] = 0; + arr[1, 1] = 33; + assert_equal(arr[1, 1], 33); + } + + script array2_get_left_ib_right_ib() { + test_it("val = arr[0 (ib), 0 (ib)]"); + var arr; + arr[0, 0] = 33; + var result = arr[0, 0]; + assert_equal(result, 33); + } + + script array2_get_left_ib_right_oob() { + var arr; + arr[0, 0] = 0; + var result = arr[0, 1]; + } + + script array2_get_left_oob_right_ib() { + var arr; + arr[0, 0] = 0; + var result = arr[1, 0]; + } + + script array2_get_left_oob_right_oob() { + var arr; + arr[0, 0] = 0; + var result = arr[1, 1]; + } +} \ No newline at end of file diff --git a/Samples/TestSuite/Tests/list.tfs b/Samples/TestSuite/Tests/list.tfs new file mode 100644 index 0000000..951f4a3 --- /dev/null +++ b/Samples/TestSuite/Tests/list.tfs @@ -0,0 +1,154 @@ +using UnitTest; +using TaffyScript.Collections; + +namespace LanguageTests { + script run_list_tests() { + var tests = new obj_unit_test("List Tests", + list_create, + list_add_one, + list_add_many, + list_clear, + list_insert, + list_index_of, + list_remove, + list_set_script_ib, + list_set_script_oob, + list_set_access_ib, + list_set_access_oob, + list_get_script_ib, + list_get_access_ib, + run_faulty_list_tests); + tests.run_tests(); + } + + script run_faulty_list_tests() { + assert(try_expect(list_get_script_oob, "ArgumentOutOfRangeException")); + assert(try_expect(list_get_access_oob, "ArgumentOutOfRangeException")); + assert(try_expect(list_call_non_existant_script, "MemberAccessException")); + assert(try_expect(list_get_non_existant_member, "MemberAccessException")); + test_it("faulty list"); + } + + script list_create() { + test_it("var l = new ds_list()"); + var list = new ds_list(); + assert_equal(object_get_name(list), "ds_list"); + } + + script list_add_one() { + test_it("list.add(val)"); + var list = new ds_list() + list.add(2); + assert_equal(list.get(0), 2); + assert_equal(list.count, 1); + } + + script list_add_many() { + test_it("list.add(val, val)"); + var list = new ds_list(); + list.add(2, 3); + assert_equal(list.get(0), 2); + assert_equal(list.count, 2); + } + + script list_clear() { + test_it("list.clear()"); + var list = new ds_list(); + list.add(1); + assert_equal(list.count, 1); + list.clear(); + assert_equal(list.count, 0); + } + + script list_insert() { + test_it("list.insert(0, val)"); + var list = new ds_list(); + list.add(2); + list.insert(0, 3); + assert_equal(list.get(0), 3); + } + + script list_index_of() { + test_it("list.index_of(val)"); + var list = new ds_list(); + list.add(0, 0, 2, 5, 6); + var index = list.index_of(5); + assert_equal(index, 3); + } + + script list_remove() { + test_it("list.remove(val)"); + var list = new ds_list(); + list.add(2, 3, 4); + list.remove(1); + assert_equal(list.get(1), 4); + } + + script list_set_script_ib() { + test_it("list.set(val (ib), val)"); + var list = new ds_list(); + list.add(0); + list.set(0, 33); + assert_equal(list.get(0), 33); + } + + script list_set_script_oob() { + test_it("list.set(val (oob), val)"); + var list = new ds_list(); + list.set(1, 33); + assert_equal(list.get(1), 33); + } + + script list_set_access_ib() { + test_it("list[val (ib)] = val"); + var list = new ds_list(); + list.add(0); + list[0] = 33; + assert_equal(list.get(0), 33); + } + + script list_set_access_oob() { + test_it("list[val (oob)] = val"); + var list = new ds_list(); + list[1] = 33; + assert_equal(list.get(1), 33); + } + + script list_get_script_ib() { + test_it("val = list.get(val (ib))"); + var list = new ds_list(); + list.add(20, 33); + assert_equal(list.get(1), 33); + } + + script list_get_script_oob() { + test_it("val = list.get(val (oob))"); + var list = new ds_list(); + list.add(20); + var result = list.get(1); + } + + script list_get_access_ib() { + test_it("val = list[val (ib)]"); + var list = new ds_list(); + list.add(33, 20); + assert_equal(list[1], 20); + } + + script list_get_access_oob() { + test_it("val = list[val (oob)]"); + var list = new ds_list(); + list.add(20); + var result = list[1]; + } + + script list_call_non_existant_script() { + var list = new ds_list(); + list.moo(); + } + + script list_get_non_existant_member() { + var list = new ds_list(); + var result = list.member; + } +} \ No newline at end of file diff --git a/Samples/TestSuite/Tests/postfix.tfs b/Samples/TestSuite/Tests/postfix.tfs index 42831a4..fce4c2e 100644 --- a/Samples/TestSuite/Tests/postfix.tfs +++ b/Samples/TestSuite/Tests/postfix.tfs @@ -20,69 +20,76 @@ namespace LanguageTests { obj.destroy(); } - script postfix_array() { - test_it("Postfix Array"); - var arr = [1]; + script postfix_array_increment() { + test_it("array++"); + var arr = [4]; arr[0]++; - assert_equal(arr[0], 2); + assert_equal(arr[0], 5); var j = arr[0]++; - assert_equal(j, 2); - assert_equal(arr[0], 3); + assert_equal(j, 5); + assert_equal(arr[0], 6); } - script postfix_list() { - test_it("Postfix List"); - var list = ds_list_create(); - ds_list_add(list, 1); - list[| 0]++; - assert_equal(list[| 0], 2); - var j = list[| 0]++; - assert_equal(j, 2); - assert_equal(list[| 0], 3); + script postfix_array_decrement() { + test_it("array--"); + var arr = [4]; + arr[0]--; + assert_equal(arr[0], 3); + var j = arr[0]--; + assert_equal(j, 3); + assert_equal(arr[0], 2); } - script postfix_grid() { - test_it("Postfix Grid"); - var grid = ds_grid_create(2, 2); - grid[# 0, 0] = 1; - grid[# 0, 0]++; - assert_equal(grid[# 0, 0], 2); - var j = grid[# 0, 0]++; - assert_equal(j, 2); - assert_equal(grid[# 0, 0], 3); + script postfix_list_increment() { + test_it("list++"); + var list = ds_list_create(); + list.add(4); + list[0]++; + assert_equal(list[0], 5); + var j = list[0]++; + assert_equal(j, 5); + assert_equal(list[0], 6); } - script postfix_map() { - test_it("Postfix Map"); - var map = ds_map_create(); - ds_map_add(map, "cow", 1); - map[? "cow"]++; - assert_equal(map[? "cow"], 2); - var j = map[? "cow"]++; - assert_equal(j, 2); - assert_equal(map[? "cow"], 3); + script postfix_list_decrement() { + test_it("list--"); + var list = ds_list_create(); + list.add(4); + list[0]--; + assert_equal(list[0], 3); + var j = list[0]--; + assert_equal(j, 3); + assert_equal(list[0], 2); } - script postfix_local_var() { - test_it("Postfix Local Var"); - var i = 0; + script postfix_local_var_increment() { + test_it("local_var++"); + var i = 4; i++; - assert_equal(i, 1); - + assert_equal(i, 5); var j = i++; - assert_equal(j, 1); + assert_equal(j, 5); + assert_equal(i, 6); + } + + script postfix_local_var_decrement() { + test_it("local_var--"); + var i = 4; + i--; + assert_equal(i, 3); + var j = i--; + assert_equal(j, 3); assert_equal(i, 2); } - script postfix_local_object_var() { - test_it("Postfix Local Object Var"); + script postfix_local_object_var_increment() { + test_it("local_object_var++"); var obj = new obj_postfix(); obj.val++; assert_equal(obj.val, 11); var j = obj.val++; assert_equal(j, 11); assert_equal(obj.val, 12); - obj.destroy(); } script postfix_global_var() { diff --git a/Samples/TestSuite/Tests/tests.tfs b/Samples/TestSuite/Tests/tests.tfs index e7d464b..076a275 100644 --- a/Samples/TestSuite/Tests/tests.tfs +++ b/Samples/TestSuite/Tests/tests.tfs @@ -20,6 +20,10 @@ namespace LanguageTests { show_debug_message(""); run_import_tests(); show_debug_message(""); + run_array_tests(); + show_debug_message(""); + run_list_tests(); + show_debug_message(""); } script timer_entry { diff --git a/TaffyScript/Collections/TsList.cs b/TaffyScript/Collections/TsList.cs index be680ab..62630f8 100644 --- a/TaffyScript/Collections/TsList.cs +++ b/TaffyScript/Collections/TsList.cs @@ -115,9 +115,6 @@ public bool TryGetDelegate(string scriptName, out TsDelegate del) case "set": del = new TsDelegate(set, "set", this); return true; - case "delete": - del = new TsDelegate((i, a) => { _source.RemoveAt((int)a[0]); return TsObject.Empty(); }, "delete", this); - return true; default: del = null; return false; diff --git a/TaffyScript/TsObject.cs b/TaffyScript/TsObject.cs index a6ecc28..9891e91 100644 --- a/TaffyScript/TsObject.cs +++ b/TaffyScript/TsObject.cs @@ -583,7 +583,7 @@ public void ArraySet(int index1, int index2, TsObject right) else if(index2 >= self.StrongValue[index1].Length) { var temp = new TsObject[index2 + 1]; - Array.Copy(self.StrongValue[index1], 0, temp, 0, self.StrongValue[index2].Length); + Array.Copy(self.StrongValue[index1], 0, temp, 0, self.StrongValue[index1].Length); self.StrongValue[index1] = temp; } self.StrongValue[index1][index2] = right; diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index 730232a..791fb60 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -1268,18 +1268,58 @@ public void Visit(AssignNode assign) .LdLocalA(secret); FreeLocal(secret); } + var isArray = emit.DefineLabel(); + var end = emit.DefineLabel(); - var argTypes = new Type[array.Children.Count]; - for (var i = 1; i < array.Children.Count; i++) + emit.Dup() + .Call(typeof(TsObject).GetMethod("get_Type")) + .LdInt((int)VariableType.Instance) + .Bne(isArray) + .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .LdStr("set") + .LdInt(array.Indeces.Count + 1) + .NewArr(typeof(TsObject)); + + for(var i = 0; i < array.Indeces.Count; i++) { - LoadElementAsInt(array.Children[i]); - argTypes[i - 1] = typeof(int); + emit.Dup() + .LdInt(i); + array.Indeces[i].Accept(this); + ConvertTopToObject(); + emit.StElem(typeof(TsObject)); + } + emit.Dup() + .LdInt(array.Indeces.Count); + assign.Right.Accept(this); + ConvertTopToObject(); + emit.StElem(typeof(TsObject)) + .Call(typeof(ITsInstance).GetMethod("Call")) + .Pop() + .Br(end) + .PushType(typeof(TsObject).MakePointerType()) + .MarkLabel(isArray); + + var argTypes = new Type[array.Indeces.Count + 1]; + + if(array.Indeces.Count > 2) + { + _errors.Add(new CompileException("Cannot access array with a rank greater then 2")); + emit.Pop() + .Call(TsTypes.Empty); + return; + } + + for (var i = 0; i < array.Indeces.Count; i++) + { + LoadElementAsInt(array.Indeces[i]); + argTypes[i] = typeof(int); } assign.Right.Accept(this); ConvertTopToObject(); argTypes[argTypes.Length - 1] = typeof(TsObject); - emit.Call(typeof(TsObject).GetMethod("ArraySet", argTypes)); + emit.Call(typeof(TsObject).GetMethod("ArraySet", argTypes)) + .MarkLabel(end); } else if(assign.Left is ListAccessNode list) { @@ -1395,11 +1435,8 @@ public void Visit(AssignNode assign) private void ProcessAssignExtra(AssignNode assign) { var op = assign.Text.Replace("=", ""); - if (assign.Left.Type == SyntaxType.ArrayAccess || assign.Left.Type == SyntaxType.ArgumentAccess) + if (assign.Left.Type == SyntaxType.ArgumentAccess) { - //Because this has to access the array location, - //we can safely just get the address of the array elem and overwrite - //the data pointed to by that address. GetAddressIfPossible(assign.Left); emit.Dup() .LdObj(typeof(TsObject)); @@ -1407,6 +1444,107 @@ private void ProcessAssignExtra(AssignNode assign) emit.Call(GetOperator(op, typeof(TsObject), emit.GetTop(), assign.Position)) .StObj(typeof(TsObject)); } + else if(assign.Left.Type == SyntaxType.ArrayAccess) + { + LocalBuilder secret; + var value = GetLocal(); + + var array = (ArrayAccessNode)assign.Left; + array.Left.Accept(this); + var top = emit.GetTop(); + if(top == typeof(TsObject)) + { + secret = GetLocal(); + emit.StLocal(secret) + .LdLocalA(secret); + FreeLocal(secret); + } + else if (top != typeof(TsObject).MakePointerType()) + { + _errors.Add(new CompileException($"Encountered invalid syntax {array.Position}")); + emit.Call(TsTypes.Empty); + return; + } + + var isArray = emit.DefineLabel(); + var end = emit.DefineLabel(); + secret = GetLocal(typeof(ITsInstance)); + + emit.Dup() + .Call(typeof(TsObject).GetMethod("get_Type")) + .LdInt((int)VariableType.Instance) + .Bne(isArray) + .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .StLocal(secret) + .LdLocal(secret) + .LdStr("get") + .LdInt(array.Indeces.Count) + .NewArr(typeof(TsObject)); + + var indeces = new LocalBuilder[array.Indeces.Count]; + for (var i = 0; i < array.Indeces.Count; i++) + { + emit.Dup() + .LdInt(i); + array.Indeces[i].Accept(this); + ConvertTopToObject(); + indeces[i] = GetLocal(); + emit.Dup() + .StLocal(indeces[i]) + .StElem(typeof(TsObject)); + } + + emit.Call(typeof(ITsInstance).GetMethod("Call")); + assign.Right.Accept(this); + emit.Call(GetOperator(op, typeof(TsObject), emit.GetTop(), assign.Position)) + .StLocal(value) + .LdLocal(secret) + .LdStr("set") + .LdInt(indeces.Length + 1) + .NewArr(typeof(TsObject)); + + FreeLocal(secret); + + for(var i = 0; i < indeces.Length; i++) + { + emit.Dup() + .LdInt(i) + .LdLocal(indeces[i]) + .StElem(typeof(TsObject)); + FreeLocal(indeces[i]); + } + emit.Dup() + .LdInt(indeces.Length) + .LdLocal(value) + .StElem(typeof(TsObject)) + .Call(typeof(ITsInstance).GetMethod("Call")) + .Pop() + .Br(end) + .PushType(typeof(TsObject).MakePointerType()) + .MarkLabel(isArray); + + FreeLocal(value); + + CallInstanceMethod(TsTypes.ObjectCasts[array.Children.Count == 2 ? typeof(TsObject[]) : typeof(TsObject[][])], array.Position); + LoadElementAsInt(array.Children[1]); + + if (array.Children.Count == 2) + { + emit.LdElemA(typeof(TsObject)); + } + else + { + emit.LdElem(typeof(TsObject[])); + LoadElementAsInt(array.Children[2]); + emit.LdElemA(typeof(TsObject)); + } + emit.Dup() + .LdObj(typeof(TsObject)); + assign.Right.Accept(this); + emit.Call(GetOperator(op, typeof(TsObject), emit.GetTop(), assign.Position)) + .StObj(typeof(TsObject)) + .MarkLabel(end); + } else if (assign.Left is ListAccessNode list) { ListAccessSet(list, 2); @@ -2627,7 +2765,7 @@ public void Visit(ObjectNode objectNode) public void Visit(PostfixNode postfix) { var secret = GetLocal(); - if (postfix.Child.Type == SyntaxType.ArrayAccess || postfix.Child.Type == SyntaxType.ArgumentAccess) + if (postfix.Child.Type == SyntaxType.ArgumentAccess) { GetAddressIfPossible(postfix.Child); emit.Dup() @@ -2639,6 +2777,114 @@ public void Visit(PostfixNode postfix) .StObj(typeof(TsObject)) .LdLocal(secret); } + else if(postfix.Child.Type == SyntaxType.ArrayAccess) + { + var value = GetLocal(); + var result = GetLocal(); + + var array = (ArrayAccessNode)postfix.Child; + array.Left.Accept(this); + var top = emit.GetTop(); + if (top == typeof(TsObject)) + { + secret = GetLocal(); + emit.StLocal(secret) + .LdLocalA(secret); + FreeLocal(secret); + } + else if (top != typeof(TsObject).MakePointerType()) + { + _errors.Add(new CompileException($"Encountered invalid syntax {array.Position}")); + emit.Call(TsTypes.Empty); + return; + } + + var isArray = emit.DefineLabel(); + var end = emit.DefineLabel(); + secret = GetLocal(typeof(ITsInstance)); + + emit.Dup() + .Call(typeof(TsObject).GetMethod("get_Type")) + .LdInt((int)VariableType.Instance) + .Bne(isArray) + .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .StLocal(secret) + .LdLocal(secret) + .LdStr("get") + .LdInt(array.Indeces.Count) + .NewArr(typeof(TsObject)); + + var indeces = new LocalBuilder[array.Indeces.Count]; + for (var i = 0; i < array.Indeces.Count; i++) + { + emit.Dup() + .LdInt(i); + array.Indeces[i].Accept(this); + ConvertTopToObject(); + indeces[i] = GetLocal(); + emit.Dup() + .StLocal(indeces[i]) + .StElem(typeof(TsObject)); + } + + emit.Call(typeof(ITsInstance).GetMethod("Call")) + .Dup() + .StLocal(value) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) + .StLocal(result) + .LdLocal(secret) + .LdStr("set") + .LdInt(indeces.Length + 1) + .NewArr(typeof(TsObject)); + + FreeLocal(secret); + + for (var i = 0; i < indeces.Length; i++) + { + emit.Dup() + .LdInt(i) + .LdLocal(indeces[i]) + .StElem(typeof(TsObject)); + FreeLocal(indeces[i]); + } + emit.Dup() + .LdInt(indeces.Length) + .LdLocal(result) + .StElem(typeof(TsObject)) + .Call(typeof(ITsInstance).GetMethod("Call")) + .Pop() + .LdLocal(value) + .Br(end) + .PushType(typeof(TsObject).MakePointerType()) + .MarkLabel(isArray); + + FreeLocal(result); + + CallInstanceMethod(TsTypes.ObjectCasts[array.Children.Count == 2 ? typeof(TsObject[]) : typeof(TsObject[][])], array.Position); + LoadElementAsInt(array.Children[1]); + + if (array.Children.Count == 2) + { + emit.LdElemA(typeof(TsObject)); + } + else + { + emit.LdElem(typeof(TsObject[])); + LoadElementAsInt(array.Children[2]); + emit.LdElemA(typeof(TsObject)); + } + emit.Dup() + .LdObj(typeof(TsObject)) + .Dup() + .StLocal(value) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) + .StObj(typeof(TsObject)) + .LdLocal(value) + .MarkLabel(end) + .PopTop(); + + FreeLocal(value); + } else if(postfix.Child is ListAccessNode list) { ListAccessSet(list, 2); @@ -2761,7 +3007,7 @@ public void Visit(PrefixNode prefix) if (prefix.Text == "++" || prefix.Text == "--") { var secret = GetLocal(); - if (prefix.Child.Type == SyntaxType.ArrayAccess || prefix.Child.Type == SyntaxType.ArgumentAccess) + if (prefix.Child.Type == SyntaxType.ArgumentAccess) { GetAddressIfPossible(prefix.Child); emit.Dup() @@ -2771,6 +3017,109 @@ public void Visit(PrefixNode prefix) .StObj(typeof(TsObject)) .LdObj(typeof(TsObject)); } + else if (prefix.Child.Type == SyntaxType.ArrayAccess) + { + var value = GetLocal(); + + var array = (ArrayAccessNode)prefix.Child; + array.Left.Accept(this); + var top = emit.GetTop(); + if (top == typeof(TsObject)) + { + secret = GetLocal(); + emit.StLocal(secret) + .LdLocalA(secret); + FreeLocal(secret); + } + else if (top != typeof(TsObject).MakePointerType()) + { + _errors.Add(new CompileException($"Encountered invalid syntax {array.Position}")); + emit.Call(TsTypes.Empty); + return; + } + + var isArray = emit.DefineLabel(); + var end = emit.DefineLabel(); + secret = GetLocal(typeof(ITsInstance)); + + emit.Dup() + .Call(typeof(TsObject).GetMethod("get_Type")) + .LdInt((int)VariableType.Instance) + .Bne(isArray) + .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .StLocal(secret) + .LdLocal(secret) + .LdStr("get") + .LdInt(array.Indeces.Count) + .NewArr(typeof(TsObject)); + + var indeces = new LocalBuilder[array.Indeces.Count]; + for (var i = 0; i < array.Indeces.Count; i++) + { + emit.Dup() + .LdInt(i); + array.Indeces[i].Accept(this); + ConvertTopToObject(); + indeces[i] = GetLocal(); + emit.Dup() + .StLocal(indeces[i]) + .StElem(typeof(TsObject)); + } + + emit.Call(typeof(ITsInstance).GetMethod("Call")) + .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) + .StLocal(value) + .LdLocal(secret) + .LdStr("set") + .LdInt(indeces.Length + 1) + .NewArr(typeof(TsObject)); + + FreeLocal(secret); + + for (var i = 0; i < indeces.Length; i++) + { + emit.Dup() + .LdInt(i) + .LdLocal(indeces[i]) + .StElem(typeof(TsObject)); + FreeLocal(indeces[i]); + } + emit.Dup() + .LdInt(indeces.Length) + .LdLocal(value) + .StElem(typeof(TsObject)) + .Call(typeof(ITsInstance).GetMethod("Call")) + .Pop() + .LdLocal(value) + .Br(end) + .PushType(typeof(TsObject).MakePointerType()) + .MarkLabel(isArray); + + CallInstanceMethod(TsTypes.ObjectCasts[array.Children.Count == 2 ? typeof(TsObject[]) : typeof(TsObject[][])], array.Position); + LoadElementAsInt(array.Children[1]); + + if (array.Children.Count == 2) + { + emit.LdElemA(typeof(TsObject)); + } + else + { + emit.LdElem(typeof(TsObject[])); + LoadElementAsInt(array.Children[2]); + emit.LdElemA(typeof(TsObject)); + } + emit.Dup() + .LdObj(typeof(TsObject)) + .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) + .Dup() + .StLocal(value) + .StObj(typeof(TsObject)) + .LdLocal(value) + .MarkLabel(end) + .PopTop(); + + FreeLocal(value); + } else if (prefix.Child is ListAccessNode list) { ListAccessSet(list, 2); @@ -3592,12 +3941,12 @@ public void Visit(ImportObjectNode importNode) if(pi.CanRead && IsMethodSupported(pi.GetMethod)) { foundIndexer = true; - AddMethodToTypeWrapper(pi.GetMethod, weakFlags, type, transformName("get"), importNode.Position, source, call, tryd, readOnly); + AddMethodToTypeWrapper(pi.GetMethod, weakFlags, type, "get", importNode.Position, source, call, tryd, readOnly); } if(pi.CanWrite && IsMethodSupported(pi.SetMethod)) { foundIndexer = true; - AddMethodToTypeWrapper(pi.SetMethod, weakFlags, type, transformName("set"), importNode.Position, source, call, tryd, readOnly); + AddMethodToTypeWrapper(pi.SetMethod, weakFlags, type, "set", importNode.Position, source, call, tryd, readOnly); } } else @@ -4009,7 +4358,7 @@ private void AddConstructorToTypeWrapper(ConstructorInfo ctor, TypeBuilder type, MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, - new[] { typeof(TsObject) }); + new[] { typeof(TsObject[]) }); emit = new ILEmitter(createMethod, new[] { typeof(TsObject[]) }); emit.LdArg(0); diff --git a/TaffyScriptCompiler/Program.cs b/TaffyScriptCompiler/Program.cs index 1eed878..63b91cd 100644 --- a/TaffyScriptCompiler/Program.cs +++ b/TaffyScriptCompiler/Program.cs @@ -26,6 +26,8 @@ static void Main(string[] args) if (extra.Count != 0) path = extra[0]; + path = @"C:\Users\Chris\Source\Repos\GmParser\Samples\TestSuite\Tests"; + if (generateBuild) { var build = new BuildConfig(); diff --git a/TaffyScriptCompiler/Syntax/Concrete/ArrayAccess.cs b/TaffyScriptCompiler/Syntax/Concrete/ArrayAccess.cs index 9fa552b..909abee 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ArrayAccess.cs +++ b/TaffyScriptCompiler/Syntax/Concrete/ArrayAccess.cs @@ -1,9 +1,21 @@ -namespace TaffyScriptCompiler.Syntax +using System.Collections.Generic; + +namespace TaffyScriptCompiler.Syntax { public class ArrayAccessNode : SyntaxNode { + private List _indeces = null; + public ISyntaxElement Left => Children[0]; - public ISyntaxElement Right => Children[1]; + public IReadOnlyList Indeces + { + get + { + if (_indeces == null) + _indeces = Children.GetRange(1, Children.Count - 1); + return _indeces; + } + } public override SyntaxType Type => SyntaxType.ArrayAccess; public ArrayAccessNode(string value, TokenPosition position) : base(value, position) From eba5fa875718f416fdd63839ae114c3a1af30193 Mon Sep 17 00:00:00 2001 From: mystborn Date: Tue, 1 May 2018 20:48:46 -0700 Subject: [PATCH 13/54] BCL Collections --- Samples/TestSuite/Tests/postfix.tfs | 108 +++- TaffyScript/Collections/Grid.cs | 7 + TaffyScript/Collections/TsGrid.cs | 594 ++++++++++++++++++ TaffyScript/Collections/TsList.cs | 34 +- TaffyScript/Collections/TsMap.cs | 180 ++++++ TaffyScript/TaffyScript.csproj | 2 + .../Backend/BaseClassLibrary.cs | 2 + TaffyScriptCompiler/Front End/Parser.cs | 2 +- TaffyScriptCompiler/Program.cs | 2 - 9 files changed, 898 insertions(+), 33 deletions(-) create mode 100644 TaffyScript/Collections/TsGrid.cs create mode 100644 TaffyScript/Collections/TsMap.cs diff --git a/Samples/TestSuite/Tests/postfix.tfs b/Samples/TestSuite/Tests/postfix.tfs index fce4c2e..1aed890 100644 --- a/Samples/TestSuite/Tests/postfix.tfs +++ b/Samples/TestSuite/Tests/postfix.tfs @@ -1,23 +1,28 @@ using UnitTest; +using TaffyScript.Collections; namespace LanguageTests { script run_postfix_tests() { var obj = new obj_postfix(); var tests = new obj_unit_test("Postfix Tests", - postfix_array, - postfix_list, - postfix_grid, - postfix_map, - postfix_local_var, - postfix_local_object_var, - postfix_global_var, - postfix_global_object_var, - obj.postfix_object_var, - obj.postfix_self_var); + postfix_array_increment, + postfix_array_decrement, + postfix_list_increment, + postfix_list_decrement, + postfix_local_var_increment, + postfix_local_var_decrement, + postfix_global_var_increment, + postfix_local_var_decrement, + postfix_local_object_var_increment, + postfix_local_object_var_decrement, + postfix_global_object_var_increment, + postfix_global_object_var_decrement, + obj.postfix_object_var_increment, + obj.postfix_object_var_decrement, + obj.postfix_self_var_increment, + obj.postfix_self_var_decrement); tests.run_tests(); - tests.destroy(); - obj.destroy(); } script postfix_array_increment() { @@ -42,7 +47,7 @@ namespace LanguageTests { script postfix_list_increment() { test_it("list++"); - var list = ds_list_create(); + var list = new ds_list(); list.add(4); list[0]++; assert_equal(list[0], 5); @@ -53,7 +58,7 @@ namespace LanguageTests { script postfix_list_decrement() { test_it("list--"); - var list = ds_list_create(); + var list = new ds_list(); list.add(4); list[0]--; assert_equal(list[0], 3); @@ -92,25 +97,54 @@ namespace LanguageTests { assert_equal(obj.val, 12); } - script postfix_global_var() { - test_it("Postfix Global Var"); - global.val = 5; + script postfix_local_object_var_decrement() { + test_it("local_object_var--"); + var obj = new obj_postfix(); + obj.val--; + assert_equal(obj.val, 9); + var j = obj.val--; + assert_equal(j, 9); + assert_equal(obj.val, 8); + } + + script postfix_global_var_increment() { + test_it("global.val++"); + global.val = 4; global.val++; - assert_equal(global.val, 6); + assert_equal(global.val, 5); var j = global.val++; - assert_equal(j, 6); - assert_equal(global.val, 7); + assert_equal(j, 5); + assert_equal(global.val, 6); + } + + script postfix_global_var_decrement() { + test_it("global.val--"); + global.val = 4; + global.val--; + assert_equal(global.val, 3); + var j = global.val--; + assert_equal(j, 3); + assert_equal(global.val, 2); } - script postfix_global_object_var() { - test_it("Postfix Global Object Var"); + script postfix_global_object_var_increment() { + test_it("global.object.val++"); global.obj = new obj_postfix(); global.obj.val++; assert_equal(global.obj.val, 11); var j = global.obj.val++; assert_equal(j, 11); assert_equal(global.obj.val, 12); - global.obj.destroy(); + } + + script postfix_global_object_var_decrement() { + test_it("global.object.val--"); + global.obj = new obj_postfix(); + global.obj.val--; + assert_equal(global.obj.val, 9); + var j = global.obj.val--; + assert_equal(j, 9); + assert_equal(global.obj.val, 8); } object obj_postfix { @@ -122,8 +156,8 @@ namespace LanguageTests { val = 10; } - event postfix_object_var() { - test_it("Postfix Object Var"); + event postfix_object_var_increment() { + test_it("object.val++"); reset(); val++; assert_equal(val, 11); @@ -132,8 +166,18 @@ namespace LanguageTests { assert_equal(val, 12); } - event postfix_self_var() { - test_it("Postfix Self Var"); + event postfix_object_var_decrement() { + test_it("object.val--"); + reset(); + val--; + assert_equal(val, 9); + var j = val--; + assert_equal(j, 9); + assert_equal(val, 8); + } + + event postfix_self_var_increment() { + test_it("self.val++"); reset(); self.val++; assert_equal(val, 11); @@ -141,5 +185,15 @@ namespace LanguageTests { assert_equal(j, 11); assert_equal(val, 12); } + + event postfix_self_var_decrement() { + test_it("self.val--"); + reset(); + self.val--; + assert_equal(val, 9); + var j = self.val--; + assert_equal(j, 9); + assert_equal(val, 8); + } } } \ No newline at end of file diff --git a/TaffyScript/Collections/Grid.cs b/TaffyScript/Collections/Grid.cs index 692f7a4..6c92ccc 100644 --- a/TaffyScript/Collections/Grid.cs +++ b/TaffyScript/Collections/Grid.cs @@ -63,6 +63,13 @@ public void SetGridRegion(Grid src, int x1, int y1, int x2, int y2, int xpos, } } + public void Clear(T value) + { + for (var h = 0; h < Height; h++) + for (var w = 0; w < Width; w++) + _source[w, h] = value; + } + public void Shuffle() { Extensions.Shuffle(_source); diff --git a/TaffyScript/Collections/TsGrid.cs b/TaffyScript/Collections/TsGrid.cs new file mode 100644 index 0000000..b5138a0 --- /dev/null +++ b/TaffyScript/Collections/TsGrid.cs @@ -0,0 +1,594 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScript.Collections +{ +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + + public class TsGrid : ITsInstance + { + private Grid _source; + + public TsObject this[string memberName] + { + get => GetMember(memberName); + set => SetMember(memberName, value); + } + + public string ObjectType => "ds_grid"; + public Grid Source => _source; + + public event DestroyedDelegate Destroyed; + + public TsGrid(TsObject[] args) + { + _source = new Grid((int)args[0], (int)args[1]); + } + + public TsGrid(Grid grid) + { + _source = new Grid(grid.Width, grid.Height); + _source.SetGridRegion(grid, 0, 0, grid.Width - 1, grid.Height - 1, 0, 0); + } + + public TsObject Call(string scriptName, params TsObject[] args) + { + switch (scriptName) + { + case "get": + return _source[(int)args[0], (int)args[1]]; + case "set": + _source[(int)args[0], (int)args[1]] = args[2]; + break; + case "add_disk": + _source.OverDisk((int)args[0], (int)args[1], (int)args[2], (w, h, g) => g[w, h] += args[3]); + break; + case "add_grid_region": + return add_grid_region(null, args); + case "add_region": + _source.OverRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], (w, h, g) => g[w, h] += args[4]); + break; + case "clear": + _source.Clear(args[0]); + break; + case "copy": + return new TsGrid(_source); + case "get_disk_max": + return get_disk_max(null, args); + case "get_disk_mean": + return get_disk_mean(null, args); + case "get_disk_min": + return get_disk_min(null, args); + case "get_disk_sum": + return get_disk_sum(null, args); + case "get_region_max": + return get_region_max(null, args); + case "get_region_mean": + return get_region_mean(null, args); + case "get_region_min": + return get_region_min(null, args); + case "get_region_sum": + return get_region_sum(null, args); + case "multiply_disk": + _source.OverDisk((int)args[0], (int)args[1], (int)args[2], (w, h, g) => g[w, h] *= args[3]); + break; + case "multiply_grid_region": + return multiply_grid_region(null, args); + case "multiply_region": + _source.OverRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], (w, h, g) => g[w, h] *= args[4]); + break; + case "resize": + _source.Resize((int)args[0], (int)args[1]); + break; + case "set_disk": + _source.OverDisk((int)args[0], (int)args[1], (int)args[2], (w, h, g) => g[w, h] *= args[3]); + break; + case "set_grid_region": + return set_grid_region(null, args); + case "set_region": + _source.OverRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], (w, h, g) => g[w, h] = args[4]); + break; + case "shuffle": + _source.Shuffle(); + break; + case "sort": + _source.Sort((int)args[0], (bool)args[1]); + break; + case "value_exists_in_disk": + return _source.InDisk((int)args[0], (int)args[1], (int)args[2], args[3]); + case "value_position_in_disk": + if (_source.InDisk((int)args[0], (int)args[1], (int)args[2], args[3], out var result, (w, h) => new TsObject[] { w, h })) + return result; + break; + case "value_exists_in_region": + return _source.InRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], args[4]); + case "value_position_in_region": + if (_source.InRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], args[4], out result, (w, h) => new TsObject[] { w, h })) + return result; + break; + default: + throw new MemberAccessException($"The type {ObjectType} does not define a script called {scriptName}"); + } + return TsObject.Empty(); + } + + public void Destroy() + { + Destroyed?.Invoke(this); + _source = null; + } + + public TsDelegate GetDelegate(string scriptName) + { + if (TryGetDelegate(scriptName, out var del)) + return del; + throw new MemberAccessException($"The type {ObjectType} does not define a script called {scriptName}"); + } + + public TsObject GetMember(string name) + { + switch (name) + { + case "width": + return _source.Width; + case "height": + return _source.Height; + default: + if (TryGetDelegate(name, out var del)) + return del; + throw new MemberAccessException($"Couldn't find member with the name {name}"); + } + } + + public void SetMember(string name, TsObject value) + { + throw new MemberAccessException($"Member {name} on type {ObjectType} is readonly"); + } + + public bool TryGetDelegate(string delegateName, out TsDelegate del) + { + switch (delegateName) + { + + case "get": + del = new TsDelegate(get, "get", this); + return true; + case "set": + del = new TsDelegate(set, "set", this); + return true; + case "add_disk": + del = new TsDelegate(add_disk, "add_disk", this); + return true; + case "add_grid_region": + del = new TsDelegate(add_grid_region, "add_grid_region", this); + return true; + case "add_region": + del = new TsDelegate(add_region, "add_region", this); + return true; + case "clear": + del = new TsDelegate(clear, "clear", this); + return true; + case "copy": + del = new TsDelegate(copy, "copy", this); + return true; + case "get_disk_max": + del = new TsDelegate(get_disk_max, "get_disk_max", this); + return true; + case "get_disk_mean": + del = new TsDelegate(get_disk_mean, "get_disk_mean", this); + return true; + case "get_disk_min": + del = new TsDelegate(get_disk_min, "get_disk_min", this); + return true; + case "get_disk_sum": + del = new TsDelegate(get_disk_sum, "get_disk_sum", this); + return true; + case "get_region_max": + del = new TsDelegate(get_region_max, "get_region_max", this); + return true; + case "get_region_mean": + del = new TsDelegate(get_region_mean, "get_region_mean", this); + return true; + case "get_region_min": + del = new TsDelegate(get_region_min, "get_region_min", this); + return true; + case "get_region_sum": + del = new TsDelegate(get_region_sum, "get_region_sum", this); + return true; + case "multiply_disk": + del = new TsDelegate(multiply_disk, "multiply_disk", this); + return true; + case "multiply_grid_region": + del = new TsDelegate(multiply_grid_region, "multiply_grid_region", this); + return true; + case "multiply_region": + del = new TsDelegate(multiply_region, "multiply_region", this); + return true; + case "resize": + del = new TsDelegate(resize, "resize", this); + return true; + case "set_disk": + del = new TsDelegate(set_disk, "set_disk", this); + return true; + case "set_grid_region": + del = new TsDelegate(set_grid_region, "set_grid_region", this); + return true; + case "set_region": + del = new TsDelegate(set_region, "set_region", this); + return true; + case "shuffle": + del = new TsDelegate(shuffle, "shuffle", this); + return true; + case "sort": + del = new TsDelegate(sort, "sort", this); + return true; + case "value_exists_in_disk": + del = new TsDelegate(value_exists_in_disk, "value_exists_in_disk", this); + return true; + case "value_position_in_disk": + del = new TsDelegate(value_position_in_disk, "value_position_in_disk", this); + return true; + case "value_exists_in_region": + del = new TsDelegate(value_exists_in_region, "value_exists_in_region", this); + return true; + case "value_position_in_region": + del = new TsDelegate(value_position_in_region, "value_position_in_region", this); + return true; + default: + del = null; + return false; + } + } + + public static explicit operator TsGrid(TsObject obj) + { + return (TsGrid)obj.Value.WeakValue; + } + + public static implicit operator TsObject(TsGrid grid) + { + return new TsObject(grid); + } + +#pragma warning disable IDE1006 // Naming Styles + + public TsObject get(ITsInstance inst, params TsObject[] args) + { + return _source[(int)args[0], (int)args[1]]; + } + + public TsObject set(ITsInstance inst, params TsObject[] args) + { + _source[(int)args[0], (int)args[1]] = args[2]; + return TsObject.Empty(); + } + + public TsObject add_disk(ITsInstance inst, params TsObject[] args) + { + _source.OverDisk((int)args[0], (int)args[1], (int)args[2], (w, h, g) => g[w, h] += args[3]); + return TsObject.Empty(); + } + + public TsObject add_grid_region(ITsInstance inst, params TsObject[] args) + { + var src = ((TsGrid)args[0]).Source; + var x1 = (int)args[1]; + var y1 = (int)args[2]; + var x2 = (int)args[2]; + var y2 = (int)args[3]; + var xPos = (int)args[4]; + var yPos = (int)args[5]; + var xLength = x2 - x1; + var yLength = y2 - y1; + + if (x1 < 0) + throw new ArgumentOutOfRangeException(nameof(x1)); + if (x2 >= src.Width) + throw new ArgumentOutOfRangeException(nameof(x2)); + if (y1 < 0) + throw new ArgumentOutOfRangeException(nameof(y1)); + if (y2 >= src.Height) + throw new ArgumentOutOfRangeException(nameof(y2)); + if (xPos < 0 || xPos + xLength >= _source.Width) + throw new ArgumentOutOfRangeException(nameof(xPos)); + if (yPos < 0 || yPos + yLength >= _source.Height) + throw new ArgumentOutOfRangeException(nameof(yPos)); + + for (var w = 0; w < xLength; w++) + { + for (var h = 0; h < yLength; h++) + { + _source[xPos + w, yPos + h] += src[x1 + w, y1 + h]; + } + } + + return TsObject.Empty(); + } + + public TsObject add_region(ITsInstance inst, params TsObject[] args) + { + _source.OverRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], (w, h, g) => g[w, h] += args[4]); + return TsObject.Empty(); + } + + public TsObject clear(ITsInstance inst, params TsObject[] args) + { + _source.Clear(args[0]); + return TsObject.Empty(); + } + + public TsObject copy(ITsInstance inst, params TsObject[] args) + { + return new TsGrid(_source); + } + + public TsObject get_disk_max(ITsInstance inst, params TsObject[] args) + { + TsObject i = TsObject.Empty(); + var set = false; + _source.OverDisk((int)args[0], (int)args[1], (int)args[2], (w, h, g) => + { + if (!set) + { + i = g[w, h]; + set = true; + } + else + { + var current = g[w, h]; + if (current > i) + i = current; + } + }); + return i; + } + + public TsObject get_disk_mean(ITsInstance inst, params TsObject[] args) + { + var mean = new TsObject(0); + var iter = 0; + _source.OverDisk((int)args[0], (int)args[1], (int)args[2], (w, h, g) => + { + iter++; + mean += g[w, h]; + }); + return mean / iter; + } + + public TsObject get_disk_min(ITsInstance inst, params TsObject[] args) + { + bool set = false; + TsObject i = TsObject.Empty(); + _source.OverDisk((int)args[0], (int)args[1], (int)args[2], (w, h, g) => + { + if (!set) + { + i = g[w, h]; + set = true; + } + else + { + var current = g[w, h]; + if (current < i) + i = current; + } + }); + return i; + } + + public TsObject get_disk_sum(ITsInstance inst, params TsObject[] args) + { + var mean = new TsObject(0); + _source.OverDisk((int)args[0], (int)args[1], (int)args[2], (w, h, g) => + { + mean += g[w, h]; + }); + return mean; + } + + public TsObject get_region_max(ITsInstance inst, params TsObject[] args) + { + TsObject i = TsObject.Empty(); + var set = false; + _source.OverRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], (w, h, g) => + { + if (!set) + { + i = g[w, h]; + set = true; + } + else + { + var current = g[w, h]; + if (current > i) + i = current; + } + }); + return i; + } + + public TsObject get_region_mean(ITsInstance inst, params TsObject[] args) + { + var mean = new TsObject(0); + var iter = 0; + _source.OverRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], (w, h, g) => + { + iter++; + mean += g[w, h]; + }); + return mean / iter; + } + + public TsObject get_region_min(ITsInstance inst, params TsObject[] args) + { + bool set = false; + TsObject i = TsObject.Empty(); + _source.OverRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], (w, h, g) => + { + if (!set) + { + i = g[w, h]; + set = true; + } + else + { + var current = g[w, h]; + if (current < i) + i = current; + } + }); + return i; + } + + public TsObject get_region_sum(ITsInstance inst, params TsObject[] args) + { + var sum = new TsObject(0); + _source.OverRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], (w, h, g) => + { + sum += g[w, h]; + }); + return sum; + } + + public TsObject multiply_disk(ITsInstance inst, params TsObject[] args) + { + _source.OverDisk((int)args[0], (int)args[1], (int)args[2], (w, h, g) => g[w, h] *= args[3]); + return TsObject.Empty(); + } + + public TsObject multiply_grid_region(ITsInstance inst, params TsObject[] args) + { + var src = ((TsGrid)args[0]).Source; + var x1 = (int)args[1]; + var y1 = (int)args[2]; + var x2 = (int)args[2]; + var y2 = (int)args[3]; + var xPos = (int)args[4]; + var yPos = (int)args[5]; + var xLength = x2 - x1; + var yLength = y2 - y1; + + if (x1 < 0) + throw new ArgumentOutOfRangeException(nameof(x1)); + if (x2 >= src.Width) + throw new ArgumentOutOfRangeException(nameof(x2)); + if (y1 < 0) + throw new ArgumentOutOfRangeException(nameof(y1)); + if (y2 >= src.Height) + throw new ArgumentOutOfRangeException(nameof(y2)); + if (xPos < 0 || xPos + xLength >= _source.Width) + throw new ArgumentOutOfRangeException(nameof(xPos)); + if (yPos < 0 || yPos + yLength >= _source.Height) + throw new ArgumentOutOfRangeException(nameof(yPos)); + + for (var w = 0; w < xLength; w++) + { + for (var h = 0; h < yLength; h++) + { + _source[xPos + w, yPos + h] *= src[x1 + w, y1 + h]; + } + } + + return TsObject.Empty(); + } + + public TsObject multiply_region(ITsInstance inst, params TsObject[] args) + { + _source.OverRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], (w, h, g) => g[w, h] *= args[4]); + return TsObject.Empty(); + } + + public TsObject set_disk(ITsInstance inst, params TsObject[] args) + { + _source.OverDisk((int)args[0], (int)args[1], (int)args[2], (w, h, g) => g[w, h] *= args[3]); + return TsObject.Empty(); + } + + public TsObject set_grid_region(ITsInstance inst, params TsObject[] args) + { + var src = ((TsGrid)args[0]).Source; + var x1 = (int)args[1]; + var y1 = (int)args[2]; + var x2 = (int)args[2]; + var y2 = (int)args[3]; + var xPos = (int)args[4]; + var yPos = (int)args[5]; + var xLength = x2 - x1; + var yLength = y2 - y1; + + if (x1 < 0) + throw new ArgumentOutOfRangeException(nameof(x1)); + if (x2 >= src.Width) + throw new ArgumentOutOfRangeException(nameof(x2)); + if (y1 < 0) + throw new ArgumentOutOfRangeException(nameof(y1)); + if (y2 >= src.Height) + throw new ArgumentOutOfRangeException(nameof(y2)); + if (xPos < 0 || xPos + xLength >= _source.Width) + throw new ArgumentOutOfRangeException(nameof(xPos)); + if (yPos < 0 || yPos + yLength >= _source.Height) + throw new ArgumentOutOfRangeException(nameof(yPos)); + + for (var w = 0; w < xLength; w++) + { + for (var h = 0; h < yLength; h++) + { + _source[xPos + w, yPos + h] = src[x1 + w, y1 + h]; + } + } + + return TsObject.Empty(); + } + + public TsObject set_region(ITsInstance inst, params TsObject[] args) + { + _source.OverRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], (w, h, g) => g[w, h] = args[4]); + return TsObject.Empty(); + } + + public TsObject resize(ITsInstance inst, params TsObject[] args) + { + _source.Resize((int)args[0], (int)args[1]); + return TsObject.Empty(); + } + + public TsObject shuffle(ITsInstance inst, params TsObject[] args) + { + _source.Shuffle(); + return TsObject.Empty(); + } + + public TsObject sort(ITsInstance inst, params TsObject[] args) + { + _source.Sort((int)args[0], (bool)args[1]); + return TsObject.Empty(); + } + + public TsObject value_exists_in_disk(ITsInstance inst, params TsObject[] args) + { + return _source.InDisk((int)args[0], (int)args[1], (int)args[2], args[3]); + } + + public TsObject value_position_in_disk(ITsInstance inst, params TsObject[] args) + { + if (_source.InDisk((int)args[0], (int)args[1], (int)args[2], args[3], out var result, (w, h) => new TsObject[] { w, h })) + return result; + return TsObject.Empty(); + } + + public TsObject value_exists_in_region(ITsInstance inst, params TsObject[] args) + { + return _source.InRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], args[4]); + } + + public TsObject value_position_in_region(ITsInstance inst, params TsObject[] args) + { + if (_source.InRegion((int)args[0], (int)args[1], (int)args[2], (int)args[3], args[4], out var result, (w, h) => new TsObject[] { w, h })) + return result; + return TsObject.Empty(); + } + } +} diff --git a/TaffyScript/Collections/TsList.cs b/TaffyScript/Collections/TsList.cs index 62630f8..3ef96d5 100644 --- a/TaffyScript/Collections/TsList.cs +++ b/TaffyScript/Collections/TsList.cs @@ -6,9 +6,10 @@ namespace TaffyScript.Collections { +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public class TsList : ITsInstance { - private List _source = new List(); + private List _source; public TsObject this[string memberName] { @@ -17,13 +18,18 @@ public TsObject this[string memberName] } public string ObjectType => "ds_list"; + public List Source => _source; public event DestroyedDelegate Destroyed; - public List Source => _source; - public TsList(TsObject[] args) { + _source = new List(); + } + + public TsList(IEnumerable source) + { + _source = new List(source); } public TsObject Call(string scriptName, params TsObject[] args) @@ -36,6 +42,8 @@ public TsObject Call(string scriptName, params TsObject[] args) case "clear": _source.Clear(); break; + case "copy": + return new TsList(_source); case "get": return _source[(int)args[0]]; case "insert": @@ -100,6 +108,9 @@ public bool TryGetDelegate(string scriptName, out TsDelegate del) case "clear": del = new TsDelegate(clear, "clear", this); return true; + case "copy": + del = new TsDelegate(copy, "copy", this); + return true; case "get": del = new TsDelegate(get, "get", this); return true; @@ -121,6 +132,18 @@ public bool TryGetDelegate(string scriptName, out TsDelegate del) } } + public static explicit operator TsList(TsObject obj) + { + return (TsList)obj.Value.WeakValue; + } + + public static implicit operator TsObject(TsList list) + { + return new TsObject(list); + } + +#pragma warning disable IDE1006 // Naming Styles + public TsObject add(ITsInstance inst, TsObject[] args) { _source.AddRange(args); @@ -133,6 +156,11 @@ public TsObject clear(ITsInstance inst, TsObject[] args) return TsObject.Empty(); } + public TsObject copy(ITsInstance inst, TsObject[] args) + { + return new TsList(_source); + } + public TsObject get(ITsInstance inst, TsObject[] args) { return _source[(int)args[0]]; diff --git a/TaffyScript/Collections/TsMap.cs b/TaffyScript/Collections/TsMap.cs new file mode 100644 index 0000000..6778244 --- /dev/null +++ b/TaffyScript/Collections/TsMap.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScript.Collections +{ +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + public class TsMap : ITsInstance + { + private Dictionary _source = new Dictionary(); + + public TsObject this[string memberName] + { + get => GetMember(memberName); + set => SetMember(memberName, value); + } + + public string ObjectType => "ds_map"; + public Dictionary Source => _source; + + public event DestroyedDelegate Destroyed; + + public TsMap(TsObject[] args) + { + } + + public TsMap(Dictionary source) + { + _source = new Dictionary(source); + } + + public TsObject Call(string scriptName, params TsObject[] args) + { + switch(scriptName) + { + case "get": + if (_source.TryGetValue(args[0], out var result)) + return result; + break; + case "set": + _source[args[0]] = args[1]; + break; + case "add": + if (_source.ContainsKey(args[0])) + return false; + _source.Add(args[0], args[1]); + return true; + case "clear": + _source.Clear(); + break; + case "remove": + return _source.Remove(args[0]); + case "contains_key": + return _source.ContainsKey(args[0]); + case "copy": + return new TsMap(_source); + default: + throw new MemberAccessException($"The type {ObjectType} does not define a script called {scriptName}"); + } + return TsObject.Empty(); + } + + public void Destroy() + { + Destroyed?.Invoke(this); + _source = null; + } + + public TsDelegate GetDelegate(string delegateName) + { + if (TryGetDelegate(delegateName, out var del)) + return del; + + throw new MemberAccessException($"The type {ObjectType} does not define a script called {delegateName}"); + } + + public TsObject GetMember(string name) + { + switch(name) + { + case "count": + return _source.Count; + case "keys": + return _source.Keys.ToArray(); + default: + if (TryGetDelegate(name, out var del)) + return del; + throw new MemberAccessException($"Couldn't find member with the name {name}"); + } + } + + public void SetMember(string name, TsObject value) + { + throw new MemberAccessException($"Member {name} on type {ObjectType} is readonly"); + } + + public bool TryGetDelegate(string delegateName, out TsDelegate del) + { + switch(delegateName) + { + case "get": + del = new TsDelegate(get, "get", this); + return true; + case "set": + del = new TsDelegate(set, "set", this); + return true; + case "add": + del = new TsDelegate(add, "add", this); + return true; + case "clear": + del = new TsDelegate(clear, "clear", this); + return true; + case "remove": + del = new TsDelegate(remove, "remove", this); + return true; + case "contains_key": + del = new TsDelegate(contains_key, "contains_key", this); + return true; + default: + del = null; + return false; + } + } + + public static explicit operator TsMap(TsObject obj) + { + return (TsMap)obj.Value.WeakValue; + } + + public static implicit operator TsObject(TsMap map) + { + return new TsObject(map); + } + +#pragma warning disable IDE1006 // Naming Styles + + public TsObject get(ITsInstance inst, params TsObject[] args) + { + return _source[args[0]]; + } + + public TsObject set(ITsInstance inst, params TsObject[] args) + { + _source[args[0]] = args[1]; + return TsObject.Empty(); + } + + public TsObject add(ITsInstance inst, params TsObject[] args) + { + if (_source.ContainsKey(args[0])) + return false; + + _source.Add(args[0], args[1]); + return true; + } + + public TsObject clear(ITsInstance inst, params TsObject[] args) + { + _source.Clear(); + return TsObject.Empty(); + } + + public TsObject remove(ITsInstance inst, params TsObject[] args) + { + return _source.Remove(args[0]); + } + + public TsObject contains_key(ITsInstance inst, params TsObject[] args) + { + return _source.ContainsKey(args[0]); + } + + public TsObject copy(ITsInstance inst, params TsObject[] args) + { + return new TsMap(_source); + } + } +} diff --git a/TaffyScript/TaffyScript.csproj b/TaffyScript/TaffyScript.csproj index 5b80b84..09915f0 100644 --- a/TaffyScript/TaffyScript.csproj +++ b/TaffyScript/TaffyScript.csproj @@ -51,7 +51,9 @@ + + diff --git a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs b/TaffyScriptCompiler/Backend/BaseClassLibrary.cs index fe75784..665f460 100644 --- a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs +++ b/TaffyScriptCompiler/Backend/BaseClassLibrary.cs @@ -195,6 +195,8 @@ public static string Generate() sb.AppendLine("namespace TaffyScript.Collections {"); sb.AppendLine("import object TsList as ds_list"); + sb.AppendLine("import object TsMap as ds_map"); + sb.AppendLine("import object TsGrid as ds_grid"); sb.AppendLine("}"); return sb.ToString(); diff --git a/TaffyScriptCompiler/Front End/Parser.cs b/TaffyScriptCompiler/Front End/Parser.cs index 6ce6690..998590f 100644 --- a/TaffyScriptCompiler/Front End/Parser.cs +++ b/TaffyScriptCompiler/Front End/Parser.cs @@ -1226,7 +1226,7 @@ private string GetNamespace() var name = first.Value; while (Validate(TokenType.Dot)) { - name += TokenType.Dot; + name += "."; name += Confirm(TokenType.Identifier).Value; } diff --git a/TaffyScriptCompiler/Program.cs b/TaffyScriptCompiler/Program.cs index 63b91cd..1eed878 100644 --- a/TaffyScriptCompiler/Program.cs +++ b/TaffyScriptCompiler/Program.cs @@ -26,8 +26,6 @@ static void Main(string[] args) if (extra.Count != 0) path = extra[0]; - path = @"C:\Users\Chris\Source\Repos\GmParser\Samples\TestSuite\Tests"; - if (generateBuild) { var build = new BuildConfig(); From 8e2728c228d7dd56d7f0402e680e973ac3f139e8 Mon Sep 17 00:00:00 2001 From: mystborn Date: Wed, 2 May 2018 10:22:49 -0700 Subject: [PATCH 14/54] Full Get/Set Access Implementation --- Samples/TestSuite/Tests/map.tfs | 147 +++ Samples/TestSuite/Tests/tests.tfs | 2 + Samples/TestSuite/UnitTestLib/unit_test.tfs | 2 +- TaffyScript/TsObject.cs | 1 + .../Backend/Compiler/MsilWeakCodeGen.cs | 857 +++++++++++------- 5 files changed, 700 insertions(+), 309 deletions(-) create mode 100644 Samples/TestSuite/Tests/map.tfs diff --git a/Samples/TestSuite/Tests/map.tfs b/Samples/TestSuite/Tests/map.tfs new file mode 100644 index 0000000..792d56b --- /dev/null +++ b/Samples/TestSuite/Tests/map.tfs @@ -0,0 +1,147 @@ +using UnitTest; +using TaffyScript.Collections; + +namespace LanguageTests { + script run_map_tests() { + var tests = new obj_unit_test("Map Tests", + map_create, + map_add_new, + map_add_duplicate, + map_clear, + map_remove_true, + map_remove_false, + map_contains_key_true, + map_contains_key_false, + map_copy, + map_keys_some, + map_keys_none, + map_get_script, + map_get_access, + map_set_script, + map_set_access); + + tests.run_tests(); + } + + script map_create() { + test_it("var m = new ds_map()"); + var map = new ds_map(); + assert_equal(object_get_name(map), "ds_map"); + } + + script map_add_new() { + test_it("map.add(key (uniq), val)"); + var map = new ds_map(); + assert(map.add("key", "val")); + assert_equal(map.count, 1); + } + + script map_add_duplicate() { + test_it("map.add(key (dup), val)"); + var map = new ds_map(); + assert(map.add("key", 4)); + assert_is_false(map.add("key", "val")); + assert_equal(map.count, 1); + } + + script map_clear() { + test_it("map.clear()"); + var map = new ds_map(); + map.add(0, 2); + map.add("moo", "cow"); + assert_equal(map.count, 2); + map.clear(); + assert_equal(map.count, 0); + } + + script map_remove_true() { + test_it("map.remove(key) == true"); + var map = new ds_map(); + map.add(0, 2); + map.add("moo", "cow"); + assert_equal(map.count, 2); + assert(map.remove(0)); + assert_equal(map.count, 1); + } + + script map_remove_false() { + test_it("map.remove(key) == false"); + var map = new ds_map(); + map.add(0, 2); + map.add("moo", "cow"); + assert_equal(map.count, 2); + assert_is_false(map.remove(1)); + assert_equal(map.count, 2); + } + + script map_contains_key_true() { + test_it("map.contains_key(key) == true"); + var map = new ds_map(); + map.add(0, 2); + map.add("moo", "cow"); + assert(map.contains_key("moo")); + } + + script map_contains_key_false() { + test_it("map.contains_key(key) == false"); + var map = new ds_map(); + map.add(0, 2); + map.add("moo", "cow"); + assert_is_false(map.contains_key("cow")); + } + + script map_copy() { + test_it("map.copy()"); + var map = new ds_map(); + map.add(0, 2); + map.add("moo", "cow"); + var copy = map.copy(); + assert_equal(map.count, 2); + assert_equal(map.count, copy.count); + assert_is_false(map == copy); + } + + script map_keys_some() { + test_it("map.keys.length > 0"); + var map = new ds_map(); + map.add(0, 2); + map.add("moo", "cow"); + var keys = map.keys; + assert_equal(array_length_1d(keys), 2); + } + + script map_keys_none() { + test_it("map.keys.length == 0"); + var map = new ds_map(); + var keys = map.keys; + assert_equal(array_length_1d(keys), 0); + } + + script map_get_script() { + test_it("map.get(key)"); + var map = new ds_map(); + map.add("moo", "cow"); + assert_equal(map.get("moo"), "cow"); + } + + script map_get_access() { + test_it("val = map[key]"); + var map = new ds_map(); + map.add("moo", "cow"); + assert_equal(map["moo"], "cow"); + } + + script map_set_script() { + test_it("map.set(key, val)"); + var map = new ds_map(); + map.set("moo", "cow"); + assert_equal(map["moo"], "cow"); + } + + script map_set_access() { + test_it("map[key] = val"); + var map = new ds_map(); + map["moo"] = "cow"; + assert_equal(map["moo"], "cow"); + } +} \ No newline at end of file diff --git a/Samples/TestSuite/Tests/tests.tfs b/Samples/TestSuite/Tests/tests.tfs index 076a275..8463990 100644 --- a/Samples/TestSuite/Tests/tests.tfs +++ b/Samples/TestSuite/Tests/tests.tfs @@ -24,6 +24,8 @@ namespace LanguageTests { show_debug_message(""); run_list_tests(); show_debug_message(""); + run_map_tests(); + show_debug_message(""); } script timer_entry { diff --git a/Samples/TestSuite/UnitTestLib/unit_test.tfs b/Samples/TestSuite/UnitTestLib/unit_test.tfs index d5accf0..761c96e 100644 --- a/Samples/TestSuite/UnitTestLib/unit_test.tfs +++ b/Samples/TestSuite/UnitTestLib/unit_test.tfs @@ -134,7 +134,7 @@ namespace UnitTest { var msg = argument0; show_debug_message(msg); show_debug_message(global._unit_test.test_description); - show_debug_message("In suite " + test_suite); + show_debug_message("In suite " + global._unit_test.test_suite); global._unit_test.tests_failed = true; } diff --git a/TaffyScript/TsObject.cs b/TaffyScript/TsObject.cs index 9891e91..e8ddae8 100644 --- a/TaffyScript/TsObject.cs +++ b/TaffyScript/TsObject.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using TaffyScript.Collections; namespace TaffyScript { diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index 791fb60..5999027 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -1064,6 +1064,13 @@ private void ConvertTopToObject(ILEmitter emitter) } } + private void LogError(Exception exception, bool loadEmptyObject = true) + { + _errors.Add(exception); + if (loadEmptyObject) + emit.Call(TsTypes.Empty); + } + #endregion #region Visitor @@ -1096,14 +1103,14 @@ public void Visit(AdditiveNode additive) } else if (right == typeof(string)) { - _errors.Add(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}")); + LogError(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}"), false); return; } else if (right == typeof(TsObject)) emit.Call(GetOperator(additive.Text, left, right, additive.Position)); else { - _errors.Add(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}")); + LogError(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}"), false); return; } } @@ -1111,12 +1118,12 @@ public void Visit(AdditiveNode additive) { if (additive.Text != "+") { - _errors.Add(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}")); + LogError(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}"), false); return; } if (right == typeof(float)) { - _errors.Add(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}")); + LogError(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}"), false); return; } else if(right == typeof(string)) @@ -1134,12 +1141,17 @@ public void Visit(AdditiveNode additive) public void Visit(ArgumentAccessNode argumentAccess) { emit.LdArg(1); - if(argumentAccess.Index is IConstantToken index) + if (argumentAccess.Index is IConstantToken index) { emit.LdInt((int)index.Value); } - else if(!TryLoadElementAsInt(argumentAccess.Index)) - _errors.Add(new CompileException($"Invalid argument access {argumentAccess.Position}")); + else if (!TryLoadElementAsInt(argumentAccess.Index)) + { + emit.Pop() + .Call(TsTypes.Empty); + LogError(new CompileException($"Invalid argument access {argumentAccess.Position}"), false); + return; + } if (_needAddress) @@ -1164,66 +1176,107 @@ public void Visit(ArrayAccessNode arrayAccess) } else if (top != typeof(TsObject).MakePointerType()) { - _errors.Add(new CompileException($"Encountered invalid syntax {arrayAccess.Position}")); + LogError(new CompileException($"Encountered invalid syntax {arrayAccess.Position}"), false); return; } - var isArray = emit.DefineLabel(); - var end = emit.DefineLabel(); - - emit.Dup() - .Call(typeof(TsObject).GetMethod("get_Type")) - .LdInt((int)VariableType.Instance) - .Bne(isArray) - .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) - .LdStr("get") - .LdInt(arrayAccess.Children.Count - 1) - .NewArr(typeof(TsObject)); - - for(var i = 1; i < arrayAccess.Children.Count; i++) + if (CanBeArrayAccess(arrayAccess)) { + var isArray = emit.DefineLabel(); + var end = emit.DefineLabel(); + emit.Dup() - .LdInt(i - 1); - arrayAccess.Children[i].Accept(this); - ConvertTopToObject(); - emit.StElem(typeof(TsObject)); - } + .Call(typeof(TsObject).GetMethod("get_Type")) + .LdInt((int)VariableType.Instance) + .Bne(isArray) + .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .LdStr("get") + .LdInt(arrayAccess.Children.Count - 1) + .NewArr(typeof(TsObject)); - emit.Call(typeof(ITsInstance).GetMethod("Call")); - if(address) - { - secret = GetLocal(); - emit.StLocal(secret) - .LdLocalA(secret); - FreeLocal(secret); - } + for (var i = 1; i < arrayAccess.Children.Count; i++) + { + emit.Dup() + .LdInt(i - 1); + arrayAccess.Children[i].Accept(this); + ConvertTopToObject(); + emit.StElem(typeof(TsObject)); + } + + emit.Call(typeof(ITsInstance).GetMethod("Call")); + if (address) + { + secret = GetLocal(); + emit.StLocal(secret) + .LdLocalA(secret); + FreeLocal(secret); + } - emit.Br(end) - .MarkLabel(isArray) - .PopTop() //The stack would get imbalanced here otherwise. - .PushType(typeof(TsObject).MakePointerType()); + emit.Br(end) + .MarkLabel(isArray) + .PopTop() //The stack would get imbalanced here otherwise. + .PushType(typeof(TsObject).MakePointerType()); - CallInstanceMethod(TsTypes.ObjectCasts[arrayAccess.Children.Count == 2 ? typeof(TsObject[]) : typeof(TsObject[][])], arrayAccess.Position); - LoadElementAsInt(arrayAccess.Children[1]); + CallInstanceMethod(TsTypes.ObjectCasts[arrayAccess.Children.Count == 2 ? typeof(TsObject[]) : typeof(TsObject[][])], arrayAccess.Position); + LoadElementAsInt(arrayAccess.Children[1]); - if(arrayAccess.Children.Count == 2) - { - if (address) - emit.LdElemA(typeof(TsObject)); + if (arrayAccess.Children.Count == 2) + { + if (address) + emit.LdElemA(typeof(TsObject)); + else + emit.LdElem(typeof(TsObject)); + } else - emit.LdElem(typeof(TsObject)); + { + emit.LdElem(typeof(TsObject[])); + LoadElementAsInt(arrayAccess.Children[2]); + + if (address) + emit.LdElemA(typeof(TsObject)); + else + emit.LdElem(typeof(TsObject)); + } + emit.MarkLabel(end); } else { - emit.LdElem(typeof(TsObject[])); - LoadElementAsInt(arrayAccess.Children[2]); + emit.Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .LdStr("get") + .LdInt(arrayAccess.Children.Count - 1) + .NewArr(typeof(TsObject)); + + for (var i = 1; i < arrayAccess.Children.Count; i++) + { + emit.Dup() + .LdInt(i - 1); + arrayAccess.Children[i].Accept(this); + ConvertTopToObject(); + emit.StElem(typeof(TsObject)); + } + emit.Call(typeof(ITsInstance).GetMethod("Call")); if (address) - emit.LdElemA(typeof(TsObject)); - else - emit.LdElem(typeof(TsObject)); + { + secret = GetLocal(); + emit.StLocal(secret) + .LdLocalA(secret); + FreeLocal(secret); + } } - emit.MarkLabel(end); + } + + private bool CanBeArrayAccess(ArrayAccessNode array) + { + if (array.Indeces.Count > 2) + return false; + + foreach(var node in array.Indeces) + { + if (node is IConstantToken constant && (constant.ConstantType == ConstantType.Bool || constant.ConstantType == ConstantType.String)) + return false; + } + return true; } public void Visit(ArrayLiteralNode arrayLiteral) @@ -1250,7 +1303,7 @@ public void Visit(AssignNode assign) return; } - if(assign.Left is ArgumentAccessNode arg) + if (assign.Left is ArgumentAccessNode arg) { GetAddressIfPossible(arg); assign.Right.Accept(this); @@ -1261,65 +1314,91 @@ public void Visit(AssignNode assign) { //Here we have to resize the array if needed, so more work needs to be done. GetAddressIfPossible(array.Left); - if (emit.GetTop() == typeof(TsObject)) + var top = emit.GetTop(); + if (top == typeof(TsObject)) { var secret = GetLocal(); emit.StLocal(secret) .LdLocalA(secret); FreeLocal(secret); } - var isArray = emit.DefineLabel(); - var end = emit.DefineLabel(); - - emit.Dup() - .Call(typeof(TsObject).GetMethod("get_Type")) - .LdInt((int)VariableType.Instance) - .Bne(isArray) - .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) - .LdStr("set") - .LdInt(array.Indeces.Count + 1) - .NewArr(typeof(TsObject)); + else if (top != typeof(TsObject).MakePointerType()) + { + LogError(new CompileException($"Encountered invalid syntax {array.Position}"), false); + return; + } - for(var i = 0; i < array.Indeces.Count; i++) + if (CanBeArrayAccess(array)) { + + var isArray = emit.DefineLabel(); + var end = emit.DefineLabel(); + emit.Dup() - .LdInt(i); - array.Indeces[i].Accept(this); + .Call(typeof(TsObject).GetMethod("get_Type")) + .LdInt((int)VariableType.Instance) + .Bne(isArray) + .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .LdStr("set") + .LdInt(array.Indeces.Count + 1) + .NewArr(typeof(TsObject)); + + for (var i = 0; i < array.Indeces.Count; i++) + { + emit.Dup() + .LdInt(i); + array.Indeces[i].Accept(this); + ConvertTopToObject(); + emit.StElem(typeof(TsObject)); + } + emit.Dup() + .LdInt(array.Indeces.Count); + assign.Right.Accept(this); ConvertTopToObject(); - emit.StElem(typeof(TsObject)); - } - emit.Dup() - .LdInt(array.Indeces.Count); - assign.Right.Accept(this); - ConvertTopToObject(); - emit.StElem(typeof(TsObject)) - .Call(typeof(ITsInstance).GetMethod("Call")) - .Pop() - .Br(end) - .PushType(typeof(TsObject).MakePointerType()) - .MarkLabel(isArray); + emit.StElem(typeof(TsObject)) + .Call(typeof(ITsInstance).GetMethod("Call")) + .Pop() + .Br(end) + .PushType(typeof(TsObject).MakePointerType()) + .MarkLabel(isArray); - var argTypes = new Type[array.Indeces.Count + 1]; + var argTypes = new Type[array.Indeces.Count + 1]; - if(array.Indeces.Count > 2) - { - _errors.Add(new CompileException("Cannot access array with a rank greater then 2")); - emit.Pop() - .Call(TsTypes.Empty); - return; - } + for (var i = 0; i < array.Indeces.Count; i++) + { + LoadElementAsInt(array.Indeces[i]); + argTypes[i] = typeof(int); + } - for (var i = 0; i < array.Indeces.Count; i++) - { - LoadElementAsInt(array.Indeces[i]); - argTypes[i] = typeof(int); + assign.Right.Accept(this); + ConvertTopToObject(); + argTypes[argTypes.Length - 1] = typeof(TsObject); + emit.Call(typeof(TsObject).GetMethod("ArraySet", argTypes)) + .MarkLabel(end); } + else + { + emit.Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .LdStr("set") + .LdInt(array.Indeces.Count + 1) + .NewArr(typeof(TsObject)); - assign.Right.Accept(this); - ConvertTopToObject(); - argTypes[argTypes.Length - 1] = typeof(TsObject); - emit.Call(typeof(TsObject).GetMethod("ArraySet", argTypes)) - .MarkLabel(end); + for (var i = 0; i < array.Indeces.Count; i++) + { + emit.Dup() + .LdInt(i); + array.Indeces[i].Accept(this); + ConvertTopToObject(); + emit.StElem(typeof(TsObject)); + } + emit.Dup() + .LdInt(array.Indeces.Count); + assign.Right.Accept(this); + ConvertTopToObject(); + emit.StElem(typeof(TsObject)) + .Call(typeof(ITsInstance).GetMethod("Call")) + .Pop(); + } } else if(assign.Left is ListAccessNode list) { @@ -1461,90 +1540,143 @@ private void ProcessAssignExtra(AssignNode assign) } else if (top != typeof(TsObject).MakePointerType()) { - _errors.Add(new CompileException($"Encountered invalid syntax {array.Position}")); - emit.Call(TsTypes.Empty); + LogError(new CompileException($"Encountered invalid syntax {array.Position}"), false); return; } - var isArray = emit.DefineLabel(); - var end = emit.DefineLabel(); - secret = GetLocal(typeof(ITsInstance)); - - emit.Dup() - .Call(typeof(TsObject).GetMethod("get_Type")) - .LdInt((int)VariableType.Instance) - .Bne(isArray) - .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) - .StLocal(secret) - .LdLocal(secret) - .LdStr("get") - .LdInt(array.Indeces.Count) - .NewArr(typeof(TsObject)); - - var indeces = new LocalBuilder[array.Indeces.Count]; - for (var i = 0; i < array.Indeces.Count; i++) + if (CanBeArrayAccess(array)) { + var isArray = emit.DefineLabel(); + var end = emit.DefineLabel(); + secret = GetLocal(typeof(ITsInstance)); + emit.Dup() - .LdInt(i); - array.Indeces[i].Accept(this); - ConvertTopToObject(); - indeces[i] = GetLocal(); - emit.Dup() - .StLocal(indeces[i]) - .StElem(typeof(TsObject)); - } + .Call(typeof(TsObject).GetMethod("get_Type")) + .LdInt((int)VariableType.Instance) + .Bne(isArray) + .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .StLocal(secret) + .LdLocal(secret) + .LdStr("get") + .LdInt(array.Indeces.Count) + .NewArr(typeof(TsObject)); - emit.Call(typeof(ITsInstance).GetMethod("Call")); - assign.Right.Accept(this); - emit.Call(GetOperator(op, typeof(TsObject), emit.GetTop(), assign.Position)) - .StLocal(value) - .LdLocal(secret) - .LdStr("set") - .LdInt(indeces.Length + 1) - .NewArr(typeof(TsObject)); + var indeces = new LocalBuilder[array.Indeces.Count]; + for (var i = 0; i < array.Indeces.Count; i++) + { + emit.Dup() + .LdInt(i); + array.Indeces[i].Accept(this); + ConvertTopToObject(); + indeces[i] = GetLocal(); + emit.Dup() + .StLocal(indeces[i]) + .StElem(typeof(TsObject)); + } - FreeLocal(secret); + emit.Call(typeof(ITsInstance).GetMethod("Call")); + assign.Right.Accept(this); + emit.Call(GetOperator(op, typeof(TsObject), emit.GetTop(), assign.Position)) + .StLocal(value) + .LdLocal(secret) + .LdStr("set") + .LdInt(indeces.Length + 1) + .NewArr(typeof(TsObject)); - for(var i = 0; i < indeces.Length; i++) - { + FreeLocal(secret); + + for (var i = 0; i < indeces.Length; i++) + { + emit.Dup() + .LdInt(i) + .LdLocal(indeces[i]) + .StElem(typeof(TsObject)); + FreeLocal(indeces[i]); + } emit.Dup() - .LdInt(i) - .LdLocal(indeces[i]) - .StElem(typeof(TsObject)); - FreeLocal(indeces[i]); - } - emit.Dup() - .LdInt(indeces.Length) - .LdLocal(value) - .StElem(typeof(TsObject)) - .Call(typeof(ITsInstance).GetMethod("Call")) - .Pop() - .Br(end) - .PushType(typeof(TsObject).MakePointerType()) - .MarkLabel(isArray); + .LdInt(indeces.Length) + .LdLocal(value) + .StElem(typeof(TsObject)) + .Call(typeof(ITsInstance).GetMethod("Call")) + .Pop() + .Br(end) + .PushType(typeof(TsObject).MakePointerType()) + .MarkLabel(isArray); - FreeLocal(value); + FreeLocal(value); - CallInstanceMethod(TsTypes.ObjectCasts[array.Children.Count == 2 ? typeof(TsObject[]) : typeof(TsObject[][])], array.Position); - LoadElementAsInt(array.Children[1]); + CallInstanceMethod(TsTypes.ObjectCasts[array.Children.Count == 2 ? typeof(TsObject[]) : typeof(TsObject[][])], array.Position); + LoadElementAsInt(array.Children[1]); - if (array.Children.Count == 2) - { - emit.LdElemA(typeof(TsObject)); - } - else - { - emit.LdElem(typeof(TsObject[])); - LoadElementAsInt(array.Children[2]); - emit.LdElemA(typeof(TsObject)); - } - emit.Dup() - .LdObj(typeof(TsObject)); - assign.Right.Accept(this); - emit.Call(GetOperator(op, typeof(TsObject), emit.GetTop(), assign.Position)) - .StObj(typeof(TsObject)) - .MarkLabel(end); - } + if (array.Children.Count == 2) + { + emit.LdElemA(typeof(TsObject)); + } + else + { + emit.LdElem(typeof(TsObject[])); + LoadElementAsInt(array.Children[2]); + emit.LdElemA(typeof(TsObject)); + } + emit.Dup() + .LdObj(typeof(TsObject)); + assign.Right.Accept(this); + emit.Call(GetOperator(op, typeof(TsObject), emit.GetTop(), assign.Position)) + .StObj(typeof(TsObject)) + .MarkLabel(end); + } + else + { + secret = GetLocal(typeof(ITsInstance)); + emit.Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .StLocal(secret) + .LdLocal(secret) + .LdStr("get") + .LdInt(array.Indeces.Count) + .NewArr(typeof(TsObject)); + + var indeces = new LocalBuilder[array.Indeces.Count]; + for (var i = 0; i < array.Indeces.Count; i++) + { + emit.Dup() + .LdInt(i); + array.Indeces[i].Accept(this); + ConvertTopToObject(); + indeces[i] = GetLocal(); + emit.Dup() + .StLocal(indeces[i]) + .StElem(typeof(TsObject)); + } + + emit.Call(typeof(ITsInstance).GetMethod("Call")); + assign.Right.Accept(this); + emit.Call(GetOperator(op, typeof(TsObject), emit.GetTop(), assign.Position)) + .StLocal(value) + .LdLocal(secret) + .LdStr("set") + .LdInt(indeces.Length + 1) + .NewArr(typeof(TsObject)); + + FreeLocal(secret); + + for (var i = 0; i < indeces.Length; i++) + { + emit.Dup() + .LdInt(i) + .LdLocal(indeces[i]) + .StElem(typeof(TsObject)); + FreeLocal(indeces[i]); + } + emit.Dup() + .LdInt(indeces.Length) + .LdLocal(value) + .StElem(typeof(TsObject)) + .Call(typeof(ITsInstance).GetMethod("Call")) + .Pop(); + + FreeLocal(value); + } + } else if (assign.Left is ListAccessNode list) { ListAccessSet(list, 2); @@ -2764,9 +2896,9 @@ public void Visit(ObjectNode objectNode) public void Visit(PostfixNode postfix) { - var secret = GetLocal(); if (postfix.Child.Type == SyntaxType.ArgumentAccess) { + var secret = GetLocal(); GetAddressIfPossible(postfix.Child); emit.Dup() .Dup() @@ -2776,6 +2908,7 @@ public void Visit(PostfixNode postfix) .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) .StObj(typeof(TsObject)) .LdLocal(secret); + FreeLocal(secret); } else if(postfix.Child.Type == SyntaxType.ArrayAccess) { @@ -2787,10 +2920,10 @@ public void Visit(PostfixNode postfix) var top = emit.GetTop(); if (top == typeof(TsObject)) { - secret = GetLocal(); - emit.StLocal(secret) - .LdLocalA(secret); - FreeLocal(secret); + var temp = GetLocal(); + emit.StLocal(temp) + .LdLocalA(temp); + FreeLocal(temp); } else if (top != typeof(TsObject).MakePointerType()) { @@ -2798,95 +2931,147 @@ public void Visit(PostfixNode postfix) emit.Call(TsTypes.Empty); return; } + + var secret = GetLocal(typeof(ITsInstance)); - var isArray = emit.DefineLabel(); - var end = emit.DefineLabel(); - secret = GetLocal(typeof(ITsInstance)); + if (CanBeArrayAccess(array)) + { - emit.Dup() - .Call(typeof(TsObject).GetMethod("get_Type")) - .LdInt((int)VariableType.Instance) - .Bne(isArray) - .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) - .StLocal(secret) - .LdLocal(secret) - .LdStr("get") - .LdInt(array.Indeces.Count) - .NewArr(typeof(TsObject)); + var isArray = emit.DefineLabel(); + var end = emit.DefineLabel(); - var indeces = new LocalBuilder[array.Indeces.Count]; - for (var i = 0; i < array.Indeces.Count; i++) - { - emit.Dup() - .LdInt(i); - array.Indeces[i].Accept(this); - ConvertTopToObject(); - indeces[i] = GetLocal(); emit.Dup() - .StLocal(indeces[i]) - .StElem(typeof(TsObject)); - } + .Call(typeof(TsObject).GetMethod("get_Type")) + .LdInt((int)VariableType.Instance) + .Bne(isArray) + .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .StLocal(secret) + .LdLocal(secret) + .LdStr("get") + .LdInt(array.Indeces.Count) + .NewArr(typeof(TsObject)); - emit.Call(typeof(ITsInstance).GetMethod("Call")) - .Dup() - .StLocal(value) - .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) - .StLocal(result) - .LdLocal(secret) - .LdStr("set") - .LdInt(indeces.Length + 1) - .NewArr(typeof(TsObject)); + var indeces = new LocalBuilder[array.Indeces.Count]; + for (var i = 0; i < array.Indeces.Count; i++) + { + emit.Dup() + .LdInt(i); + array.Indeces[i].Accept(this); + ConvertTopToObject(); + indeces[i] = GetLocal(); + emit.Dup() + .StLocal(indeces[i]) + .StElem(typeof(TsObject)); + } - FreeLocal(secret); + emit.Call(typeof(ITsInstance).GetMethod("Call")) + .Dup() + .StLocal(value) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) + .StLocal(result) + .LdLocal(secret) + .LdStr("set") + .LdInt(indeces.Length + 1) + .NewArr(typeof(TsObject)); - for (var i = 0; i < indeces.Length; i++) - { + for (var i = 0; i < indeces.Length; i++) + { + emit.Dup() + .LdInt(i) + .LdLocal(indeces[i]) + .StElem(typeof(TsObject)); + FreeLocal(indeces[i]); + } emit.Dup() - .LdInt(i) - .LdLocal(indeces[i]) - .StElem(typeof(TsObject)); - FreeLocal(indeces[i]); - } - emit.Dup() - .LdInt(indeces.Length) - .LdLocal(result) - .StElem(typeof(TsObject)) - .Call(typeof(ITsInstance).GetMethod("Call")) - .Pop() - .LdLocal(value) - .Br(end) - .PushType(typeof(TsObject).MakePointerType()) - .MarkLabel(isArray); - - FreeLocal(result); + .LdInt(indeces.Length) + .LdLocal(result) + .StElem(typeof(TsObject)) + .Call(typeof(ITsInstance).GetMethod("Call")) + .Pop() + .LdLocal(value) + .Br(end) + .PushType(typeof(TsObject).MakePointerType()) + .MarkLabel(isArray); - CallInstanceMethod(TsTypes.ObjectCasts[array.Children.Count == 2 ? typeof(TsObject[]) : typeof(TsObject[][])], array.Position); - LoadElementAsInt(array.Children[1]); + CallInstanceMethod(TsTypes.ObjectCasts[array.Children.Count == 2 ? typeof(TsObject[]) : typeof(TsObject[][])], array.Position); + LoadElementAsInt(array.Children[1]); - if (array.Children.Count == 2) - { - emit.LdElemA(typeof(TsObject)); + if (array.Children.Count == 2) + { + emit.LdElemA(typeof(TsObject)); + } + else + { + emit.LdElem(typeof(TsObject[])); + LoadElementAsInt(array.Children[2]); + emit.LdElemA(typeof(TsObject)); + } + emit.Dup() + .LdObj(typeof(TsObject)) + .Dup() + .StLocal(value) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) + .StObj(typeof(TsObject)) + .LdLocal(value) + .MarkLabel(end) + .PopTop(); } else { - emit.LdElem(typeof(TsObject[])); - LoadElementAsInt(array.Children[2]); - emit.LdElemA(typeof(TsObject)); + emit.Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .StLocal(secret) + .LdLocal(secret) + .LdStr("get") + .LdInt(array.Indeces.Count) + .NewArr(typeof(TsObject)); + + var indeces = new LocalBuilder[array.Indeces.Count]; + for (var i = 0; i < array.Indeces.Count; i++) + { + emit.Dup() + .LdInt(i); + array.Indeces[i].Accept(this); + ConvertTopToObject(); + indeces[i] = GetLocal(); + emit.Dup() + .StLocal(indeces[i]) + .StElem(typeof(TsObject)); + } + + emit.Call(typeof(ITsInstance).GetMethod("Call")) + .Dup() + .StLocal(value) + .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) + .StLocal(result) + .LdLocal(secret) + .LdStr("set") + .LdInt(indeces.Length + 1) + .NewArr(typeof(TsObject)); + + for (var i = 0; i < indeces.Length; i++) + { + emit.Dup() + .LdInt(i) + .LdLocal(indeces[i]) + .StElem(typeof(TsObject)); + FreeLocal(indeces[i]); + } + emit.Dup() + .LdInt(indeces.Length) + .LdLocal(result) + .StElem(typeof(TsObject)) + .Call(typeof(ITsInstance).GetMethod("Call")) + .Pop() + .LdLocal(value); } - emit.Dup() - .LdObj(typeof(TsObject)) - .Dup() - .StLocal(value) - .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) - .StObj(typeof(TsObject)) - .LdLocal(value) - .MarkLabel(end) - .PopTop(); + FreeLocal(result); FreeLocal(value); + FreeLocal(secret); } else if(postfix.Child is ListAccessNode list) { + var secret = GetLocal(); ListAccessSet(list, 2); emit.Call(typeof(List).GetMethod("get_Item")) .StLocal(secret) @@ -2894,9 +3079,11 @@ public void Visit(PostfixNode postfix) .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) .Call(typeof(List).GetMethod("set_Item")) .LdLocal(secret); + FreeLocal(secret); } else if(postfix.Child is GridAccessNode grid) { + var secret = GetLocal(); GridAccessSet(grid); emit.Call(typeof(Grid).GetMethod("get_Item")) .StLocal(secret) @@ -2904,9 +3091,11 @@ public void Visit(PostfixNode postfix) .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) .Call(typeof(Grid).GetMethod("set_Item")) .LdLocal(secret); + FreeLocal(secret); } else if(postfix.Child is MapAccessNode map) { + var secret = GetLocal(); MapAccessSet(map); emit.Call(typeof(Dictionary).GetMethod("get_Item")) .StLocal(secret) @@ -2914,9 +3103,11 @@ public void Visit(PostfixNode postfix) .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) .Call(typeof(Dictionary).GetMethod("set_Item")) .LdLocal(secret); + FreeLocal(secret); } else if (postfix.Child is VariableToken variable) { + var secret = GetLocal(); if (_table.Defined(variable.Text, out var symbol)) { if (symbol.Type != SymbolType.Variable) @@ -2941,9 +3132,11 @@ public void Visit(PostfixNode postfix) .Call(typeof(ITsInstance).GetMethod("set_Item", new[] { typeof(string), typeof(TsObject) })) .LdLocal(secret); } + FreeLocal(secret); } else if (postfix.Child is MemberAccessNode member) { + var secret = GetLocal(); var value = member.Right as VariableToken; if (value is null) { @@ -2984,11 +3177,10 @@ public void Visit(PostfixNode postfix) FreeLocal(target); } + FreeLocal(secret); } else _errors.Add(new CompileException($"Invalid syntax detected {postfix.Child.Position}")); - - FreeLocal(secret); } private Func GetReadOnlyLoadFunc(ReadOnlyToken read) @@ -3040,83 +3232,132 @@ public void Visit(PrefixNode prefix) var isArray = emit.DefineLabel(); var end = emit.DefineLabel(); + FreeLocal(secret); secret = GetLocal(typeof(ITsInstance)); - emit.Dup() - .Call(typeof(TsObject).GetMethod("get_Type")) - .LdInt((int)VariableType.Instance) - .Bne(isArray) - .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) - .StLocal(secret) - .LdLocal(secret) - .LdStr("get") - .LdInt(array.Indeces.Count) - .NewArr(typeof(TsObject)); - - var indeces = new LocalBuilder[array.Indeces.Count]; - for (var i = 0; i < array.Indeces.Count; i++) + if (CanBeArrayAccess(array)) { + emit.Dup() - .LdInt(i); - array.Indeces[i].Accept(this); - ConvertTopToObject(); - indeces[i] = GetLocal(); - emit.Dup() - .StLocal(indeces[i]) - .StElem(typeof(TsObject)); - } + .Call(typeof(TsObject).GetMethod("get_Type")) + .LdInt((int)VariableType.Instance) + .Bne(isArray) + .Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .StLocal(secret) + .LdLocal(secret) + .LdStr("get") + .LdInt(array.Indeces.Count) + .NewArr(typeof(TsObject)); - emit.Call(typeof(ITsInstance).GetMethod("Call")) - .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) - .StLocal(value) - .LdLocal(secret) - .LdStr("set") - .LdInt(indeces.Length + 1) - .NewArr(typeof(TsObject)); + var indeces = new LocalBuilder[array.Indeces.Count]; + for (var i = 0; i < array.Indeces.Count; i++) + { + emit.Dup() + .LdInt(i); + array.Indeces[i].Accept(this); + ConvertTopToObject(); + indeces[i] = GetLocal(); + emit.Dup() + .StLocal(indeces[i]) + .StElem(typeof(TsObject)); + } - FreeLocal(secret); + emit.Call(typeof(ITsInstance).GetMethod("Call")) + .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) + .StLocal(value) + .LdLocal(secret) + .LdStr("set") + .LdInt(indeces.Length + 1) + .NewArr(typeof(TsObject)); - for (var i = 0; i < indeces.Length; i++) - { + for (var i = 0; i < indeces.Length; i++) + { + emit.Dup() + .LdInt(i) + .LdLocal(indeces[i]) + .StElem(typeof(TsObject)); + FreeLocal(indeces[i]); + } emit.Dup() - .LdInt(i) - .LdLocal(indeces[i]) - .StElem(typeof(TsObject)); - FreeLocal(indeces[i]); - } - emit.Dup() - .LdInt(indeces.Length) - .LdLocal(value) - .StElem(typeof(TsObject)) - .Call(typeof(ITsInstance).GetMethod("Call")) - .Pop() - .LdLocal(value) - .Br(end) - .PushType(typeof(TsObject).MakePointerType()) - .MarkLabel(isArray); + .LdInt(indeces.Length) + .LdLocal(value) + .StElem(typeof(TsObject)) + .Call(typeof(ITsInstance).GetMethod("Call")) + .Pop() + .LdLocal(value) + .Br(end) + .PushType(typeof(TsObject).MakePointerType()) + .MarkLabel(isArray); - CallInstanceMethod(TsTypes.ObjectCasts[array.Children.Count == 2 ? typeof(TsObject[]) : typeof(TsObject[][])], array.Position); - LoadElementAsInt(array.Children[1]); + CallInstanceMethod(TsTypes.ObjectCasts[array.Children.Count == 2 ? typeof(TsObject[]) : typeof(TsObject[][])], array.Position); + LoadElementAsInt(array.Children[1]); - if (array.Children.Count == 2) - { - emit.LdElemA(typeof(TsObject)); + if (array.Children.Count == 2) + { + emit.LdElemA(typeof(TsObject)); + } + else + { + emit.LdElem(typeof(TsObject[])); + LoadElementAsInt(array.Children[2]); + emit.LdElemA(typeof(TsObject)); + } + emit.Dup() + .LdObj(typeof(TsObject)) + .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) + .Dup() + .StLocal(value) + .StObj(typeof(TsObject)) + .LdLocal(value) + .MarkLabel(end) + .PopTop(); } else { - emit.LdElem(typeof(TsObject[])); - LoadElementAsInt(array.Children[2]); - emit.LdElemA(typeof(TsObject)); + emit.Call(typeof(TsObject).GetMethod("GetInstanceUnchecked")) + .StLocal(secret) + .LdLocal(secret) + .LdStr("get") + .LdInt(array.Indeces.Count) + .NewArr(typeof(TsObject)); + + var indeces = new LocalBuilder[array.Indeces.Count]; + for (var i = 0; i < array.Indeces.Count; i++) + { + emit.Dup() + .LdInt(i); + array.Indeces[i].Accept(this); + ConvertTopToObject(); + indeces[i] = GetLocal(); + emit.Dup() + .StLocal(indeces[i]) + .StElem(typeof(TsObject)); + } + + emit.Call(typeof(ITsInstance).GetMethod("Call")) + .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) + .StLocal(value) + .LdLocal(secret) + .LdStr("set") + .LdInt(indeces.Length + 1) + .NewArr(typeof(TsObject)); + + for (var i = 0; i < indeces.Length; i++) + { + emit.Dup() + .LdInt(i) + .LdLocal(indeces[i]) + .StElem(typeof(TsObject)); + FreeLocal(indeces[i]); + } + emit.Dup() + .LdInt(indeces.Length) + .LdLocal(value) + .StElem(typeof(TsObject)) + .Call(typeof(ITsInstance).GetMethod("Call")) + .Pop() + .LdLocal(value); } - emit.Dup() - .LdObj(typeof(TsObject)) - .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) - .Dup() - .StLocal(value) - .StObj(typeof(TsObject)) - .LdLocal(value) - .MarkLabel(end) - .PopTop(); FreeLocal(value); } From 1a712d75d2698a990e2efac59bb44e9f6491d24a Mon Sep 17 00:00:00 2001 From: mystborn Date: Wed, 2 May 2018 11:49:32 -0700 Subject: [PATCH 15/54] Deprecate ds_* Methods --- Samples/TestSuite/Tests/postfix.tfs | 1 + Samples/TestSuite/Tests/prefix.tfs | 37 +- Samples/TestSuite/Tests/tests.tfs | 230 ------ Samples/TestSuite/UnitTestLib/unit_test.tfs | 14 +- TaffyScript/BaseClassLib/DsGrid.cs | 659 ------------------ TaffyScript/BaseClassLib/DsList.cs | 219 ------ TaffyScript/BaseClassLib/DsMap.cs | 160 ----- TaffyScript/TaffyScript.csproj | 3 - .../Backend/BaseClassLibrary.cs | 66 -- .../Backend/Compiler/MsilWeakCodeGen.cs | 229 +----- .../Front End/LexicalAnalysis/TokenType.cs | 1 - .../Front End/LexicalAnalysis/Tokenizer.cs | 1 - TaffyScriptCompiler/Front End/Parser.cs | 10 +- .../Syntax/Concrete/ExplicitArrayAccess.cs | 18 - .../Syntax/Concrete/GridAccess.cs | 19 - .../Syntax/Concrete/ListAccess.cs | 18 - .../Syntax/Concrete/MapAccess.cs | 18 - .../Syntax/ISyntaxElementVisitor.cs | 4 - .../Syntax/SyntaxElementFactory.cs | 8 - TaffyScriptCompiler/Syntax/SyntaxType.cs | 7 - .../TaffyScriptCompiler.csproj | 4 - 21 files changed, 37 insertions(+), 1689 deletions(-) delete mode 100644 TaffyScript/BaseClassLib/DsGrid.cs delete mode 100644 TaffyScript/BaseClassLib/DsList.cs delete mode 100644 TaffyScript/BaseClassLib/DsMap.cs delete mode 100644 TaffyScriptCompiler/Syntax/Concrete/ExplicitArrayAccess.cs delete mode 100644 TaffyScriptCompiler/Syntax/Concrete/GridAccess.cs delete mode 100644 TaffyScriptCompiler/Syntax/Concrete/ListAccess.cs delete mode 100644 TaffyScriptCompiler/Syntax/Concrete/MapAccess.cs diff --git a/Samples/TestSuite/Tests/postfix.tfs b/Samples/TestSuite/Tests/postfix.tfs index 1aed890..37e7a89 100644 --- a/Samples/TestSuite/Tests/postfix.tfs +++ b/Samples/TestSuite/Tests/postfix.tfs @@ -12,6 +12,7 @@ namespace LanguageTests { postfix_local_var_increment, postfix_local_var_decrement, postfix_global_var_increment, + postfix_global_var_decrement, postfix_local_var_decrement, postfix_local_object_var_increment, postfix_local_object_var_decrement, diff --git a/Samples/TestSuite/Tests/prefix.tfs b/Samples/TestSuite/Tests/prefix.tfs index 5b8202f..88bc0e6 100644 --- a/Samples/TestSuite/Tests/prefix.tfs +++ b/Samples/TestSuite/Tests/prefix.tfs @@ -1,4 +1,5 @@ using UnitTest; +using TaffyScript.Collections; namespace LanguageTests { script run_prefix_tests() { @@ -12,10 +13,10 @@ namespace LanguageTests { prefix_decrement_array, prefix_increment_list, prefix_decrement_list, - prefix_increment_grid, + /* prefix_increment_grid, prefix_decrement_grid, prefix_increment_map, - prefix_decrement_map, + prefix_decrement_map,*/ prefix_increment_local_var, prefix_decrement_local_var, prefix_increment_global_var, @@ -87,31 +88,27 @@ namespace LanguageTests { script prefix_increment_list() { test_it("++list"); - var list = ds_list_create(); - ds_list_add(list, 2); - ++list[| 0]; - assert_equal(list[| 0], 3); - var j = ++list[| 0]; + var list = new ds_list(); + list.add(2); + ++list[0]; + assert_equal(list[0], 3); + var j = ++list[0]; assert_equal(j, 4); - assert_equal(list[| 0], 4); - - ds_list_destroy(list); + assert_equal(list[0], 4); } script prefix_decrement_list() { test_it("--list"); - var list = ds_list_create(); - ds_list_add(list, 2); - --list[| 0]; - assert_equal(list[| 0], 1); - var j = --list[| 0]; + var list = new ds_list(); + list.add(2); + --list[0]; + assert_equal(list[0], 1); + var j = --list[0]; assert_equal(j, 0); - assert_equal(list[| 0], 0); - - ds_list_destroy(list); + assert_equal(list[0], 0); } - script prefix_increment_grid() { + /*script prefix_increment_grid() { test_it("++grid"); var grid = ds_grid_create(2, 2); grid[# 0, 0] = 2; @@ -161,7 +158,7 @@ namespace LanguageTests { assert_equal(map[? "moo"], 0); ds_map_destroy(map); - } + }*/ script prefix_increment_local_var() { test_it("++local_var"); diff --git a/Samples/TestSuite/Tests/tests.tfs b/Samples/TestSuite/Tests/tests.tfs index 8463990..09b8278 100644 --- a/Samples/TestSuite/Tests/tests.tfs +++ b/Samples/TestSuite/Tests/tests.tfs @@ -27,234 +27,4 @@ namespace LanguageTests { run_map_tests(); show_debug_message(""); } - - script timer_entry { - var time_result = time_invoke(scr_object_cycle, 100000); - show_debug_message("Object Cycle:"); - show_debug_message(" Milliseconds: " + string(time_result.ms)); - show_debug_message(" Ticks: " + string(time_result.ticks)); - time_result = time_invoke(gc_collect); - show_debug_message("Collect Garbage:"); - show_debug_message(" Milliseconds: " + string(time_result.ms)); - show_debug_message(" Ticks: " + string(time_result.ticks)); - time_result = time_invoke(scr_obj_create, 100000); - show_debug_message("Object Create:"); - show_debug_message(" Milliseconds: " + string(time_result.ms)); - show_debug_message(" Ticks: " + string(time_result.ticks)); - time_result = time_invoke(gc_collect); - show_debug_message("Collect Garbage:"); - show_debug_message(" Milliseconds: " + string(time_result.ms)); - show_debug_message(" Ticks: " + string(time_result.ticks)); - } - - script array_literal() { - test_it("Array Literal"); - var arr = [0, 1, 6]; - assert_equal(arr[0], 0); - assert_equal(arr[2], 6); - } - - script assignment() { - test_it("Assignment"); - assignment_1("yo"); - - var val = 1; - assert_equal(val, 1); - val = 2; - assert_equal(val, 2); - - var arr = [0, 1]; - assert_equal(arr[1], 1); - arr[1] = 36; - assert_equal(arr[1], 36); - - var list = ds_list_create(); - ds_list_add(list, 0); - assert_equal(list[| 0], 0); - list[| 0] = 66; - assert_equal(list[| 0], 66); - - var grid = ds_grid_create(5, 5); - grid[# 0, 2] = 12; - assert_equal(grid[# 0, 2], 12); - - var map = ds_map_create(); - map[? "key"] = "value"; - assert_equal(map[? "key"], "value"); - - var obj = new obj_test(); - obj.assignment(); - obj.val = 99; - assert_equal(obj.val, 99); - - global.obj = obj; - global.obj.val = -5; - assert_equal(global.obj.val, -5); - - global.val = 66; - assert_equal(global.val, 66); - - val += 1; - assert_equal(val, 3); - - arr[1] += 1; - assert_equal(arr[1], 37); - - list[| 0] += 1; - assert_equal(list[| 0], 67); - - grid[# 0, 2] += 1; - assert_equal(grid[# 0, 2], 13); - - map[? "key"] += "moo"; - assert_equal(map[? "key"], "valuemoo"); - - obj.val += 1; - assert_equal(obj.val, -4); - - global.obj.val += 1; - assert_equal(global.obj.val, -3); - - global.val += 1; - assert_equal(global.val, 67); - - ds_map_destroy(map); - ds_grid_destroy(grid); - ds_list_destroy(list); - obj.destroy(); - } - - script assignment_1() { - var value = argument0; - assert_equal(value, argument0); - argument0 = 36; - assert_equal(argument0, 36); - - argument0 += 1; - assert_equal(argument0, 37); - } - - script prefix() { - test_it("Prefix"); - var i = 0; - ++i; - assert_equal(i, 1); - var j = ++i; - assert_equal(j, 2); - assert_equal(i, 2); - var obj = new obj_test(); - ++obj.val; - assert_equal(obj.val, 31); - j = ++obj.val; - assert_equal(j, 32); - assert_equal(obj.val, 32); - global.val = 64; - ++global.val; - assert_equal(global.val, 65); - j = ++global.val; - assert_equal(j, 66); - assert_equal(global.val, 66); - global.obj = obj; - ++global.obj.val; - assert_equal(global.obj.val, 33); - j = ++global.obj.val; - assert_equal(j, 34); - assert_equal(global.obj.val, 34); - obj.prefix(); - obj.destroy(); - } - - script script_tests() { - test_it("Script") - var func = script1; - var result = func(); - assert_equal(result, 40); - func = script2; - result = func("henlo"); - assert_equal(result, "henlo"); - var obj = new obj_test(); - func = obj.script1; - result = func(); - assert_equal(result, obj); - func = obj.script2; - result = func("yo"); - assert_equal(result, "yo"); - obj.destroy(); - func = Inner.script1; - result = func(); - assert_equal(result, 6); - func = Inner.script2; - result = func("cow"); - assert_equal(result, "cow"); - } - - script script1() { - return 40; - } - - script script2() { - return argument0; - } - - object obj_test { - event create() { - val = 30; - } - - event postfix() { - val++; - assert_equal(val, 35); - var j = val++; - assert_equal(j, 35); - assert_equal(val, 36); - self.val++; - assert_equal(self.val, 37); - j = self.val++; - assert_equal(j, 37); - assert_equal(self.val, 38); - } - - event prefix() { - val = 30; - ++val; - assert_equal(val, 31); - var j = ++val; - assert_equal(j, 32); - assert_equal(val, 32); - ++self.val; - assert_equal(self.val, 33); - j = ++self.val; - assert_equal(j, 34); - assert_equal(self.val, 34); - } - - event assignment() { - val = 50; - assert_equal(val, 50); - self.val = 49; - assert_equal(self.val, 49); - val += 2; - assert_equal(val, 51); - self.val += 1; - assert_equal(self.val, 52); - } - - event script1() { - return self; - } - - event script2() { - return argument0; - } - } - - namespace Inner { - script script1() { - return 6; - } - - script script2() { - return argument0; - } - } } \ No newline at end of file diff --git a/Samples/TestSuite/UnitTestLib/unit_test.tfs b/Samples/TestSuite/UnitTestLib/unit_test.tfs index 761c96e..8c6e637 100644 --- a/Samples/TestSuite/UnitTestLib/unit_test.tfs +++ b/Samples/TestSuite/UnitTestLib/unit_test.tfs @@ -2,6 +2,8 @@ //To find more information, you can view the project here: //https://github.com/gm-core/gamatas +using TaffyScript.Collections; + namespace UnitTest { object obj_unit_test { event create(test_suite_name) { @@ -12,22 +14,18 @@ namespace UnitTest { tests_failed = false; test_suite = test_suite_name; test_description = ""; - tests = ds_list_create(); + tests = new ds_list(); for(var i = 1; i < argument_count; i++) { - ds_list_add(tests, argument[i]); + tests.add(argument[i]); } } - event destroy() { - ds_list_destroy(tests); - } - event run_tests() { - var count = ds_list_size(tests); + var count = tests.count; for(var i = 0; i < count; i++) { global._unit_test = self; test_description = ""; - tests[| i](); + tests[i](); show_debug_message(string(test_description) + " tests have passed."); } if(tests_failed) diff --git a/TaffyScript/BaseClassLib/DsGrid.cs b/TaffyScript/BaseClassLib/DsGrid.cs deleted file mode 100644 index 2369d05..0000000 --- a/TaffyScript/BaseClassLib/DsGrid.cs +++ /dev/null @@ -1,659 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using TaffyScript.Collections; - -namespace TaffyScript -{ - /// - /// Basic Grid implementation attempting to keep the same api as the ds_grid from Gamemaker. - /// - public class DsGrid - { - private static readonly ClassBinder> _grids = new ClassBinder>(); - - private TsObject[,] _source; - - /// - /// Get or set the value at the given location within a Grid. - /// - /// The x position - /// The y position - /// The value at the location. - public TsObject this[int x, int y] - { - get => _source[x, y]; - set => _source[x, y] = value; - } - - private DsGrid(int width, int height) - { - _source = new TsObject[width, height]; - } - - /// - /// Adds a value to the object at the given location. - /// - /// Grid Id - /// The x position - /// The y position - /// The value to add. - public static void DsGridAdd(int index, int x, int y, TsObject value) - { - _grids[index][x, y] += value; - } - - /// - /// Adds a value to every object within a disk. - /// - /// Grid Id - /// The x position of the center of the disk - /// The y position of the center of the disk - /// The radius of the disk - /// The value to add. - public static void DsGridAddDisk(int index, int xm, int ym, int r, TsObject value) - { - _grids[index].OverDisk(xm, ym, r, (w, h, g) => g[w, h] += value); - } - - /// - /// Adds all of the values in a source grid to the values in a destination grid. - /// - /// The id of the destination grid - /// The id of the source grid - /// The left position of the source region to copy - /// The top position of the source region to copy - /// The right position of the source region to copy - /// The bottom position of the source region to copy - /// The x position in the destination grid to add the source region to. - /// The y position in the destination grid to add the source region to. - public static void DsGridAddGridRegion(int index, int source, int x1, int y1, int x2, int y2, int xpos, int ypos) - { - var dest = _grids[index]; - var src = _grids[source]; - var xLength = x2 - x1; - var yLength = y2 - y1; - - if (x1 < 0) - throw new ArgumentOutOfRangeException("x1"); - else if (x2 >= src.Width) - throw new ArgumentOutOfRangeException("x2"); - else if (y1 < 0) - throw new ArgumentOutOfRangeException("y1"); - else if (y2 >= src.Height) - throw new ArgumentOutOfRangeException("y2"); - else if (xpos < 0 || xpos + xLength >= dest.Width) - throw new ArgumentOutOfRangeException("xpos"); - else if (ypos < 0 || ypos + yLength >= dest.Height) - throw new ArgumentOutOfRangeException("ypos"); - - for(var w = 0; w < xLength; w++) - { - for(var h = 0; h < yLength; h++) - { - dest[xpos + w, ypos + h] += src[x1 + w, x2 + h]; - } - } - } - - /// - /// Adds a value to every object within a region. - /// - /// Grid id - /// The left position of the region - /// The top position of the region - /// The right position of the region - /// The bottom position of the region - /// The value to add. - public static void DsGridAddRegion(int index, int x1, int y1, int x2, int y2, TsObject value) - { - _grids[index].OverRegion(x1, y1, x2, y2, (w, h, g) => g[w, h] += value); - } - - /// - /// Sets all of the values in a grid to the specified value. - /// - /// Grid id - /// The new value. - public static void DsGridClear(int index, TsObject value) - { - var grid = _grids[index]; - for(var w = 0; w < grid.Width; w++) - { - for(var h = 0; h < grid.Height; h++) - { - grid[w, h] = value; - } - } - } - - /// - /// Copies one grid into another. - /// - /// The destination grid id - /// The source grid id - public static void DsGridCopy(int destination, int source) - { - var dst = _grids[destination]; - var src = _grids[source]; - var xLength = Math.Min(dst.Width, src.Width) - 1; - var yLength = Math.Min(dst.Height, src.Height) - 1; - dst.SetGridRegion(src, 0, 0, xLength, yLength, 0, 0); - } - - /// - /// Creates a grid with the specified width and height. - /// - /// Grid width - /// Grid height - /// Grid id - public static int DsGridCreate(int w, int h) - { - return _grids.Add(new Grid(w, h)); - } - - /// - /// Destroys a previously created grid. - /// - /// Grid id - public static void DsGridDestroy(int index) - { - if (index < 0 || index >= _grids.Count) - throw new ArgumentOutOfRangeException(nameof(index)); - - if (_grids[index] == null) - throw new DataStructureDestroyedException("grid", index); - - _grids.Remove(index); - } - - /// - /// Gets the value in the grid at the specified position. - /// - /// Grid id - /// The x position - /// The y position - /// The retrieved value. - public static TsObject DsGridGet(int index, int x, int y) - { - return _grids[index][x, y]; - } - - /// - /// Gets the maximum value within a disk in the grid. - /// - /// Grid id - /// - /// - /// - /// - public static TsObject DsGridGetDiskMax(int index, int xm, int ym, int r) - { - TsObject i = TsObject.Empty(); - _grids[index].OverDisk(xm, ym, r, (w, h, g) => - { - var set = false; - if (!set) - i = g[w, h]; - else - { - var current = g[w, h]; - if (current > i) - i = current; - } - }); - return i; - } - - /// - /// Gets the average value within a disk in the grid. - /// - /// Grid Id - /// The x position of the center of the disk - /// The y position of the center of the disk - /// The radius of the disk - /// - public static TsObject DsGridGetDiskMean(int index, int xm, int ym, int r) - { - var mean = new TsObject(0); - var iter = 0; - _grids[index].OverDisk(xm, ym, r, (w, h, g) => - { - iter++; - mean += g[w, h]; - }); - return mean / iter; - } - - /// - /// Gets the minimum value within a disk in the grid. - /// - /// Grid Id - /// The x position of the center of the disk - /// The y position of the center of the disk - /// The radius of the disk - /// - public static TsObject DsGridGetDiskMin(int index, int xm, int ym, int r) - { - bool set = false; - TsObject i = TsObject.Empty(); - _grids[index].OverDisk(xm, ym, r, (w, h, g) => - { - if (!set) - i = g[w, h]; - else - { - var current = g[w, h]; - if (current < i) - i = current; - } - }); - return i; - } - - /// - /// Gets the sum of all values within a disk in the grid. - /// - /// Grid Id - /// The x position of the center of the disk - /// The y position of the center of the disk - /// The radius of the disk - /// - public static TsObject DsGridGetDiskSum(int index, int xm, int ym, int r) - { - var mean = new TsObject(0); - _grids[index].OverDisk(xm, ym, r, (w, h, g) => - { - mean += g[w, h]; - }); - return mean; - } - - public static Grid DsGridGetGrid(int id) - { - return _grids[id]; - } - - /// - /// Gets the maximum value within a region. - /// - /// Grid id - /// The left position of the region - /// The top position of the region - /// The right position of the region - /// The bottom position of the region - /// - public static TsObject DsGridGetMax(int index, int x1, int y1, int x2, int y2) - { - bool set = false; - TsObject i = TsObject.Empty(); - _grids[index].OverRegion(x1, y1, x2, y2, (w, h, g) => - { - if (!set) - i = g[w, h]; - else - { - var current = g[w, h]; - if (current > i) - i = current; - } - }); - return i; - } - - /// - /// Gets the average value within a region. - /// - /// Grid id - /// The left position of the region - /// The top position of the region - /// The right position of the region - /// The bottom position of the region - /// - public static TsObject DsGridGetMean(int index, int x1, int y1, int x2, int y2) - { - var mean = new TsObject(0); - var iter = 0; - _grids[index].OverRegion(x1, y1, x2, y2, (w, h, g) => - { - iter++; - mean += g[w, h]; - }); - return mean / iter; - } - - /// - /// Gets the minimum value within a region. - /// - /// Grid id - /// The left position of the region - /// The top position of the region - /// The right position of the region - /// The bottom position of the region - /// - public static TsObject DsGridGetMin(int index, int x1, int y1, int x2, int y2) - { - bool set = false; - TsObject i = TsObject.Empty(); - _grids[index].OverRegion(x1, y1, x2, y2, (w, h, g) => - { - if (!set) - i = g[w, h]; - else - { - var current = g[w, h]; - if (current < i) - i = current; - } - }); - return i; - } - - /// - /// Gets the sum of all values within a region. - /// - /// Grid id - /// The left position of the region - /// The top position of the region - /// The right position of the region - /// The bottom position of the region - /// - public static TsObject DsGridGetSum(int index, int x1, int y1, int x2, int y2) - { - var mean = new TsObject(0); - _grids[index].OverRegion(x1, y1, x2, y2, (w, h, g) => - { - mean += g[w, h]; - }); - return mean; - } - - /// - /// Gets the height of a grid. - /// - /// Grid id - /// Height - public static int DsGridHeight(int index) - { - return _grids[index].Height; - } - - /// - /// Multiplies a value with the object at the given location. - /// - /// Grid Id - /// The x position - /// The y position - /// The value to multiply. - public static void DsGridMultiply(int index, int x, int y, TsObject value) - { - _grids[index][x, y] *= value; - } - - /// - /// Multiplies a value with every object within a disk. - /// - /// Grid Id - /// The x position of the center of the disk - /// The y position of the center of the disk - /// The radius of the disk - /// The value to multiply. - public static void DsGridMultiplyDisk(int index, int xm, int ym, int r, TsObject obj) - { - _grids[index].OverDisk(xm, ym, r, (w, h, g) => g[w, h] *= obj); - } - - /// - /// Multiplies all of the values in a source grid with the values in a destination grid. - /// - /// The id of the destination grid - /// The id of the source grid - /// The left position of the source region to copy - /// The top position of the source region to copy - /// The right position of the source region to copy - /// The bottom position of the source region to copy - /// The x position in the destination grid to add the source region to. - /// The y position in the destination grid to add the source region to. - public static void DsGridMultiplyGridRegion(int index, int source, int x1, int y1, int x2, int y2, int xpos, int ypos) - { - var dest = _grids[index]; - var src = _grids[source]; - var xLength = x2 - x1; - var yLength = y2 - y1; - - if (x1 < 0) - throw new ArgumentOutOfRangeException("x1"); - else if (x2 >= src.Width) - throw new ArgumentOutOfRangeException("x2"); - else if (y1 < 0) - throw new ArgumentOutOfRangeException("y1"); - else if (y2 >= src.Height) - throw new ArgumentOutOfRangeException("y2"); - else if (xpos < 0 || xpos + xLength >= dest.Width) - throw new ArgumentOutOfRangeException("xpos"); - else if (ypos < 0 || ypos + yLength >= dest.Height) - throw new ArgumentOutOfRangeException("ypos"); - - for (var w = 0; w < xLength; w++) - { - for (var h = 0; h < yLength; h++) - { - dest[xpos + w, ypos + h] *= src[x1 + w, x2 + h]; - } - } - } - - /// - /// Multiplies a value with every object within a region. - /// - /// Grid id - /// The left position of the region - /// The top position of the region - /// The right position of the region - /// The bottom position of the region - /// The value to multiply. - public static void DsGridMultiplyRegion(int index, int x1, int y1, int x2, int y2, TsObject value) - { - _grids[index].OverRegion(x1, y1, x2, y2, (w, h, g) => g[w, h] *= value); - } - - /// - /// Resizes a grid. - /// - /// Grid id - /// The new width - /// The new height - public static void DsGridResize(int index, int w, int h) - { - _grids[index].Resize(w, h); - } - - /// - /// Sets the value at the given location. - /// - /// Grid Id - /// The x position - /// The y position - /// The value to set - public static void DsGridSet(int index, int x, int y, TsObject value) - { - _grids[index][x, y] = value; - } - - /// - /// Sets every location within a disk to a value. - /// - /// Grid Id - /// The x position of the center of the disk - /// The y position of the center of the disk - /// The radius of the disk - /// The value to set - public static void DsGridSetDisk(int index, int xm, int ym, int r, TsObject value) - { - _grids[index].OverDisk(xm, ym, r, (w, h, g) => g[w, h] = value); - } - - /// - /// Copies the contents in a source grid to a destination grid. - /// - /// The id of the destination grid - /// The id of the source grid - /// The left position of the source region to copy - /// The top position of the source region to copy - /// The right position of the source region to copy - /// The bottom position of the source region to copy - /// The x position in the destination grid to add the source region to. - /// The y position in the destination grid to add the source region to. - public static void DsGridSetGridRegion(int index, int source, int x1, int y1, int x2, int y2, int xpos, int ypos) - { - var dest = _grids[index]; - var src = _grids[source]; - dest.SetGridRegion(src, x1, y1, x2, y2, xpos, ypos); - } - - /// - /// Sets every location within a region to a value. - /// - /// Grid id - /// The left position of the region - /// The top position of the region - /// The right position of the region - /// The bottom position of the region - /// The value to set. - public static void DsGridSetRegion(int index, int x1, int y1, int x2, int y2, TsObject value) - { - _grids[index].OverRegion(x1, y1, x2, y2, (w, h, g) => g[w, h] = value); - } - - /// - /// Shuffles all of the values within a grid. - /// - /// Grid id - public static void DsGridShuffle(int index) - { - _grids[index].Shuffle(); - } - - /// - /// Sorts a column within a grid. - /// - /// Grid id - /// Column index - /// Whether the values should be sorted in ascending or descending order. - public static void DsGridSort(int index, int column, bool ascending) - { - _grids[index].Sort(column, ascending); - } - - /// - /// Determines if a value exists within a disk. - /// - /// Grid Id - /// The x position of the center of the disk - /// The y position of the center of the disk - /// The radius of the disk - /// The value to find - /// - public static bool DsGridValueDiskExists(int index, int xm, int ym, int r, TsObject val) - { - return _grids[index].InDisk(xm, ym, r, val); - } - - /// - /// Gets the x position of a value within a disk. - /// - /// Grid Id - /// The x position of the center of the disk - /// The y position of the center of the disk - /// The radius of the disk - /// The value to find - /// - public static int DsGridValueDiskX(int index, int xm, int ym, int r, TsObject val) - { - var grid = _grids[index]; - if(grid.InDisk(xm, ym, r, val, out var result, (w, h) => w)) - return result; - return 0; - } - - /// - /// Gets the y position of a value within a disk. - /// - /// Grid Id - /// The x position of the center of the disk - /// The y position of the center of the disk - /// The radius of the disk - /// The value to find - /// - public static int DsGridValueDiskY(int index, int xm, int ym, int r, TsObject val) - { - var grid = _grids[index]; - if (grid.InDisk(xm, ym, r, val, out var result, (w, h) => h)) - return result; - return 0; - } - - /// - /// Determines if a value exists within a region. - /// - /// Grid id - /// The left position of the region - /// The top position of the region - /// The right position of the region - /// The bottom position of the region - /// - /// - public static bool DsGridValueExists(int index, int x1, int y1, int x2, int y2, TsObject val) - { - return _grids[index].InRegion(x1, y1, x2, y2, val); - } - - /// - /// Gets the x position of a value within a region. - /// - /// Grid id - /// The left position of the region - /// The top position of the region - /// The right position of the region - /// The bottom position of the region - /// The value to find - /// - public static int DsGridValueX(int index, int x1, int y1, int x2, int y2, TsObject val) - { - var grid = _grids[index]; - if (grid.InRegion(x1, y1, x2, y2, val, out var result, (w, h) => w)) - return result; - return 0; - } - - /// - /// Gets the y position of a value within a region. - /// - /// Grid id - /// The left position of the region - /// The top position of the region - /// The right position of the region - /// The bottom position of the region - /// The value to find - /// - public static int DsGridValueY(int index, int x1, int y1, int x2, int y2, TsObject val) - { - var grid = _grids[index]; - if (grid.InRegion(x1, y1, x2, y2, val, out var result, (w, h) => h)) - return result; - return 0; - } - - /// - /// Gets the width of a grid. - /// - /// Grid id - /// - public static int DsGridWidth(int index) - { - return _grids[index].Width; - } - } -} diff --git a/TaffyScript/BaseClassLib/DsList.cs b/TaffyScript/BaseClassLib/DsList.cs deleted file mode 100644 index 3caff0c..0000000 --- a/TaffyScript/BaseClassLib/DsList.cs +++ /dev/null @@ -1,219 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using TaffyScript.Collections; - -namespace TaffyScript -{ - /// - /// Basic List implementation attempting to keep the same api as the ds_list from Gamemaker. - /// - public static class DsList - { - private readonly static ClassBinder> _lists = new ClassBinder>(); - - /// - /// Adds a value to a list. - /// - [WeakMethod] - public static TsObject DsListAdd(ITsInstance target, TsObject[] args) - { - if (args.Length < 2) - throw new ArgumentNullException("When calling ds_list_add, at least 2 arguments must be provided."); - var list = _lists[(int)args[0]]; - for (var i = 1; i < args.Length; i++) - list.Add(args[i]); - - return TsObject.Empty(); - } - - /// - /// Clears all values from a list. - /// - /// - public static void DsListClear(int id) - { - _lists[id].Clear(); - } - - /// - /// Copies the contents from a source list to a destination list, clearing all previous contents in the destination. - /// - /// - /// - public static void DsListCopy(int id, int source) - { - var dest = _lists[id]; - var src = _lists[source]; - dest.Clear(); - dest.AddRange(src); - } - - /// - /// Creates a new list. - /// - /// - public static int DsListCreate() - { - return _lists.Add(new List()); - } - - /// - /// Removes the value at the specified position within a list. - /// - /// - /// - public static void DsListDelete(int id, int position) - { - _lists[id].RemoveAt(position); - } - - /// - /// Destroys a previously created list. - /// - /// - public static void DsListDestroy(int id) - { - if (id < 0 || id >= _lists.Count) - throw new ArgumentOutOfRangeException("id"); - else if (_lists[id] == null) - throw new DataStructureDestroyedException("list", id); - - _lists.Remove(id); - } - - /// - /// Determines if a list is empty. - /// - /// - /// - public static bool DsListEmpty(int id) - { - return _lists[id].Count == 0; - } - - /// - /// Finds the index of the given value within a list. - /// - /// List id - /// The value to find. - /// - public static int DsListFindIndex(int id, TsObject value) - { - return _lists[id].FindIndex(v => v == value); - } - - /// - /// Gets the value stored in specified list index. - /// - /// List id - /// The index of the value. - /// - public static TsObject DsListFindValue(int id, int index) - { - var list = _lists[id]; - if (index >= list.Count) - return TsObject.Empty(); - return list[index]; - } - - /// - /// Gets the list with the specified id. - /// - /// List id - /// - public static List DsListGet(int id) - { - return _lists[id]; - } - - /// - /// Inserts a value at the specified location. - /// - /// List id - /// Position index - /// Value to insert - public static void DsListInsert(int id, int pos, TsObject val) - { - _lists[id].Insert(pos, val); - } - - /// - /// Replaces a value at the specfied index. - /// - /// List id - /// Position index - /// Value to replace with - public static void DsListReplace(int id, int pos, TsObject val) - { - _lists[id][pos] = val; - } - - /// - /// Sets a value at the specified position within a list. - /// - /// - /// Do not change the signature of this method. It is used within the compiler when using the following syntax: - /// list[| 0] = "foo"; - /// - [WeakMethod] - public static TsObject DsListSet(ITsInstance target, TsObject[] args) - { - if (args.Length < 3) - throw new ArgumentException("When calling ds_list_set, at least 3 arguments must be provided."); - var list = _lists[(int)args[0]]; - var pos = (int)args[1]; - var length = pos + args.Length - 2; - while (list.Count <= length) - list.Add(new TsObject(0)); - for (var i = 2; i < args.Length; i++) - list[pos + i - 2] = args[i]; - - return TsObject.Empty(); - } - - /// - /// Sets a value at the specified position within a list. - /// - /// The id of the list. - /// The index of the value. - /// The new value. - public static void DsListSet(int id, int pos, TsObject value) - { - var list = _lists[id]; - while (list.Count <= pos) - list.Add(new TsObject(0)); - list[pos] = value; - } - - /// - /// Shuffles all of the values within a list. - /// - /// - public static void DsListShuffle(int id) - { - _lists[id].Shuffle(); - } - - /// - /// Gets the number of elements within a list. - /// - /// - /// - public static int DsListSize(int id) - { - return _lists[id].Count; - } - - /// - /// Sorts all of the elements within a list. - /// - /// - public static void DsListSort(int id) - { - _lists[id].Sort(); - } - } -} diff --git a/TaffyScript/BaseClassLib/DsMap.cs b/TaffyScript/BaseClassLib/DsMap.cs deleted file mode 100644 index a7d7903..0000000 --- a/TaffyScript/BaseClassLib/DsMap.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using TaffyScript.Collections; - -namespace TaffyScript -{ - /// - /// Basic Map implementation attempting to keep the same api as the ds_map from Gamemaker. - /// - public class DsMap - { - private static readonly ClassBinder> _maps = new ClassBinder>(); - - /// - /// Adds a value to a map with the given key. - /// - /// Map id - /// The key to add the value to - /// The value to add - /// - public static bool DsMapAdd(int id, TsObject key, TsObject value) - { - var map = _maps[id]; - if (map.ContainsKey(key)) - return false; - map.Add(key, value); - return true; - } - - /// - /// Clears all of the values from aa map. - /// - /// - public static void DsMapClear(int id) - { - _maps[id].Clear(); - } - - /// - /// Copies all values from a source map to a destination map, clearing the destination map first. - /// - /// The destination map id - /// The source map id - public static void DsMapCopy(int id, int source) - { - var dst = _maps[id]; - var src = _maps[source]; - - dst.Clear(); - foreach (var kvp in src) - dst.Add(kvp.Key, kvp.Value); - } - - /// - /// Creates a new map - /// - /// - public static int DsMapCreate() - { - return _maps.Add(new Dictionary()); - } - - /// - /// Deletes the value with the specified key from a map - /// - /// Map id - /// The key to delete - public static void DsMapDelete(int id, TsObject key) - { - _maps[id].Remove(key); - } - - /// - /// Destroys a previously created map - /// - /// Map id - public static void DsMapDestroy(int id) - { - if (id < 0 || id >= _maps.Count) - throw new ArgumentOutOfRangeException(nameof(id)); - if (_maps[id] == null) - throw new DataStructureDestroyedException("ds_map", id); - - _maps.Remove(id); - } - - /// - /// Determines if a map is empty - /// - /// Map id - /// - public static bool DsMapEmpty(int id) - { - return _maps[id].Count == 0; - } - - /// - /// Determines if a key exists within a map. - /// - /// Map id - /// The key to find - /// - public static bool DsMapExists(int id, TsObject key) - { - return _maps[id].ContainsKey(key); - } - - /// - /// Finds the value with the specified key within a map. - /// - /// Map id - /// The key used to find the value - /// - public static TsObject DsMapFindValue(int id, TsObject key) - { - if (_maps[id].TryGetValue(key, out var result)) - return result; - return TsObject.Empty(); - } - - public static Dictionary DsMapGet(int id) - { - return _maps[id]; - } - - /// - /// Gets all of the keys within a map as an array. - /// - /// Map id - /// - public static TsObject[] DsMapKeys(int id) - { - return _maps[id].Keys.ToArray(); - } - - /// - /// Replaces the value with the given key with a new value. - /// - /// Map id - /// The key to replace - /// The new value - public static void DsMapReplace(int id, TsObject key, TsObject value) - { - _maps[id][key] = value; - } - - /// - /// Gets the number of elements within a map - /// - /// - /// - public static int DsMapSize(int id) - { - return _maps[id].Count; - } - } -} diff --git a/TaffyScript/TaffyScript.csproj b/TaffyScript/TaffyScript.csproj index 09915f0..df834a0 100644 --- a/TaffyScript/TaffyScript.csproj +++ b/TaffyScript/TaffyScript.csproj @@ -46,8 +46,6 @@ - - @@ -64,7 +62,6 @@ - diff --git a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs b/TaffyScriptCompiler/Backend/BaseClassLibrary.cs index 665f460..e4cd39d 100644 --- a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs +++ b/TaffyScriptCompiler/Backend/BaseClassLibrary.cs @@ -46,72 +46,6 @@ public static string Generate() sb.AppendLine("import Bcl.DotProduct(float, float, float, float) as dot_product"); - sb.AppendLine("import DsGrid.DsGridAdd(int, int, int, object) as ds_grid_add"); - sb.AppendLine("import DsGrid.DsGridAddDisk(int, int, int, int, object) as ds_grid_add_disk"); - sb.AppendLine("import DsGrid.DsGridAddGridRegion(int, int, int, int, int, int, int, int) as ds_grid_add_grid_region"); - sb.AppendLine("import DsGrid.DsGridAddRegion(int, int, int, int, int, object) as ds_grid_add_region"); - sb.AppendLine("import DsGrid.DsGridClear(int, object) as ds_grid_clear"); - sb.AppendLine("import DsGrid.DsGridCopy(int, int) as ds_grid_copy"); - sb.AppendLine("import DsGrid.DsGridCreate(int, int) as ds_grid_create"); - sb.AppendLine("import DsGrid.DsGridDestroy(int) as ds_grid_destroy"); - sb.AppendLine("import DsGrid.DsGridGet(int, int, int) as ds_grid_get"); - sb.AppendLine("import DsGrid.DsGridGetDiskMax(int, int, int, int) as ds_grid_get_disk_max"); - sb.AppendLine("import DsGrid.DsGridGetDiskMean(int, int, int, int) as ds_grid_get_disk_mean"); - sb.AppendLine("import DsGrid.DsGridGetDiskMin(int, int, int, int) as ds_grid_get_disk_min"); - sb.AppendLine("import DsGrid.DsGridGetDiskSum(int, int, int, int) as ds_grid_get_disk_sum"); - sb.AppendLine("import DsGrid.DsGridGetMax(int, int, int, int, int) as ds_grid_get_max"); - sb.AppendLine("import DsGrid.DsGridGetMean(int, int, int, int, int) as ds_grid_get_mean"); - sb.AppendLine("import DsGrid.DsGridGetMin(int, int, int, int, int) as ds_grid_get_min"); - sb.AppendLine("import DsGrid.DsGridGetSum(int, int, int, int, int) as ds_grid_get_sum"); - sb.AppendLine("import DsGrid.DsGridHeight(int) as ds_grid_height"); - sb.AppendLine("import DsGrid.DsGridMultiply(int, int, int, object) as ds_grid_multiply"); - sb.AppendLine("import DsGrid.DsGridMultiplyDisk(int, int, int, int, object) as ds_grid_multiply_disk"); - sb.AppendLine("import DsGrid.DsGridMultiplyGridRegion(int, int, int, int, int, int, int, int) as ds_grid_multiply_grid_region"); - sb.AppendLine("import DsGrid.DsGridMultiplyRegion(int, int, int, int, int, object) as ds_grid_multiply_region"); - sb.AppendLine("import DsGrid.DsGridResize(int, int, int) as ds_grid_resize"); - sb.AppendLine("import DsGrid.DsGridSet(int, int, int, object) as ds_grid_set"); - sb.AppendLine("import DsGrid.DsGridSetDisk(int, int, int, int, object) as ds_grid_set_disk"); - sb.AppendLine("import DsGrid.DsGridSetGridRegion(int, int, int, int, int, int, int, int) as ds_grid_set_grid_region"); - sb.AppendLine("import DsGrid.DsGridSetRegion(int, int, int, int, int, object) as ds_grid_set_region"); - sb.AppendLine("import DsGrid.DsGridShuffle(int) as ds_grid_shuffle"); - sb.AppendLine("import DsGrid.DsGridSort(int, int, bool) as ds_grid_sort"); - sb.AppendLine("import DsGrid.DsGridValueDiskExists(int, int, int, int, object) as ds_grid_value_disk_exists"); - sb.AppendLine("import DsGrid.DsGridValueDiskX(int, int, int, int, object) as ds_grid_value_disk_x"); - sb.AppendLine("import DsGrid.DsGridValueDiskY(int, int, int, int, object) as ds_grid_value_disk_y"); - sb.AppendLine("import DsGrid.DsGridValueExists(int, int, int, int, int, object) as ds_grid_value_exists"); - sb.AppendLine("import DsGrid.DsGridValueX(int, int, int, int, int, object) as ds_grid_value_x"); - sb.AppendLine("import DsGrid.DsGridValueY(int, int, int, int, int, object) as ds_grid_value_y"); - sb.AppendLine("import DsGrid.DsGridWidth(int) as ds_grid_width"); - - sb.AppendLine("import DsList.DsListAdd(instance, array) as ds_list_add"); - sb.AppendLine("import DsList.DsListClear(int) as ds_list_clear"); - sb.AppendLine("import DsList.DsListCopy(int, int) as ds_list_copy"); - sb.AppendLine("import DsList.DsListCreate() as ds_list_create"); - sb.AppendLine("import DsList.DsListDelete(int, int) as ds_list_delete"); - sb.AppendLine("import DsList.DsListDestroy(int) as ds_list_destroy"); - sb.AppendLine("import DsList.DsListEmpty(int) as ds_list_empty"); - sb.AppendLine("import DsList.DsListFindIndex(int, object) as ds_list_find_index"); - sb.AppendLine("import DsList.DsListFindValue(int, int) as ds_list_find_value"); - sb.AppendLine("import DsList.DsListInsert(int, int, object) as ds_list_insert"); - sb.AppendLine("import DsList.DsListReplace(int, int, object) as ds_list_replace"); - sb.AppendLine("import DsList.DsListSet(instance, array) as ds_list_set"); - sb.AppendLine("import DsList.DsListShuffle(int) as ds_list_shuffle"); - sb.AppendLine("import DsList.DsListSize(int) as ds_list_size"); - sb.AppendLine("import DsList.DsListSort(int) as ds_list_sort"); - - sb.AppendLine("import DsMap.DsMapAdd(int, object, object) as ds_map_add"); - sb.AppendLine("import DsMap.DsMapClear(int) as ds_map_clear"); - sb.AppendLine("import DsMap.DsMapCopy(int, int) as ds_map_copy"); - sb.AppendLine("import DsMap.DsMapCreate() as ds_map_create"); - sb.AppendLine("import DsMap.DsMapDelete(int, object) as ds_map_delete"); - sb.AppendLine("import DsMap.DsMapDestroy(int) as ds_map_destroy"); - sb.AppendLine("import DsMap.DsMapEmpty(int) as ds_map_empty"); - sb.AppendLine("import DsMap.DsMapExists(int, object) as ds_map_exists"); - sb.AppendLine("import DsMap.DsMapFindValue(int, object) as ds_map_find_value"); - sb.AppendLine("import DsMap.DsMapKeys(int) as ds_map_keys"); - sb.AppendLine("import DsMap.DsMapReplace(int, object, object) as ds_map_replace"); - sb.AppendLine("import DsMap.DsMapSize(int) as ds_map_size"); - sb.AppendLine("import Bcl.EnvironmentGetVariable(string) as environment_get_variable"); sb.AppendLine("import Bcl.EventInherited(instance, array) as event_inherited"); sb.AppendLine("import Bcl.EventPerform(instance, array) as event_perform"); diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index 5999027..de4c11c 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -1400,32 +1400,6 @@ public void Visit(AssignNode assign) .Pop(); } } - else if(assign.Left is ListAccessNode list) - { - LoadElementAsInt(list.Left); - LoadElementAsInt(list.Right); - assign.Right.Accept(this); - ConvertTopToObject(); - emit.Call(typeof(DsList).GetMethod("DsListSet", new[] { typeof(int), typeof(int), typeof(TsObject) })); - } - else if(assign.Left is GridAccessNode grid) - { - LoadElementAsInt(grid.Left); - LoadElementAsInt(grid.X); - LoadElementAsInt(grid.Y); - assign.Right.Accept(this); - ConvertTopToObject(); - emit.Call(typeof(DsGrid).GetMethod("DsGridSet")); - } - else if(assign.Left is MapAccessNode map) - { - LoadElementAsInt(map.Left); - map.Right.Accept(this); - ConvertTopToObject(); - assign.Right.Accept(this); - ConvertTopToObject(); - emit.Call(typeof(DsMap).GetMethod("DsMapReplace")); - } else if (assign.Left is VariableToken variable) { //Check if the variable is a local variable. @@ -1677,30 +1651,6 @@ private void ProcessAssignExtra(AssignNode assign) FreeLocal(value); } } - else if (assign.Left is ListAccessNode list) - { - ListAccessSet(list, 2); - emit.Call(typeof(List).GetMethod("get_Item")); - assign.Right.Accept(this); - emit.Call(GetOperator(op, typeof(TsObject), emit.GetTop(), assign.Position)) - .Call(typeof(List).GetMethod("set_Item", new[] { typeof(int), typeof(TsObject) })); - } - else if (assign.Left is GridAccessNode grid) - { - GridAccessSet(grid); - emit.Call(typeof(Grid).GetMethod("get_Item")); - assign.Right.Accept(this); - emit.Call(GetOperator(op, typeof(TsObject), emit.GetTop(), assign.Position)) - .Call(typeof(Grid).GetMethod("set_Item")); - } - else if (assign.Left is MapAccessNode map) - { - MapAccessSet(map); - emit.Call(typeof(Dictionary).GetMethod("get_Item")); - assign.Right.Accept(this); - emit.Call(GetOperator(op, typeof(TsObject), emit.GetTop(), assign.Position)) - .Call(typeof(Dictionary).GetMethod("set_Item")); - } else if(assign.Left is VariableToken variable) { if (_table.Defined(variable.Text, out var symbol)) @@ -1783,69 +1733,6 @@ private void ProcessAssignExtra(AssignNode assign) } } - private void ListAccessSet(ListAccessNode listAccess, int accesses) - { - var id = GetLocal(typeof(List)); - var index = GetLocal(typeof(int)); - - LoadElementAsInt(listAccess.Left); - emit.Call(typeof(DsList).GetMethod("DsListGet")) - .StLocal(id); - - LoadElementAsInt(listAccess.Right); - emit.StLocal(index); - for(var i = 0; i < accesses; i++) - { - emit.LdLocal(id) - .LdLocal(index); - } - FreeLocal(id); - FreeLocal(index); - } - - private void GridAccessSet(GridAccessNode grid) - { - var id = GetLocal(typeof(Grid)); - var x = GetLocal(typeof(int)); - var y = GetLocal(typeof(int)); - LoadElementAsInt(grid.Left); - emit.Call(typeof(DsGrid).GetMethod("DsGridGetGrid")) - .StLocal(id); - LoadElementAsInt(grid.X); - emit.StLocal(x); - LoadElementAsInt(grid.Y); - emit.StLocal(y) - .LdLocal(id) - .LdLocal(x) - .LdLocal(y) - .LdLocal(id) - .LdLocal(x) - .LdLocal(y); - FreeLocal(id); - FreeLocal(x); - FreeLocal(y); - } - - private void MapAccessSet(MapAccessNode map) - { - var id = GetLocal(typeof(Dictionary)); - var key = GetLocal(); - LoadElementAsInt(map.Left); - emit.Call(typeof(DsMap).GetMethod("DsMapGet")) - .StLocal(id); - - map.Right.Accept(this); - ConvertTopToObject(); - emit.StLocal(key); - emit.LdLocal(id) - .LdLocal(key) - .LdLocal(id) - .LdLocal(key); - - FreeLocal(id); - FreeLocal(key); - } - private void SelfAccessSet(VariableToken variable) { emit.LdArg(0) @@ -2149,11 +2036,6 @@ public void Visit(ExitToken exitToken) emit.Ret(); } - public void Visit(ExplicitArrayAccessNode explicitArrayAccess) - { - _errors.Add(new NotImplementedException($"Currently explicit array access is not available {explicitArrayAccess.Position}.")); - } - public void Visit(ForNode forNode) { var forStart = emit.DefineLabel(); @@ -2351,14 +2233,6 @@ private void CallEvent(string name, bool loadId, FunctionCallNode functionCall, } } - public void Visit(GridAccessNode gridAccess) - { - LoadElementAsInt(gridAccess.Left); - LoadElementAsInt(gridAccess.X); - LoadElementAsInt(gridAccess.Y); - emit.Call(typeof(DsGrid).GetMethod("DsGridGet")); - } - public void Visit(IfNode ifNode) { // If there is no else node, just let execution flow naturally. @@ -2448,13 +2322,6 @@ public void Visit(ImportNode import) GenerateWeakMethodForImport(method, internalName); } - public void Visit(ListAccessNode listAccess) - { - LoadElementAsInt(listAccess.Left); - LoadElementAsInt(listAccess.Right); - emit.Call(typeof(DsList).GetMethod("DsListFindValue")); - } - private void LoadElementAsInt(ISyntaxElement element) { GetAddressIfPossible(element); @@ -2558,14 +2425,6 @@ public void Visit(LogicalNode logical) emit.MarkLabel(end); } - public void Visit(MapAccessNode mapAccess) - { - LoadElementAsInt(mapAccess.Left); - mapAccess.Right.Accept(this); - ConvertTopToObject(); - emit.Call(typeof(DsMap).GetMethod("DsMapFindValue")); - } - public void Visit(MemberAccessNode memberAccess) { var resolved = ResolveNamespace(memberAccess); @@ -3069,42 +2928,6 @@ public void Visit(PostfixNode postfix) FreeLocal(value); FreeLocal(secret); } - else if(postfix.Child is ListAccessNode list) - { - var secret = GetLocal(); - ListAccessSet(list, 2); - emit.Call(typeof(List).GetMethod("get_Item")) - .StLocal(secret) - .LdLocal(secret) - .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) - .Call(typeof(List).GetMethod("set_Item")) - .LdLocal(secret); - FreeLocal(secret); - } - else if(postfix.Child is GridAccessNode grid) - { - var secret = GetLocal(); - GridAccessSet(grid); - emit.Call(typeof(Grid).GetMethod("get_Item")) - .StLocal(secret) - .LdLocal(secret) - .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) - .Call(typeof(Grid).GetMethod("set_Item")) - .LdLocal(secret); - FreeLocal(secret); - } - else if(postfix.Child is MapAccessNode map) - { - var secret = GetLocal(); - MapAccessSet(map); - emit.Call(typeof(Dictionary).GetMethod("get_Item")) - .StLocal(secret) - .LdLocal(secret) - .Call(GetOperator(postfix.Text, typeof(TsObject), postfix.Position)) - .Call(typeof(Dictionary).GetMethod("set_Item")) - .LdLocal(secret); - FreeLocal(secret); - } else if (postfix.Child is VariableToken variable) { var secret = GetLocal(); @@ -3198,9 +3021,9 @@ public void Visit(PrefixNode prefix) //These operators need special handling if (prefix.Text == "++" || prefix.Text == "--") { - var secret = GetLocal(); if (prefix.Child.Type == SyntaxType.ArgumentAccess) { + var secret = GetLocal(); GetAddressIfPossible(prefix.Child); emit.Dup() .Dup() @@ -3208,6 +3031,7 @@ public void Visit(PrefixNode prefix) .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) .StObj(typeof(TsObject)) .LdObj(typeof(TsObject)); + FreeLocal(secret); } else if (prefix.Child.Type == SyntaxType.ArrayAccess) { @@ -3218,10 +3042,10 @@ public void Visit(PrefixNode prefix) var top = emit.GetTop(); if (top == typeof(TsObject)) { - secret = GetLocal(); - emit.StLocal(secret) - .LdLocalA(secret); - FreeLocal(secret); + var temp = GetLocal(); + emit.StLocal(temp) + .LdLocalA(temp); + FreeLocal(temp); } else if (top != typeof(TsObject).MakePointerType()) { @@ -3232,8 +3056,7 @@ public void Visit(PrefixNode prefix) var isArray = emit.DefineLabel(); var end = emit.DefineLabel(); - FreeLocal(secret); - secret = GetLocal(typeof(ITsInstance)); + var secret = GetLocal(typeof(ITsInstance)); if (CanBeArrayAccess(array)) { @@ -3358,39 +3181,9 @@ public void Visit(PrefixNode prefix) .Pop() .LdLocal(value); } - + FreeLocal(secret); FreeLocal(value); } - else if (prefix.Child is ListAccessNode list) - { - ListAccessSet(list, 2); - emit.Call(typeof(List).GetMethod("get_Item")) - .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) - .Dup() - .StLocal(secret) - .Call(typeof(List).GetMethod("set_Item")) - .LdLocal(secret); - } - else if (prefix.Child is GridAccessNode grid) - { - GridAccessSet(grid); - emit.Call(typeof(Grid).GetMethod("get_Item")) - .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) - .Dup() - .StLocal(secret) - .Call(typeof(Grid).GetMethod("set_Item")) - .LdLocal(secret); - } - else if (prefix.Child is MapAccessNode map) - { - MapAccessSet(map); - emit.Call(typeof(Dictionary).GetMethod("get_Item")) - .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) - .Dup() - .StLocal(secret) - .Call(typeof(Dictionary).GetMethod("set_Item")) - .LdLocal(secret); - } else if (prefix.Child is VariableToken variable) { if (_table.Defined(variable.Text, out var symbol)) @@ -3404,6 +3197,7 @@ public void Visit(PrefixNode prefix) } else { + var secret = GetLocal(); SelfAccessSet(variable); emit.Call(typeof(ITsInstance).GetMethod("get_Item")) .Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) @@ -3411,6 +3205,7 @@ public void Visit(PrefixNode prefix) .LdLocal(secret) .Call(typeof(ITsInstance).GetMethod("set_Item")) .LdLocal(secret); + FreeLocal(secret); } } else if (prefix.Child is MemberAccessNode member) @@ -3421,6 +3216,7 @@ public void Visit(PrefixNode prefix) emit.Call(TsTypes.Empty); return; } + var secret = GetLocal(); if (member.Left is ReadOnlyToken read) { Func loadTarget = GetReadOnlyLoadFunc(read); @@ -3455,11 +3251,10 @@ public void Visit(PrefixNode prefix) FreeLocal(target); } + FreeLocal(secret); } else _errors.Add(new CompileException($"Invalid syntax detected {prefix.Position}")); - - FreeLocal(secret); } else { diff --git a/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs b/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs index 9e5fa1e..74af1da 100644 --- a/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs +++ b/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs @@ -69,7 +69,6 @@ public enum TokenType Return, Script, SemiColon, - Sharp, ShiftLeft, ShiftRight, String, diff --git a/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs b/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs index b88d720..ffad36a 100644 --- a/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs +++ b/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs @@ -143,7 +143,6 @@ static Tokenizer() { "%", TokenType.Modulo }, { ",", TokenType.Comma }, { "?", TokenType.QuestionMark }, - { "#", TokenType.Sharp }, { ":", TokenType.Colon }, }; for (var i = 0; i < 16; i++) diff --git a/TaffyScriptCompiler/Front End/Parser.cs b/TaffyScriptCompiler/Front End/Parser.cs index 998590f..8a320b8 100644 --- a/TaffyScriptCompiler/Front End/Parser.cs +++ b/TaffyScriptCompiler/Front End/Parser.cs @@ -934,15 +934,7 @@ private ISyntaxElement PrimaryExpression() Throw(new InvalidTokenException(accessToken, "Cannot use an accessor on a newed value")); return value; } - ISyntaxNode access; - if (Validate(TokenType.BitwiseOr)) - access = _factory.CreateNode(SyntaxType.ListAccess, value.Position); - else if (Validate(TokenType.Sharp)) - access = _factory.CreateNode(SyntaxType.GridAccess, value.Position); - else if (Validate(TokenType.QuestionMark)) - access = _factory.CreateNode(SyntaxType.MapAccess, value.Position); - else - access = _factory.CreateNode(SyntaxType.ArrayAccess, value.Position); + ISyntaxNode access = _factory.CreateNode(SyntaxType.ArrayAccess, value.Position); access.AddChild(value); access.AddChild(Expression()); diff --git a/TaffyScriptCompiler/Syntax/Concrete/ExplicitArrayAccess.cs b/TaffyScriptCompiler/Syntax/Concrete/ExplicitArrayAccess.cs deleted file mode 100644 index 31eb15a..0000000 --- a/TaffyScriptCompiler/Syntax/Concrete/ExplicitArrayAccess.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace TaffyScriptCompiler.Syntax -{ - public class ExplicitArrayAccessNode : SyntaxNode - { - public ISyntaxElement Left => Children[0]; - public ISyntaxElement Right => Children[1]; - public override SyntaxType Type => SyntaxType.ExplicitArrayAccess; - - public ExplicitArrayAccessNode(string value, TokenPosition position) : base(value, position) - { - } - - public override void Accept(ISyntaxElementVisitor visitor) - { - visitor.Visit(this); - } - } -} diff --git a/TaffyScriptCompiler/Syntax/Concrete/GridAccess.cs b/TaffyScriptCompiler/Syntax/Concrete/GridAccess.cs deleted file mode 100644 index d59c1b3..0000000 --- a/TaffyScriptCompiler/Syntax/Concrete/GridAccess.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace TaffyScriptCompiler.Syntax -{ - public class GridAccessNode : SyntaxNode - { - public ISyntaxElement Left => Children[0]; - public ISyntaxElement X => Children[1]; - public ISyntaxElement Y => Children[2]; - public override SyntaxType Type => SyntaxType.GridAccess; - - public GridAccessNode(string value, TokenPosition position) : base(value, position) - { - } - - public override void Accept(ISyntaxElementVisitor visitor) - { - visitor.Visit(this); - } - } -} diff --git a/TaffyScriptCompiler/Syntax/Concrete/ListAccess.cs b/TaffyScriptCompiler/Syntax/Concrete/ListAccess.cs deleted file mode 100644 index 043e89b..0000000 --- a/TaffyScriptCompiler/Syntax/Concrete/ListAccess.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace TaffyScriptCompiler.Syntax -{ - public class ListAccessNode : SyntaxNode - { - public ISyntaxElement Left => Children[0]; - public ISyntaxElement Right => Children[1]; - public override SyntaxType Type => SyntaxType.ListAccess; - - public ListAccessNode(string value, TokenPosition position) : base(value, position) - { - } - - public override void Accept(ISyntaxElementVisitor visitor) - { - visitor.Visit(this); - } - } -} diff --git a/TaffyScriptCompiler/Syntax/Concrete/MapAccess.cs b/TaffyScriptCompiler/Syntax/Concrete/MapAccess.cs deleted file mode 100644 index 18698de..0000000 --- a/TaffyScriptCompiler/Syntax/Concrete/MapAccess.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace TaffyScriptCompiler.Syntax -{ - public class MapAccessNode : SyntaxNode - { - public ISyntaxElement Left => Children[0]; - public ISyntaxElement Right => Children[1]; - public override SyntaxType Type => SyntaxType.MapAccess; - - public MapAccessNode(string value, TokenPosition position) : base(value, position) - { - } - - public override void Accept(ISyntaxElementVisitor visitor) - { - visitor.Visit(this); - } - } -} diff --git a/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs b/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs index 69b8c58..e6ab959 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs +++ b/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs @@ -43,10 +43,6 @@ public interface ISyntaxElementVisitor void Visit(ImportNode import); void Visit(PostfixNode postfix); void Visit(ArrayAccessNode arrayAccess); - void Visit(ExplicitArrayAccessNode explicitArrayAccess); - void Visit(MapAccessNode mapAccess); - void Visit(GridAccessNode gridAccess); - void Visit(ListAccessNode listAccess); void Visit(MemberAccessNode memberAccess); void Visit(FunctionCallNode functionCall); void Visit(ConditionalNode conditional); diff --git a/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs b/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs index 89befc2..89dec26 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs +++ b/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs @@ -70,14 +70,6 @@ public ISyntaxNode CreateNode(SyntaxType type, TokenPosition position) return new ConditionalNode(null, position); case SyntaxType.MemberAccess: return new MemberAccessNode(null, position); - case SyntaxType.ListAccess: - return new ListAccessNode(null, position); - case SyntaxType.GridAccess: - return new GridAccessNode(null, position); - case SyntaxType.MapAccess: - return new MapAccessNode(null, position); - case SyntaxType.ExplicitArrayAccess: - return new ExplicitArrayAccessNode(null, position); case SyntaxType.ArrayAccess: return new ArrayAccessNode(null, position); case SyntaxType.ArgumentAccess: diff --git a/TaffyScriptCompiler/Syntax/SyntaxType.cs b/TaffyScriptCompiler/Syntax/SyntaxType.cs index bf5b78e..5ef7139 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxType.cs +++ b/TaffyScriptCompiler/Syntax/SyntaxType.cs @@ -23,11 +23,7 @@ public enum SyntaxType Prefix, FunctionCall, MemberAccess, - ListAccess, - GridAccess, - MapAccess, ArrayAccess, - ExplicitArrayAccess, Postfix, ArrayLiteral, Declare, @@ -51,9 +47,6 @@ public enum SyntaxType Namespace, New, ImportObject, - ImportObjectMember, - ImportObjectMethod, - ImportObjectConstructor, //Token Constant, diff --git a/TaffyScriptCompiler/TaffyScriptCompiler.csproj b/TaffyScriptCompiler/TaffyScriptCompiler.csproj index a71e623..a446260 100644 --- a/TaffyScriptCompiler/TaffyScriptCompiler.csproj +++ b/TaffyScriptCompiler/TaffyScriptCompiler.csproj @@ -112,20 +112,16 @@ - - - - From e5208159f8b3158fa826c75ec562d8928dda6dc7 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 May 2018 13:31:21 -0600 Subject: [PATCH 16/54] Update Changelog.md --- Changelog.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/Changelog.md b/Changelog.md index dbc9bef..9da5be2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,42 @@ +# Release 1.7.0 +### Temporarily Removed `with`; Permanently Changed it's Functionality +TaffyScript instances are no longer bound to an id. Therefore, the way with originally worked is no longer valid. Removing id's from instances will make them work much faster (depending on the operations, sometimes up to a 300% increase), and allow them to be garbage collected. This means you no longer have to call `.destroy()` on every instance. It also makes the next major change much easier to implement. + +### Import C# Objects +You can now import a c# object to be usable from within TaffyScript. When imported, a special wrapper class is created that allows the object to be used as any other TS object. There are two import modes: explicit and automatic. In the eplicit mode you layout what methods, fields, properties, and constructor to import. In the automatic mode, all methods/properties/fields that have valid TS types are imported, as well as the first valid constructor. Until the wiki page is created you can check out [this](https://github.com/mystborn/TaffyScript/blob/dev-experimental/Samples/TestSuite/Tests/object_import.tfs) page which shows some example imports. + +### Object Indexers +_This functionality is still under consideration and is highly subject to change._ + +You can now define indexers on objects. This functionality was created to support accessors on c# objects. To define an accessor, simply define a combination of `get` and `set` events on an object. Then you can call those methods using array access syntax. The values inside the brackets will be passed to the respective method. + +### Deprecated ds_* Scripts +These scripts were removed in favor of imported c# objects. The new c# objects are ds_list, ds_map, and ds_grid. More information will be added to the wiki soon. + +### Full Changelog +* Made Binders more efficient +* Fixed excluding files +* Made all `ISyntaxElement`s have a `Text` property. Means less casting and more clear code during compilation phase. +* Better errors when using an addition operator. +* Added an `ITsInstance` interface that all instances must derive from +* Made `TsInstance` inherit from `ITsInstance`. +* Changed TsScript first argument to be `ITsInstance`. +* Changed `TsDelegate` `Target` to be of type `ITsInstance`. +* All WeakMethod first arguments have been changed to use `ITsInstance` instead of `TsInstance`. +* Removed `InstanceEnumerator` as it no longer functioned. +* Temporarily removed variable_instance_* scripts. +* Made `TsObject` wrap `ITsInstance`. +* Added some timer related methods to the UnitTest library. +* Added MemberAccessException. +* Implemented types for ds_list, ds_map, and ds_grid. +* Added the ability to import c# objects. +* Temporarily removed `with` block. +* Added the ability to natively import any type that inherits from `ITsInstance` in a fashion similar to importing `WeakMethod`s. +* Allow objects to have indexer syntax with get and set scripts. +* Fixed bug when resizing a 2d array. +* Fully deprecated ds_* scripts +* Removed indexer accessor tokens + # Release 1.6.1.0 _General fixes and updates related to the script rework. Many bug fixes and performance enhancements._ From 68a18f23ad5bd6e5c55c0c7fe9fa263d7ffd9bca Mon Sep 17 00:00:00 2001 From: mystborn Date: Wed, 2 May 2018 16:47:23 -0700 Subject: [PATCH 17/54] Fixed With --- Samples/TestSuite/Tests/tests.tfs | 2 + Samples/TestSuite/Tests/with.tfs | 58 +++++++++++++++++++ TaffyScript/TsInstance.cs | 2 +- .../Backend/Compiler/MsilWeakCodeGen.cs | 46 ++++++++++++++- .../Front End/LexicalAnalysis/TokenType.cs | 1 + .../Front End/LexicalAnalysis/Tokenizer.cs | 4 +- TaffyScriptCompiler/Front End/Parser.cs | 10 ++++ .../Syntax/Concrete/WithNode.cs | 21 +++++++ .../Syntax/ISyntaxElementVisitor.cs | 1 + .../Syntax/SyntaxElementFactory.cs | 2 + .../TaffyScriptCompiler.csproj | 1 + 11 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 Samples/TestSuite/Tests/with.tfs create mode 100644 TaffyScriptCompiler/Syntax/Concrete/WithNode.cs diff --git a/Samples/TestSuite/Tests/tests.tfs b/Samples/TestSuite/Tests/tests.tfs index 09b8278..991791d 100644 --- a/Samples/TestSuite/Tests/tests.tfs +++ b/Samples/TestSuite/Tests/tests.tfs @@ -26,5 +26,7 @@ namespace LanguageTests { show_debug_message(""); run_map_tests(); show_debug_message(""); + run_with_tests(); + show_debug_message(""); } } \ No newline at end of file diff --git a/Samples/TestSuite/Tests/with.tfs b/Samples/TestSuite/Tests/with.tfs new file mode 100644 index 0000000..19a6099 --- /dev/null +++ b/Samples/TestSuite/Tests/with.tfs @@ -0,0 +1,58 @@ +using UnitTest; + +namespace LanguageTests { + script run_with_tests() { + var tests = new obj_unit_test("With Tests", + with_can_compile, + with_can_access_local, + with_can_call_event, + with_sets_other); + tests.run_tests(); + } + + script with_can_compile() { + test_it("with(obj)"); + var obj = new obj_with(0); + with(obj) { + var i = 0; + } + } + + script with_can_access_local() { + test_it("with(obj) local"); + var obj = new obj_with(2); + with(obj) { + assert_equal(num, 2); + } + } + + script with_can_call_event() { + test_it("with(obj) event()"); + var obj = new obj_with(2); + with(obj) { + assert_equal(get_value(), 4); + } + } + + script with_sets_other() { + test_it("with(obj) other.val"); + var obj2 = new obj_with(2); + var obj3 = new obj_with(3); + with(obj2) { + with(obj3) { + assert_equal(other.num, 2); + assert_equal(num, 3); + } + } + } + + object obj_with { + event create(num) { + self.num = num; + } + + event get_value() { + return 4; + } + } +} \ No newline at end of file diff --git a/TaffyScript/TsInstance.cs b/TaffyScript/TsInstance.cs index a2fe16c..c56f680 100644 --- a/TaffyScript/TsInstance.cs +++ b/TaffyScript/TsInstance.cs @@ -66,7 +66,7 @@ public class TsInstance : ITsInstance /// /// References the target of the parent scope in a with block. /// - public static TsInstance Other { get; set; } + public static ITsInstance Other { get; set; } /// /// Gets or sets a value based on a variable name. diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index de4c11c..6ec2c6a 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -1436,6 +1436,9 @@ public void Visit(AssignNode assign) case "self": emit.LdArg(0); break; + case "other": + emit.Call(typeof(TsInstance).GetMethod("get_Other")); + break; default: _errors.Add(new CompileException($"Cannot access member on non-global readonly value {token.Position}")); return; @@ -2478,6 +2481,9 @@ public void Visit(MemberAccessNode memberAccess) case "self": emit.LdArg(0); break; + case "other": + emit.Call(typeof(TsInstance).GetMethod("get_Other")); + break; default: _errors.Add(new CompileException($"Invalid syntax detected {right.Position}")); emit.Call(TsTypes.Empty); @@ -2519,7 +2525,7 @@ public void Visit(MemberAccessNode memberAccess) } else if (memberAccess.Right is ReadOnlyToken readOnly) { - if (readOnly.Text != "id" && readOnly.Text != "self") + if (readOnly.Text != "self") { _errors.Add(new NotImplementedException($"Only the read only variables id and self can be accessed from an instance currently {readOnly.Position}")); emit.Call(TsTypes.Empty); @@ -3010,6 +3016,8 @@ private Func GetReadOnlyLoadFunc(ReadOnlyToken read) { if (read.Text == "global") return () => emit.LdFld(typeof(TsInstance).GetField("Global")); + else if (read.Text == "other") + return () => emit.Call(typeof(TsInstance).GetMethod("get_Other")); else return () => emit.LdArg(0); } @@ -3272,9 +3280,11 @@ public void Visit(ReadOnlyToken readOnlyToken) switch(readOnlyToken.Text) { case "self": - case "id": emit.LdArg(0); break; + case "other": + emit.Call(typeof(TsInstance).GetMethod("get_Other")); + break; case "argument_count": if(_argumentCount == null) { @@ -3728,6 +3738,38 @@ public void Visit(WhileNode whileNode) .MarkLabel(end); } + public void Visit(WithNode with) + { + GetAddressIfPossible(with.Target); + var top = emit.GetTop(); + if (top == typeof(TsObject) || top == typeof(TsObject).MakePointerType()) + CallInstanceMethod(TsTypes.ObjectCasts[typeof(ITsInstance)], with.Target.Position); + else if(!typeof(ITsInstance).IsAssignableFrom(top)) + { + emit.Pop(); + LogError(new CompileException($"Invalid target for with statement {with.Target.Position}"), false); + return; + } + var other = GetLocal(typeof(ITsInstance)); + var get = typeof(TsInstance).GetMethod("get_Other"); + var set = typeof(TsInstance).GetMethod("set_Other"); + + emit.Call(get) + .StLocal(other) + .LdArg(0) + .Call(set) + .StArg(0); + + with.Body.Accept(this); + + emit.Call(get) + .StArg(0) + .LdLocal(other) + .Call(set); + + FreeLocal(other); + } + public void Visit(ImportObjectNode importNode) { ImportObjectLeaf leaf = (ImportObjectLeaf)_table.Defined(importNode.ImportName.Value); diff --git a/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs b/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs index 74af1da..da196e0 100644 --- a/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs +++ b/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs @@ -78,6 +78,7 @@ public enum TokenType Using, Var, While, + With, Xor, XorEquals } diff --git a/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs b/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs index ffad36a..52441e9 100644 --- a/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs +++ b/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs @@ -73,6 +73,7 @@ static Tokenizer() { "repeat", TokenType.Repeat }, { "do", TokenType.Do }, { "until", TokenType.Until }, + { "with", TokenType.With }, { "if", TokenType.If }, { "else", TokenType.Else }, { "for", TokenType.For }, @@ -88,11 +89,10 @@ static Tokenizer() { "argument_count", TokenType.ReadOnly }, { "all", TokenType.ReadOnly }, { "noone", TokenType.ReadOnly }, - { "id", TokenType.ReadOnly }, { "self", TokenType.ReadOnly }, { "pi", TokenType.ReadOnly }, { "global", TokenType.ReadOnly }, - { "instance_count", TokenType.ReadOnly }, + { "other", TokenType.ReadOnly }, { "object", TokenType.Object }, { "event", TokenType.Event }, { "using", TokenType.Using }, diff --git a/TaffyScriptCompiler/Front End/Parser.cs b/TaffyScriptCompiler/Front End/Parser.cs index 8a320b8..76872ec 100644 --- a/TaffyScriptCompiler/Front End/Parser.cs +++ b/TaffyScriptCompiler/Front End/Parser.cs @@ -563,6 +563,16 @@ private ISyntaxElement SimpleStatement() temp.AddChild(BodyStatement()); result = temp; break; + case TokenType.With: + Confirm(TokenType.With); + temp = _factory.CreateNode(SyntaxType.With, next.Position); + paren = Validate(TokenType.OpenParen); + temp.AddChild(Expression()); + if (paren) + Confirm(TokenType.CloseParen); + temp.AddChild(BodyStatement()); + result = temp; + break; case TokenType.Do: Confirm(TokenType.Do); temp = _factory.CreateNode(SyntaxType.Do, next.Position); diff --git a/TaffyScriptCompiler/Syntax/Concrete/WithNode.cs b/TaffyScriptCompiler/Syntax/Concrete/WithNode.cs new file mode 100644 index 0000000..2bf8748 --- /dev/null +++ b/TaffyScriptCompiler/Syntax/Concrete/WithNode.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace TaffyScriptCompiler.Syntax +{ + public class WithNode : SyntaxNode + { + public override SyntaxType Type => SyntaxType.With; + public ISyntaxElement Target => Children[0]; + public ISyntaxElement Body => Children[1]; + + public WithNode(string value, TokenPosition position) + : base(value, position) + { + } + + public override void Accept(ISyntaxElementVisitor visitor) + { + visitor.Visit(this); + } + } +} \ No newline at end of file diff --git a/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs b/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs index e6ab959..d90832d 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs +++ b/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs @@ -15,6 +15,7 @@ public interface ISyntaxElementVisitor void Visit(NewNode newNode); void Visit(NamespaceNode namespaceNode); void Visit(ImportObjectNode importObjectNode); + void Visit(WithNode withNode); void Visit(ObjectNode objectNode); void Visit(ContinueToken continueToken); void Visit(UsingsNode usingsNode); diff --git a/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs b/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs index 89dec26..3c2907b 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs +++ b/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs @@ -50,6 +50,8 @@ public ISyntaxNode CreateNode(SyntaxType type, TokenPosition position) return new ReturnNode(null, position); case SyntaxType.While: return new WhileNode(null, position); + case SyntaxType.With: + return new WithNode(null, position); case SyntaxType.Repeat: return new RepeatNode(null, position); case SyntaxType.Do: diff --git a/TaffyScriptCompiler/TaffyScriptCompiler.csproj b/TaffyScriptCompiler/TaffyScriptCompiler.csproj index a446260..291be69 100644 --- a/TaffyScriptCompiler/TaffyScriptCompiler.csproj +++ b/TaffyScriptCompiler/TaffyScriptCompiler.csproj @@ -140,6 +140,7 @@ + From a8628042a4a3f52ec95598d26e3fc6309a4777b2 Mon Sep 17 00:00:00 2001 From: mystborn Date: Wed, 2 May 2018 16:51:38 -0700 Subject: [PATCH 18/54] Updated With Tests --- Samples/TestSuite/Tests/with.tfs | 37 +++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/Samples/TestSuite/Tests/with.tfs b/Samples/TestSuite/Tests/with.tfs index 19a6099..94ac7bb 100644 --- a/Samples/TestSuite/Tests/with.tfs +++ b/Samples/TestSuite/Tests/with.tfs @@ -1,41 +1,62 @@ using UnitTest; +using TaffyScript.Collections; namespace LanguageTests { script run_with_tests() { var tests = new obj_unit_test("With Tests", with_can_compile, - with_can_access_local, - with_can_call_event, + with_can_access_local_ts, + with_can_access_local_cs, + with_can_call_event_ts, + with_can_call_event_cs, with_sets_other); tests.run_tests(); } script with_can_compile() { - test_it("with(obj)"); + test_it("with(ts)"); var obj = new obj_with(0); with(obj) { var i = 0; } } - script with_can_access_local() { - test_it("with(obj) local"); + script with_can_access_local_ts() { + test_it("with(ts) local"); var obj = new obj_with(2); with(obj) { assert_equal(num, 2); } } - script with_can_call_event() { - test_it("with(obj) event()"); + script with_can_access_local_cs() { + test_it("with(cs) local"); + var list = new ds_list(); + list.add(3); + with(list) { + assert_equal(count, 1); + } + } + + script with_can_call_event_ts() { + test_it("with(ts) event()"); var obj = new obj_with(2); with(obj) { assert_equal(get_value(), 4); } } + script with_can_call_event_cs() { + test_it("with(cs) event()"); + var list = new ds_list(); + with(list) { + add(4, 3); + } + assert_equal(list.count, 2); + } + script with_sets_other() { - test_it("with(obj) other.val"); + test_it("with(ts) other.val"); var obj2 = new obj_with(2); var obj3 = new obj_with(3); with(obj2) { From d03e55c57f4ace1be1065957dbd423fe7764b1db Mon Sep 17 00:00:00 2001 From: mystborn Date: Wed, 2 May 2018 19:59:08 -0700 Subject: [PATCH 19/54] Removed Destroyed Delegate --- Samples/TestSuite/Tests/addition.tfs | 1 - Samples/TestSuite/Tests/division.tfs | 1 - Samples/TestSuite/Tests/modulus.tfs | 1 - Samples/TestSuite/Tests/multiplication.tfs | 1 - Samples/TestSuite/Tests/prefix.tfs | 6 -- Samples/TestSuite/Tests/subtraction.tfs | 1 - Samples/TestSuite/Tests/ternary.tfs | 1 - Samples/TestSuite/Tests/time_tests.tfs | 20 ---- TaffyScript/Collections/TsGrid.cs | 8 -- TaffyScript/Collections/TsList.cs | 8 -- TaffyScript/Collections/TsMap.cs | 8 -- TaffyScript/ITsInstance.cs | 9 -- TaffyScript/TsDelegate.cs | 10 -- TaffyScript/TsInstance.cs | 44 --------- .../Backend/BaseClassLibrary.cs | 1 - .../Backend/Compiler/MsilWeakCodeGen.cs | 91 +------------------ 16 files changed, 4 insertions(+), 207 deletions(-) delete mode 100644 Samples/TestSuite/Tests/time_tests.tfs diff --git a/Samples/TestSuite/Tests/addition.tfs b/Samples/TestSuite/Tests/addition.tfs index 4a064a3..aa7c0a5 100644 --- a/Samples/TestSuite/Tests/addition.tfs +++ b/Samples/TestSuite/Tests/addition.tfs @@ -14,7 +14,6 @@ namespace LanguageTests { run_addition_faulty_tests); tests.run_tests(); - tests.destroy(); } script run_addition_faulty_tests() { diff --git a/Samples/TestSuite/Tests/division.tfs b/Samples/TestSuite/Tests/division.tfs index 50c6aec..cfd3316 100644 --- a/Samples/TestSuite/Tests/division.tfs +++ b/Samples/TestSuite/Tests/division.tfs @@ -10,7 +10,6 @@ namespace LanguageTests { run_division_faulty_tests); tests.run_tests(); - tests.destroy(); } script run_division_faulty_tests() { diff --git a/Samples/TestSuite/Tests/modulus.tfs b/Samples/TestSuite/Tests/modulus.tfs index 501f6e3..7d7a893 100644 --- a/Samples/TestSuite/Tests/modulus.tfs +++ b/Samples/TestSuite/Tests/modulus.tfs @@ -10,7 +10,6 @@ namespace LanguageTests { run_modulus_faulty_tests); tests.run_tests(); - tests.destroy(); } script run_modulus_faulty_tests() { diff --git a/Samples/TestSuite/Tests/multiplication.tfs b/Samples/TestSuite/Tests/multiplication.tfs index 4ab4ab1..7c516c3 100644 --- a/Samples/TestSuite/Tests/multiplication.tfs +++ b/Samples/TestSuite/Tests/multiplication.tfs @@ -10,7 +10,6 @@ namespace LanguageTests { run_multiplication_faulty_tests); tests.run_tests(); - tests.destroy(); } script run_multiplication_faulty_tests() { diff --git a/Samples/TestSuite/Tests/prefix.tfs b/Samples/TestSuite/Tests/prefix.tfs index 88bc0e6..8fe4e25 100644 --- a/Samples/TestSuite/Tests/prefix.tfs +++ b/Samples/TestSuite/Tests/prefix.tfs @@ -31,8 +31,6 @@ namespace LanguageTests { obj.prefix_decrement_self_var); tests.run_tests(); - tests.destroy(); - obj.destroy(); } script prefix_negate() { @@ -188,7 +186,6 @@ namespace LanguageTests { var j = ++obj.val; assert_equal(j, 4); assert_equal(obj.val, 4); - obj.destroy(); } script prefix_decrement_local_object_var() { @@ -199,7 +196,6 @@ namespace LanguageTests { var j = --obj.val; assert_equal(j, 0); assert_equal(obj.val, 0); - obj.destroy(); } script prefix_increment_global_var() { @@ -230,7 +226,6 @@ namespace LanguageTests { var j = ++global.obj.val; assert_equal(j, 4); assert_equal(global.obj.val, 4); - global.obj.destroy(); } script prefix_decrement_global_object_var() { @@ -241,7 +236,6 @@ namespace LanguageTests { var j = --global.obj.val; assert_equal(j, 0); assert_equal(global.obj.val, 0); - global.obj.destroy(); } object obj_prefix { diff --git a/Samples/TestSuite/Tests/subtraction.tfs b/Samples/TestSuite/Tests/subtraction.tfs index 746115e..e48dcfd 100644 --- a/Samples/TestSuite/Tests/subtraction.tfs +++ b/Samples/TestSuite/Tests/subtraction.tfs @@ -10,7 +10,6 @@ namespace LanguageTests { run_subtraction_faulty_tests); tests.run_tests(); - tests.destroy(); } script run_subtraction_faulty_tests() { diff --git a/Samples/TestSuite/Tests/ternary.tfs b/Samples/TestSuite/Tests/ternary.tfs index f8df362..feb1467 100644 --- a/Samples/TestSuite/Tests/ternary.tfs +++ b/Samples/TestSuite/Tests/ternary.tfs @@ -7,7 +7,6 @@ namespace LanguageTests { ternary_argument_assign); tests.run_tests(); - tests.destroy(); } script ternary_var_assign() { diff --git a/Samples/TestSuite/Tests/time_tests.tfs b/Samples/TestSuite/Tests/time_tests.tfs deleted file mode 100644 index b8b5fe7..0000000 --- a/Samples/TestSuite/Tests/time_tests.tfs +++ /dev/null @@ -1,20 +0,0 @@ -using UnitTest; - -namespace LanguageTests { - script scr_object_cycle(iter) { - for(var i = 0; i < iter; i++) { - var obj = new obj_time(); - obj.destroy(); - } - } - - script scr_obj_create(iter) { - for(var i = 0; i < iter; i++) { - var obj = new obj_time(); - } - } - - object obj_time { - - } -} \ No newline at end of file diff --git a/TaffyScript/Collections/TsGrid.cs b/TaffyScript/Collections/TsGrid.cs index b5138a0..c807f19 100644 --- a/TaffyScript/Collections/TsGrid.cs +++ b/TaffyScript/Collections/TsGrid.cs @@ -21,8 +21,6 @@ public TsObject this[string memberName] public string ObjectType => "ds_grid"; public Grid Source => _source; - public event DestroyedDelegate Destroyed; - public TsGrid(TsObject[] args) { _source = new Grid((int)args[0], (int)args[1]); @@ -115,12 +113,6 @@ public TsObject Call(string scriptName, params TsObject[] args) return TsObject.Empty(); } - public void Destroy() - { - Destroyed?.Invoke(this); - _source = null; - } - public TsDelegate GetDelegate(string scriptName) { if (TryGetDelegate(scriptName, out var del)) diff --git a/TaffyScript/Collections/TsList.cs b/TaffyScript/Collections/TsList.cs index 3ef96d5..f58f876 100644 --- a/TaffyScript/Collections/TsList.cs +++ b/TaffyScript/Collections/TsList.cs @@ -20,8 +20,6 @@ public TsObject this[string memberName] public string ObjectType => "ds_list"; public List Source => _source; - public event DestroyedDelegate Destroyed; - public TsList(TsObject[] args) { _source = new List(); @@ -66,12 +64,6 @@ public TsObject Call(string scriptName, params TsObject[] args) return TsObject.Empty(); } - public void Destroy() - { - Destroyed?.Invoke(this); - _source = null; - } - public TsDelegate GetDelegate(string scriptName) { if (TryGetDelegate(scriptName, out var del)) diff --git a/TaffyScript/Collections/TsMap.cs b/TaffyScript/Collections/TsMap.cs index 6778244..246e240 100644 --- a/TaffyScript/Collections/TsMap.cs +++ b/TaffyScript/Collections/TsMap.cs @@ -20,8 +20,6 @@ public TsObject this[string memberName] public string ObjectType => "ds_map"; public Dictionary Source => _source; - public event DestroyedDelegate Destroyed; - public TsMap(TsObject[] args) { } @@ -62,12 +60,6 @@ public TsObject Call(string scriptName, params TsObject[] args) return TsObject.Empty(); } - public void Destroy() - { - Destroyed?.Invoke(this); - _source = null; - } - public TsDelegate GetDelegate(string delegateName) { if (TryGetDelegate(delegateName, out var del)) diff --git a/TaffyScript/ITsInstance.cs b/TaffyScript/ITsInstance.cs index d9e3867..96eba51 100644 --- a/TaffyScript/ITsInstance.cs +++ b/TaffyScript/ITsInstance.cs @@ -11,10 +11,6 @@ namespace TaffyScript /// public interface ITsInstance { - /// - /// Event that gets triggered when this instance is destroyed. - /// - event DestroyedDelegate Destroyed; /// /// Gets or sets a value based on a variable name. @@ -42,11 +38,6 @@ public interface ITsInstance /// The new value. void SetMember(string name, TsObject value); - /// - /// Destroys this instance. - /// - void Destroy(); - /// /// Gets a delegate defined by this instance. /// diff --git a/TaffyScript/TsDelegate.cs b/TaffyScript/TsDelegate.cs index 580f280..bb64a40 100644 --- a/TaffyScript/TsDelegate.cs +++ b/TaffyScript/TsDelegate.cs @@ -20,7 +20,6 @@ public class TsDelegate : IEquatable public TsScriptScope ScriptScope { get; } public TsScript Script { get; private set; } public ITsInstance Target { get; private set; } - public bool Disposed { get; private set; } = false; public string Name { get; } public TsDelegate(TsScript script, string name) @@ -36,7 +35,6 @@ public TsDelegate(TsScript script, string name, ITsInstance target) ScriptScope = TsScriptScope.Instance; Target = target; Script = script; - target.Destroyed += OnTargetDestroyed; Name = name; } @@ -73,8 +71,6 @@ public TsObject Invoke(params TsObject[] args) Array.Copy(args, 1, scriptArgs, 0, args.Length - 1); return Script(target, scriptArgs); } - else if (Disposed) - throw new ObjectDisposedException("Target", "The target of this script has been destroyed."); return Script(Target, args); } @@ -86,12 +82,6 @@ public TsObject Invoke(ITsInstance target, params TsObject[] args) return Script(target, args); } - private void OnTargetDestroyed(ITsInstance inst) - { - Disposed = true; - Target = null; - } - public override bool Equals(object obj) { if (obj is TsDelegate del) diff --git a/TaffyScript/TsInstance.cs b/TaffyScript/TsInstance.cs index c56f680..48bae90 100644 --- a/TaffyScript/TsInstance.cs +++ b/TaffyScript/TsInstance.cs @@ -9,24 +9,12 @@ namespace TaffyScript { - /// - /// Delegate used to represent methods to be triggered when a TS instance is destroyed. - /// - /// The instance that was destroyed. - public delegate void DestroyedDelegate(ITsInstance inst); - /// /// Represents an instance of an object in TaffyScript. /// public class TsInstance : ITsInstance { private const string CreateEvent = "create"; - private const string DestroyEvent = "destroy"; - - /// - /// Event that gets triggered when this instance is destroyed. - /// - public event DestroyedDelegate Destroyed; private Dictionary _vars = new Dictionary(); @@ -256,9 +244,6 @@ public void SetMember(string name, TsObject value) /// Determines whether the events are performed public void ChangeType(string type, bool performEvents) { - if (performEvents && TryGetDelegate(DestroyEvent, out var destroy)) - destroy.Invoke(this, null); - ObjectType = type; Init(performEvents); } @@ -278,19 +263,6 @@ public TsInstance Copy(bool performEvents) return copy; } - /// - /// Destroys this instance in the eyes of TaffyScript - /// - /// - /// Make this object inherit from IDisposable, change this to Dispose method? - /// - public void Destroy() - { - if (TryGetDelegate(DestroyEvent, out var destroy)) - destroy.Invoke(this, null); - Destroyed?.Invoke(this); - } - public override string ToString() { return $"{ObjectType} {Id}"; @@ -387,22 +359,6 @@ public static TsObject InstanceCreate(ITsInstance target, TsObject[] args) return new TsObject(inst); } - /// - /// Destroys a previously created instance. This overload should not be called. - /// - /// Currently executing instance if any. - /// Optionally contains the id of the instance. - [WeakMethod] - public static TsObject InstanceDestroy(ITsInstance target, TsObject[] args) - { - if (args == null || args.Length == 0) - target.Destroy(); - else - args[0].GetInstance().Destroy(); - - return TsObject.Empty(); - } - /// /// Gets the object type of an instance. /// diff --git a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs b/TaffyScriptCompiler/Backend/BaseClassLibrary.cs index e4cd39d..eac1f23 100644 --- a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs +++ b/TaffyScriptCompiler/Backend/BaseClassLibrary.cs @@ -57,7 +57,6 @@ public static string Generate() sb.AppendLine("import TsInstance.InstanceChange(instance, array) as instance_change"); sb.AppendLine("import TsInstance.InstanceCopy(instance, array) as instance_copy"); sb.AppendLine("import TsInstance.InstanceCreate(instance, array) as instance_create"); - sb.AppendLine("import TsInstance.InstanceDestroy(instance, array) as instance_destroy"); sb.AppendLine("import TsObject.IsArray(object) as is_array"); sb.AppendLine("import TsObject.IsReal(object) as is_real"); diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index 6ec2c6a..a998759 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -2220,20 +2220,10 @@ private void CallEvent(string name, bool loadId, FunctionCallNode functionCall, emit.Call(TsTypes.Empty); return; } - - if(name == "destroy") - { - //Syntactic sugar for instance_destroy(inst); - emit.Call(typeof(ITsInstance).GetMethod("Destroy")) - .Call(TsTypes.Empty); - } - else - { - //The object returned by GetDelegate should already have a target. - emit.LdStr(name); - LoadFunctionArguments(functionCall); - emit.Call(typeof(ITsInstance).GetMethod("Call")); - } + + emit.LdStr(name); + LoadFunctionArguments(functionCall); + emit.Call(typeof(ITsInstance).GetMethod("Call")); } public void Visit(IfNode ifNode) @@ -3815,55 +3805,6 @@ public void Visit(ImportObjectNode importNode) gen.Emit(OpCodes.Ret); objectType.SetGetMethod(getObjectType); - var destroyedField = type.DefineField("Destroyed", typeof(DestroyedDelegate), FieldAttributes.Private); - var destroyedEvent = type.DefineEvent("Destroyed", EventAttributes.None, typeof(DestroyedDelegate)); - var eventArgs = new[] { typeof(DestroyedDelegate) }; - - var addDestroyed = type.DefineMethod("add_Destroyed", - MethodAttributes.Public | - MethodAttributes.HideBySig | - MethodAttributes.NewSlot | - MethodAttributes.SpecialName | - MethodAttributes.Virtual | - MethodAttributes.Final, - typeof(void), - eventArgs); - - emit = new ILEmitter(addDestroyed, eventArgs); - - - emit.LdArg(0) - .Dup() - .LdFld(destroyedField) - .LdArg(1) - .Call(typeof(Delegate).GetMethod("Combine", new[] { typeof(Delegate), typeof(Delegate) })) - .CastClass(typeof(DestroyedDelegate)) - .StFld(destroyedField) - .Ret(); - - destroyedEvent.SetAddOnMethod(addDestroyed); - - var removeDestroyed = type.DefineMethod("remove_Destroyed", - MethodAttributes.Public | - MethodAttributes.HideBySig | - MethodAttributes.NewSlot | - MethodAttributes.SpecialName | - MethodAttributes.Virtual | - MethodAttributes.Final, - typeof(void), - eventArgs); - - emit = new ILEmitter(removeDestroyed, eventArgs); - emit.LdArg(0) - .Dup() - .LdFld(destroyedField) - .LdArg(1) - .Call(typeof(Delegate).GetMethod("Remove", new[] { typeof(Delegate), typeof(Delegate) })) - .CastClass(typeof(DestroyedDelegate)) - .StFld(destroyedField) - .Ret(); - - destroyedEvent.SetRemoveOnMethod(removeDestroyed); var methodFlags = MethodAttributes.Public | MethodAttributes.HideBySig | @@ -3874,30 +3815,6 @@ public void Visit(ImportObjectNode importNode) var weakFlags = MethodAttributes.Public | MethodAttributes.HideBySig; - - - var destroy = type.DefineMethod("Destroy", methodFlags); - - emit = new ILEmitter(destroy, Type.EmptyTypes); - var notNull = emit.DefineLabel(); - var end = emit.DefineLabel(); - - emit.LdArg(0) - .LdFld(destroyedField) - .Dup() - .BrTrue(notNull) - .Pop() - .Br(end) - .MarkLabel(notNull) - .PushType(destroyedField.FieldType) - .LdArg(0) - .Call(typeof(DestroyedDelegate).GetMethod("Invoke", new[] { typeof(ITsInstance) })) - .MarkLabel(end) - .LdArg(0) - .LdNull() //<- this will have to be changed when importing valuetype - .StFld(source) - .Ret(); - var callMethod = type.DefineMethod("Call", methodFlags, typeof(TsObject), new[] { typeof(string), typeof(TsObject[]) }); var getMemberMethod = type.DefineMethod("GetMember", methodFlags, typeof(TsObject), new[] { typeof(string) }); var setMemberMethod = type.DefineMethod("SetMember", methodFlags, typeof(void), new[] { typeof(string), typeof(TsObject) }); From 053c8216fa5f2aec715b04e30299b33dbee12814 Mon Sep 17 00:00:00 2001 From: mystborn Date: Thu, 3 May 2018 12:43:00 -0700 Subject: [PATCH 20/54] Better Reflection on Imports --- TaffyScript/TsInstance.cs | 70 +++++++++---------- .../Backend/Compiler/MsilWeakCodeGen.cs | 41 ++++++++++- TaffyScriptCompiler/Backend/ILEmitter.cs | 11 +++ 3 files changed, 84 insertions(+), 38 deletions(-) diff --git a/TaffyScript/TsInstance.cs b/TaffyScript/TsInstance.cs index 48bae90..c193e64 100644 --- a/TaffyScript/TsInstance.cs +++ b/TaffyScript/TsInstance.cs @@ -46,6 +46,11 @@ public class TsInstance : ITsInstance /// public static Stack EventType { get; } = new Stack(); + /// + /// Maps imported types to a func that will construct an instance of the type. + /// + public static Dictionary> WrappedConstructors { get; } = new Dictionary>(); + /// /// Gets the isntance used to store global variables. /// @@ -73,11 +78,6 @@ public TsObject this[string variableName] set => _vars[variableName] = value; } - /// - /// Gets the id of this instance. - /// - public int Id { get; } - /// /// Gets the type of this instance. /// @@ -115,7 +115,6 @@ private TsInstance(string instanceType, bool performEvent = true, params TsObjec /// private TsInstance() { - Id = -5; ObjectType = ""; } @@ -265,17 +264,7 @@ public TsInstance Copy(bool performEvents) public override string ToString() { - return $"{ObjectType} {Id}"; - } - - public override int GetHashCode() - { - return Id; - } - - public override bool Equals(object obj) - { - return obj is TsInstance inst && inst.Id == Id; + return $"{ObjectType}"; } /// @@ -328,9 +317,9 @@ public static TsObject InstanceChange(ITsInstance inst, TsObject[] args) /// Determines whther or not to perform the create event on the copy. /// [WeakMethod] - public static float InstanceCopy(ITsInstance inst, TsObject[] args) + public static TsObject InstanceCopy(ITsInstance inst, TsObject[] args) { - return ((TsInstance)inst).Copy((bool)args[0]).Id; + return ((TsInstance)inst).Copy((bool)args[0]); } /// @@ -346,17 +335,18 @@ public static float InstanceCopy(ITsInstance inst, TsObject[] args) [WeakMethod] public static TsObject InstanceCreate(ITsInstance target, TsObject[] args) { - TsInstance inst; - if (args.Length > 1) + var type = (string)args[0]; + TsObject[] ctorArgs = null; + if(args.Length > 1) { - var ctorArgs = new TsObject[args.Length - 1]; + ctorArgs = new TsObject[args.Length - 1]; Array.Copy(args, 1, ctorArgs, 0, args.Length - 1); - inst = new TsInstance((string)args[0], ctorArgs); } - else - inst = new TsInstance((string)args[0]); - return new TsObject(inst); + if (WrappedConstructors.TryGetValue(type, out var ctor)) + return new TsObject(ctor(ctorArgs)); + else + return new TsInstance(type, ctorArgs); } /// @@ -454,7 +444,10 @@ public static void VariableGlobalSet(string name, TsObject value) /// public static bool VariableInstanceExists(ITsInstance inst, string name) { - throw new NotImplementedException(); + if (inst is TsInstance ts) + return ts._vars.ContainsKey(name); + else + throw new NotImplementedException("Currently imported types don't support determining if a variable exists."); } /// @@ -465,7 +458,7 @@ public static bool VariableInstanceExists(ITsInstance inst, string name) /// public static TsObject VariableInstanceGet(ITsInstance inst, string name) { - throw new NotImplementedException(); + return inst.GetMember(name); } /// @@ -475,13 +468,19 @@ public static TsObject VariableInstanceGet(ITsInstance inst, string name) /// public static TsObject[] VariableInstanceGetNames(ITsInstance inst) { - throw new NotImplementedException(); - /*var arr = new TsObject[inst._vars.Count]; - var i = 0; - foreach (var key in inst._vars.Keys) - arr[i++] = key; + if(inst is TsInstance ts) + { + var arr = new TsObject[ts._vars.Count]; + var i = 0; + foreach (var key in ts._vars.Keys) + arr[i++] = key; - return arr;*/ + return arr; + } + else + { + throw new NotImplementedException("Currenyly imported types don't support getting the names of variables."); + } } /// @@ -492,8 +491,7 @@ public static TsObject[] VariableInstanceGetNames(ITsInstance inst) /// The value to set public static void VariableInstanceSet(ITsInstance inst, string name, TsObject value) { - throw new NotImplementedException(); - //inst._vars[name] = value; + inst.SetMember(name, value); } private static TsInstance InitGlobal() diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index a998759..2e1c120 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -3774,8 +3774,32 @@ public void Visit(ImportObjectNode importNode) _errors.Add(new CompileException($"Could not import the type {importType.Name}. Imported types must be concrete and currently must be a class.")); var ns = GetAssetNamespace(leaf); + var name = $"{ns}.{importNode.ImportName.Value}".TrimStart('.'); + if(typeof(ITsInstance).IsAssignableFrom(importType)) { + var ctor = importType.GetConstructor(new[] { typeof(TsObject[]) }); + if(ctor is null) + { + LogError(new CompileException($"Could not import type that inherits from ITsInstance because it does not have a valid constructor: {importNode.Position}"), false); + return; + } + + leaf.Constructor = ctor; + var bt = GetBaseType(ns); + var wrappedCtor = bt.DefineMethod($"New_0{importNode.ImportName.Value}", MethodAttributes.Public | MethodAttributes.Static, typeof(ITsInstance), new[] { typeof(TsObject[]) }); + var wctr = new ILEmitter(wrappedCtor, new[] { typeof(TsObject[]) }); + wctr.LdArg(0) + .New(ctor) + .Ret(); + + Initializer.Call(typeof(TsInstance).GetMethod("get_WrappedConstructors")) + .LdStr(name) + .LdNull() + .LdFtn(wrappedCtor) + .New(typeof(Func).GetConstructor(new[] { typeof(object), typeof(IntPtr) })) + .Call(typeof(Dictionary>).GetMethod("Add", new[] { typeof(string), typeof(Func) })); + SpecialImports.Write((byte)ImportType.Object); SpecialImports.Write(':'); SpecialImports.Write(ns); @@ -3786,7 +3810,6 @@ public void Visit(ImportObjectNode importNode) return; } - var name = $"{ns}.{importNode.ImportName.Value}".TrimStart('.'); var type = _module.DefineType(name, TypeAttributes.Public, importNode.WeaklyTyped ? typeof(ObjectWrapper) : typeof(Object), new[] { typeof(ITsInstance) }); var source = type.DefineField("_source", importType, FieldAttributes.Private); @@ -4388,6 +4411,20 @@ private void AddConstructorToTypeWrapper(ConstructorInfo ctor, TypeBuilder type, emit.Ret(); leaf.Constructor = createMethod; + + var wrappedCtor = type.DefineMethod("Create", MethodAttributes.Public | MethodAttributes.Static, type, new[] { typeof(TsObject[]) }); + var wctr = new ILEmitter(wrappedCtor, new[] { typeof(TsObject[]) }); + + wctr.LdArg(0) + .New(createMethod, 1) + .Ret(); + + Initializer.Call(typeof(TsInstance).GetMethod("get_WrappedConstructors")) + .LdStr(type.FullName) + .LdNull() + .LdFtn(wrappedCtor) + .New(typeof(Func).GetConstructor(new[] { typeof(object), typeof(IntPtr) })) + .Call(typeof(Dictionary>).GetMethod("Add", new[] { typeof(string), typeof(Func) })); } private bool IsMethodSupported(MethodInfo method) @@ -4419,4 +4456,4 @@ private bool AreMethodParametersSupported(ParameterInfo[] parameters) #endregion } -} +} \ No newline at end of file diff --git a/TaffyScriptCompiler/Backend/ILEmitter.cs b/TaffyScriptCompiler/Backend/ILEmitter.cs index 7ac219e..efc2a1e 100644 --- a/TaffyScriptCompiler/Backend/ILEmitter.cs +++ b/TaffyScriptCompiler/Backend/ILEmitter.cs @@ -675,6 +675,17 @@ public ILEmitter New(ConstructorInfo info) return this; } + public ILEmitter New(ConstructorInfo info, int args) + { + for (var i = 0; i < args; i++) + _types.Pop(); + + _generator.Emit(OpCodes.Newobj, info); + + _types.Push(info.DeclaringType); + return this; + } + public ILEmitter NewArr(Type elementType) { _types.Pop(); From 2701c9543dccd1edc1b5716a57d45c5a60604bfd Mon Sep 17 00:00:00 2001 From: mystborn Date: Tue, 8 May 2018 16:57:36 -0700 Subject: [PATCH 21/54] Lambda Support --- Samples/TestSuite/Tests/build.cfg | 2 +- Samples/TestSuite/Tests/lambda.tfs | 54 +++++ Samples/TestSuite/Tests/tests.tfs | 2 + TaffyScriptCompiler/Backend/Closure.cs | 24 +++ .../Backend/Compiler/MsilWeakCodeGen.cs | 186 +++++++++++++++--- TaffyScriptCompiler/Front End/Parser.cs | 20 +- TaffyScriptCompiler/Program.cs | 2 + TaffyScriptCompiler/Symbols/SymbolTable.cs | 5 +- TaffyScriptCompiler/Symbols/VariableLeaf.cs | 18 ++ .../Syntax/Concrete/LambdaNode.cs | 41 ++++ .../Syntax/ISyntaxElementVisitor.cs | 1 + .../Syntax/SyntaxElementFactory.cs | 2 + TaffyScriptCompiler/Syntax/SyntaxType.cs | 1 + .../TaffyScriptCompiler.csproj | 3 + 14 files changed, 336 insertions(+), 25 deletions(-) create mode 100644 Samples/TestSuite/Tests/lambda.tfs create mode 100644 TaffyScriptCompiler/Backend/Closure.cs create mode 100644 TaffyScriptCompiler/Symbols/VariableLeaf.cs create mode 100644 TaffyScriptCompiler/Syntax/Concrete/LambdaNode.cs diff --git a/Samples/TestSuite/Tests/build.cfg b/Samples/TestSuite/Tests/build.cfg index 8ba3185..4f26f97 100644 --- a/Samples/TestSuite/Tests/build.cfg +++ b/Samples/TestSuite/Tests/build.cfg @@ -8,7 +8,7 @@ struct.tfs - + LanguageTests.main Debug diff --git a/Samples/TestSuite/Tests/lambda.tfs b/Samples/TestSuite/Tests/lambda.tfs new file mode 100644 index 0000000..5f6309c --- /dev/null +++ b/Samples/TestSuite/Tests/lambda.tfs @@ -0,0 +1,54 @@ +// Lambdas aren't implemented yet; +// This file shows a potential implementation. +// Currently it's excluded from the build. + +using UnitTest; + +namespace LanguageTests { + script run_lambda_tests() { + var tests = new obj_unit_test("Lambda Tests", + lambda_no_capture, + lambda_capture_local, + lambda_capture_argument, + lambda_capture_default_argument); + + tests.run_tests(); + } + + script lambda_no_capture() { + test_it("lambda { no_capture }"); + var i = script { + return 1 + } + var result = i(); + assert_equal(result, 1); + } + + script lambda_capture_local() { + test_it("lambda { local_capture }"); + var i = 1; + var s = script { + return i; + } + var result = s(); + assert_equal(result, 1); + } + + script lambda_capture_argument() { + test_it("lambda { arg_capture }"); + var s = scr_get_arg_capture_script(1); + var result = s(); + assert_equal(result, 1); + } + + script lambda_capture_default_argument() { + test_it("lambda { arg_default_capture }"); + var s = scr_get_arg_capture_script(); + var result = s(); + assert_equal(result, 2); + } + + script scr_get_arg_capture_script(arg = 2) { + return script { return arg; } + } +} \ No newline at end of file diff --git a/Samples/TestSuite/Tests/tests.tfs b/Samples/TestSuite/Tests/tests.tfs index 991791d..4bf7424 100644 --- a/Samples/TestSuite/Tests/tests.tfs +++ b/Samples/TestSuite/Tests/tests.tfs @@ -28,5 +28,7 @@ namespace LanguageTests { show_debug_message(""); run_with_tests(); show_debug_message(""); + run_lambda_tests(); + show_debug_message(""); } } \ No newline at end of file diff --git a/TaffyScriptCompiler/Backend/Closure.cs b/TaffyScriptCompiler/Backend/Closure.cs new file mode 100644 index 0000000..e41fd96 --- /dev/null +++ b/TaffyScriptCompiler/Backend/Closure.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Reflection; +using System.Reflection.Emit; + +namespace TaffyScriptCompiler.Backend +{ + public class Closure + { + public TypeBuilder Type { get; } + public ConstructorBuilder Constructor { get; set; } + public Dictionary Fields { get; set; } = new Dictionary(); + public LocalBuilder Self { get; set; } = null; + + public Closure(TypeBuilder type, ConstructorBuilder ctor) + { + Type = type; + Constructor = ctor; + } + } +} diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index 2e1c120..23e6032 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -152,6 +152,10 @@ internal partial class MsilWeakCodeGen : ISyntaxElementVisitor private LocalBuilder _argumentCount = null; + private Closure _closure = null; + private int _closures = 0; + private int _argOffset = 0; + #endregion #region Properties @@ -840,7 +844,18 @@ private void ScriptStart(string scriptName, MethodBuilder method, Type[] args) { //Raise local variables up one level. _table.AddChild(local); - _locals.Add(local, emit.DeclareLocal(typeof(TsObject), local.Name)); + + if (local is VariableLeaf leaf && leaf.IsCaptured) + { + if (_closure == null) + GetClosure(true); + var field = _closure.Type.DefineField(local.Name, typeof(TsObject), FieldAttributes.Public); + _closure.Fields.Add(local.Name, field); + } + else + { + _locals.Add(local, emit.DeclareLocal(typeof(TsObject), local.Name)); + } } } @@ -852,6 +867,47 @@ private void ScriptEnd() _secrets.Clear(); _secret = 0; _argumentCount = null; + if(_closure != null) + { + _closure.Type.CreateType(); + _closure = null; + } + } + + private Closure GetClosure(bool setLocal) + { + if(_closure == null) + { + var bt = GetBaseType(_namespace); + var type = bt.DefineNestedType($"<>{emit.Method.Name}_Display", TypeAttributes.NestedAssembly | TypeAttributes.AnsiClass | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit); + var constructor = type.DefineConstructor(MethodAttributes.Public | + MethodAttributes.HideBySig | + MethodAttributes.SpecialName | + MethodAttributes.RTSpecialName, + CallingConventions.HasThis, + Type.EmptyTypes); + var temp = emit; + + emit = new ILEmitter(constructor, new[] { typeof(object) }); + emit.LdArg(0) + .CallBase(typeof(object).GetConstructor(Type.EmptyTypes)) + .Ret(); + + emit = temp; + + _closure = new Closure(type, constructor); + + if (setLocal) + { + var local = emit.DeclareLocal(type, "__0closure"); + emit.New(constructor, 0) + .StLocal(local); + + _closure.Self = local; + } + } + + return _closure; } private LocalBuilder GetLocal() => GetLocal(typeof(TsObject)); @@ -1140,7 +1196,7 @@ public void Visit(AdditiveNode additive) public void Visit(ArgumentAccessNode argumentAccess) { - emit.LdArg(1); + emit.LdArg(1 + _argOffset); if (argumentAccess.Index is IConstantToken index) { emit.LdInt((int)index.Value); @@ -1406,16 +1462,24 @@ public void Visit(AssignNode assign) //If not, then it MUST be a member var. if (_table.Defined(variable.Text, out var symbol)) { - if (symbol.Type != SymbolType.Variable) + var leaf = symbol as VariableLeaf; + if(leaf is null) _errors.Add(new CompileException($"Cannot assign to the value {symbol.Name} {variable.Position}")); + + if(leaf.IsCaptured) + emit.LdLocal(_closure.Self); assign.Right.Accept(this); ConvertTopToObject(); - emit.StLocal(_locals[symbol]); + + if(leaf.IsCaptured) + emit.StFld(_closure.Fields[leaf.Name]); + else + emit.StLocal(_locals[symbol]); } else { - emit.LdArg(0) + emit.LdArg(0 + _argOffset) .LdStr(variable.Text); assign.Right.Accept(this); ConvertTopToObject(); @@ -1434,7 +1498,7 @@ public void Visit(AssignNode assign) emit.LdFld(typeof(TsInstance).GetField("Global")); break; case "self": - emit.LdArg(0); + emit.LdArg(0 + _argOffset); break; case "other": emit.Call(typeof(TsInstance).GetMethod("get_Other")); @@ -1738,9 +1802,9 @@ private void ProcessAssignExtra(AssignNode assign) private void SelfAccessSet(VariableToken variable) { - emit.LdArg(0) + emit.LdArg(0 + _argOffset) .LdStr(variable.Text) - .LdArg(0) + .LdArg(0 + _argOffset) .LdStr(variable.Text); } @@ -2167,7 +2231,7 @@ public void Visit(FunctionCallNode functionCall) MarkSequencePoint(functionCall); //Load the target - emit.LdArg(0); + emit.LdArg(0 + _argOffset); LoadFunctionArguments(functionCall); @@ -2208,7 +2272,7 @@ private void CallEvent(string name, bool loadId, FunctionCallNode functionCall, MarkSequencePoint(functionCall); if (loadId) - emit.LdArg(0); + emit.LdArg(0 + _argOffset); var top = emit.GetTop(); @@ -2370,6 +2434,37 @@ private bool TryLoadElementAsInt(ISyntaxElement element) return true; } + public void Visit(LambdaNode lambda) + { + var bt = GetBaseType(_namespace); + var owner = GetClosure(false); + var closure = owner.Type.DefineMethod($"<{emit.Method.Name}>closure_{lambda.Scope.Remove(0, 5)}", + MethodAttributes.Assembly | MethodAttributes.HideBySig, + typeof(TsObject), + ScriptArgs); + var temp = emit; + + emit = new ILEmitter(closure, ScriptArgs); + _table.Enter(lambda.Scope); + ++_closures; + _argOffset = 1; + lambda.Body.Accept(this); + --_closures; + _argOffset = _closures > 0 ? 1 : 0; + _table.Exit(); + emit = temp; + if (owner.Self == null) + emit.New(owner.Constructor, 0); + else + emit.LdLocal(owner.Self); + + emit.LdFtn(closure) + .New(typeof(TsScript).GetConstructor(new[] { typeof(object), typeof(IntPtr) })) + .LdStr("lambda") + .LdArg(0) + .New(typeof(TsDelegate).GetConstructor(new[] { typeof(TsScript), typeof(string), typeof(ITsInstance) })); + } + public void Visit(LocalsNode localsNode) { foreach (var child in localsNode.Children) @@ -2469,7 +2564,7 @@ public void Visit(MemberAccessNode memberAccess) emit.LdFld(typeof(TsInstance).GetField("Global")); break; case "self": - emit.LdArg(0); + emit.LdArg(0 + _argOffset); break; case "other": emit.Call(typeof(TsInstance).GetMethod("get_Other")); @@ -3009,7 +3104,7 @@ private Func GetReadOnlyLoadFunc(ReadOnlyToken read) else if (read.Text == "other") return () => emit.Call(typeof(TsInstance).GetMethod("get_Other")); else - return () => emit.LdArg(0); + return () => emit.LdArg(0 + _argOffset); } public void Visit(PrefixNode prefix) @@ -3270,7 +3365,7 @@ public void Visit(ReadOnlyToken readOnlyToken) switch(readOnlyToken.Text) { case "self": - emit.LdArg(0); + emit.LdArg(0 + _argOffset); break; case "other": emit.Call(typeof(TsInstance).GetMethod("get_Other")); @@ -3281,7 +3376,7 @@ public void Visit(ReadOnlyToken readOnlyToken) _argumentCount = emit.DeclareLocal(typeof(float), "argument_count"); var isNull = emit.DefineLabel(); var end = emit.DefineLabel(); - emit.LdArg(1) + emit.LdArg(1 + _argOffset) .Dup() .BrFalse(isNull) .LdLen() @@ -3479,9 +3574,11 @@ public void Visit(ScriptNode script) private void ProcessScriptArguments(ScriptNode script) { + //Todo: make this loop better for captured variables. + if (script.Arguments.Count > 0) { - emit.LdArg(1); + emit.LdArg(1 + _argOffset); for (var i = 0; i < script.Arguments.Count; i++) { var arg = script.Arguments[i]; @@ -3494,6 +3591,8 @@ private void ProcessScriptArguments(ScriptNode script) _errors.Add(new CompileException($"Unknown exception occurred {left.Position}")); continue; } + var leaf = symbol as VariableLeaf; + var lte = emit.DefineLabel(); var end = emit.DefineLabel(); emit.Dup() @@ -3505,16 +3604,45 @@ private void ProcessScriptArguments(ScriptNode script) .Ble(lte) .Dup() .LdInt(i) - .LdElem(typeof(TsObject)) - .StLocal(_locals[symbol]) - .Br(end) + .LdElem(typeof(TsObject)); + + if (leaf.IsCaptured) + { + var secret = GetLocal(); + emit.StLocal(secret); + if (_closures == 0) + emit.LdLocal(_closure.Self); + else + emit.LdArg(0); + emit.LdLocal(secret) + .StFld(_closure.Fields[leaf.Name]); + + FreeLocal(secret); + } + else + emit.StLocal(_locals[symbol]); + + emit.Br(end) .MarkLabel(lte); //Must be ConstantToken + + if (leaf.IsCaptured) + { + if (_closures == 0) + emit.LdLocal(_closure.Self); + else + emit.LdArg(0); + } + assign.Right.Accept(this); ConvertTopToObject(); - emit.StLocal(_locals[symbol]) - .MarkLabel(end); + if (leaf.IsCaptured) + emit.StFld(_closure.Fields[leaf.Name]); + else + emit.StLocal(_locals[symbol]); + + emit.MarkLabel(end); } else if (arg is VariableToken variable) { @@ -3699,6 +3827,20 @@ public void Visit(VariableToken variableToken) else emit.LdLocal(local); } + else if(symbol is VariableLeaf leaf && leaf.IsCaptured) + { + var field = _closure.Fields[symbol.Name]; + + if (_closures == 0) + emit.LdLocal(_closure.Self); + else + emit.LdArg(0); + + if (_needAddress) + emit.LdFldA(field); + else + emit.LdFld(field); + } else _errors.Add(new CompileException($"Tried to reference a non-existant variable {variableToken.Text} {variableToken.Position}")); break; @@ -3709,7 +3851,7 @@ public void Visit(VariableToken variableToken) } else { - emit.LdArg(0) + emit.LdArg(0 + _argOffset) .LdStr(variableToken.Text) .Call(typeof(ITsInstance).GetMethod("get_Item")); } @@ -3746,7 +3888,7 @@ public void Visit(WithNode with) emit.Call(get) .StLocal(other) - .LdArg(0) + .LdArg(0 + _argOffset) .Call(set) .StArg(0); diff --git a/TaffyScriptCompiler/Front End/Parser.cs b/TaffyScriptCompiler/Front End/Parser.cs index 76872ec..ed19865 100644 --- a/TaffyScriptCompiler/Front End/Parser.cs +++ b/TaffyScriptCompiler/Front End/Parser.cs @@ -31,6 +31,7 @@ private static HashSet HexCharacters private Tokenizer _stream; private SymbolTable _table; private ISyntaxElementFactory _factory; + private int lambdaId = 0; /// /// Flag used to determine whether = should mean assignment or equality. @@ -685,10 +686,27 @@ private ISyntaxElement BodyStatement() private ISyntaxElement Expression() { - var value = AssignmentExpression(); + var value = LambdaExpression(); return value; } + private ISyntaxElement LambdaExpression() + { + if(Try(TokenType.Script, out var token)) + { + var lambda = new LambdaNode(null, token.Position); + var scope = $"lambda{lambdaId++}"; + _table.EnterNew(scope, SymbolType.Script, SymbolScope.Local); + lambda.Scope = scope; + lambda.AddChild(BlockStatement()); + _table.Exit(); + lambda.MarkVariablesAsCaptured(_table); + return lambda; + } + + return AssignmentExpression(); + } + private ISyntaxElement AssignmentExpression() { // This is used to determine what = means. diff --git a/TaffyScriptCompiler/Program.cs b/TaffyScriptCompiler/Program.cs index 1eed878..35d5367 100644 --- a/TaffyScriptCompiler/Program.cs +++ b/TaffyScriptCompiler/Program.cs @@ -26,6 +26,8 @@ static void Main(string[] args) if (extra.Count != 0) path = extra[0]; + //path = @"C:\Users\Chris\Source\Repos\GmParser\Samples\TestSuite\Tests"; + if (generateBuild) { var build = new BuildConfig(); diff --git a/TaffyScriptCompiler/Symbols/SymbolTable.cs b/TaffyScriptCompiler/Symbols/SymbolTable.cs index 95eda0f..c5c2828 100644 --- a/TaffyScriptCompiler/Symbols/SymbolTable.cs +++ b/TaffyScriptCompiler/Symbols/SymbolTable.cs @@ -152,7 +152,10 @@ public bool AddLeaf(string name, SymbolType type, SymbolScope scope) { if(!Defined(name, out var overwrite)) { - Current.Children.Add(name, new SymbolLeaf(Current, name, type, scope)); + if (type == SymbolType.Variable) + Current.Children.Add(name, new VariableLeaf(Current, name, scope)); + else + Current.Children.Add(name, new SymbolLeaf(Current, name, type, scope)); return true; } return false; diff --git a/TaffyScriptCompiler/Symbols/VariableLeaf.cs b/TaffyScriptCompiler/Symbols/VariableLeaf.cs new file mode 100644 index 0000000..cb26f27 --- /dev/null +++ b/TaffyScriptCompiler/Symbols/VariableLeaf.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScriptCompiler +{ + public class VariableLeaf : SymbolLeaf + { + public bool IsCaptured { get; set; } = false; + + public VariableLeaf(SymbolNode parent, string name, SymbolScope scope) + : base(parent, name, SymbolType.Variable, scope) + { + } + } +} diff --git a/TaffyScriptCompiler/Syntax/Concrete/LambdaNode.cs b/TaffyScriptCompiler/Syntax/Concrete/LambdaNode.cs new file mode 100644 index 0000000..15cce26 --- /dev/null +++ b/TaffyScriptCompiler/Syntax/Concrete/LambdaNode.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace TaffyScriptCompiler.Syntax +{ + public class LambdaNode : SyntaxNode + { + public override SyntaxType Type => SyntaxType.Lambda; + public ISyntaxElement Body => Children[0]; + public string Scope { get; set; } + + public LambdaNode(string value, TokenPosition position) + : base(value, position) + { + } + + public override void Accept(ISyntaxElementVisitor visitor) + { + visitor.Visit(this); + } + + public void MarkVariablesAsCaptured(SymbolTable table) + { + MarkVariablesAsCaptured((BlockNode)Body, table); + } + + private void MarkVariablesAsCaptured(ISyntaxNode node, SymbolTable table) + { + foreach(var child in node.Children) + { + if (child is VariableToken variable && table.Defined(variable.Text, out var symbol) && symbol is VariableLeaf leaf) + { + leaf.IsCaptured = true; + } + else if (child is ISyntaxNode sn) + MarkVariablesAsCaptured(sn, table); + } + } + } +} diff --git a/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs b/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs index d90832d..5051564 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs +++ b/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs @@ -16,6 +16,7 @@ public interface ISyntaxElementVisitor void Visit(NamespaceNode namespaceNode); void Visit(ImportObjectNode importObjectNode); void Visit(WithNode withNode); + void Visit(LambdaNode lambdaNode); void Visit(ObjectNode objectNode); void Visit(ContinueToken continueToken); void Visit(UsingsNode usingsNode); diff --git a/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs b/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs index 3c2907b..3b9adf6 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs +++ b/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs @@ -80,6 +80,8 @@ public ISyntaxNode CreateNode(SyntaxType type, TokenPosition position) return new ArrayLiteralNode(null, position); case SyntaxType.FunctionCall: return new FunctionCallNode(null, position); + case SyntaxType.Lambda: + return new LambdaNode(null, position); default: throw new InvalidOperationException(); } diff --git a/TaffyScriptCompiler/Syntax/SyntaxType.cs b/TaffyScriptCompiler/Syntax/SyntaxType.cs index 5ef7139..5e4fcd9 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxType.cs +++ b/TaffyScriptCompiler/Syntax/SyntaxType.cs @@ -47,6 +47,7 @@ public enum SyntaxType Namespace, New, ImportObject, + Lambda, //Token Constant, diff --git a/TaffyScriptCompiler/TaffyScriptCompiler.csproj b/TaffyScriptCompiler/TaffyScriptCompiler.csproj index 291be69..c90f73b 100644 --- a/TaffyScriptCompiler/TaffyScriptCompiler.csproj +++ b/TaffyScriptCompiler/TaffyScriptCompiler.csproj @@ -64,6 +64,7 @@ + @@ -94,6 +95,7 @@ + @@ -121,6 +123,7 @@ + From 6d0d042eac6d197801878b9ddcc33839dd5e9dad Mon Sep 17 00:00:00 2001 From: mystborn Date: Fri, 11 May 2018 14:15:01 -0700 Subject: [PATCH 22/54] Removed Unnecessary Collections --- TaffyScript/Collections/Binder.cs | 294 ---------------------------- TaffyScript/Collections/FastList.cs | 141 ------------- TaffyScript/TaffyScript.csproj | 2 - 3 files changed, 437 deletions(-) delete mode 100644 TaffyScript/Collections/Binder.cs delete mode 100644 TaffyScript/Collections/FastList.cs diff --git a/TaffyScript/Collections/Binder.cs b/TaffyScript/Collections/Binder.cs deleted file mode 100644 index 126b648..0000000 --- a/TaffyScript/Collections/Binder.cs +++ /dev/null @@ -1,294 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace TaffyScript.Collections -{ - /// - /// Binds objects to an index. - /// - /// - public interface IBinder - { - /// - /// Gets the item at the specified index. - /// - /// The index of the item. - /// Item - T this[int index] { get; } - - /// - /// Gets the number of bound items. - /// - int Count { get; } - - /// - /// Adds an item to the binder, returning it's index. - /// - /// The item to add. - /// Item index. - int Add(T item); - - /// - /// Determines if the Binder contains an item with the specified index. - /// - /// The index of the item. - /// True if the item was found; otherwise false. - bool Contains(int index); - - /// - /// Removes the item at the specified index. - /// - /// The index of the item. - void Remove(int index); - - /// - /// Attempts to get the item at the specified index. - /// - /// The index of the item. - /// The item, if found. - /// True if the item was found; otherwise false. - bool TryGetValue(int index, out T value); - - - /// - /// Returns an enumerator used to enumerate through all of the bound items. - /// - /// - IEnumerator GetEnumerator(); - } - - /// - /// Binds heap allocated objects to an index. - /// - /// - public class ClassBinder : IBinder where T : class - { - private T[] _binder = new T[10]; - private int _count = 0; - private readonly Stack _openSlots = new Stack(); - - /// - /// Gets the item at the specified index. - /// - /// The index of the item. - /// Item - public T this[int index] - { - get => _binder[index]; - } - - /// - /// Gets the number of bound items. - /// - public int Count => _count; - - /// - /// Adds an item to the binder, returning its index. - /// - /// The item to add. - /// Item index - public int Add(T item) - { - int index; - if (_openSlots.Count == 0) - { - if (_count == _binder.Length) - { - var temp = new T[_count * 2]; - Array.Copy(_binder, temp, _count); - _binder = temp; - } - index = _count; - } - else - index = _openSlots.Pop(); - - ++_count; - _binder[index] = item; - return index; - } - - /// - /// Determines if the Binder contains an item with the specified index. - /// - /// The index of the item. - /// True if the item was found; otherwise false. - public bool Contains(int index) - { - return index >= 0 && index < _count && _binder[index] != null; - } - - /// - /// Returns an enumerator used to enumerate through all of the bound items. - /// - /// - public IEnumerator GetEnumerator() - { - for(var i = 0; i < _count; i++) - { - if (_binder[i] != null) - yield return _binder[i]; - } - } - - /// - /// Removes the item at the specified index. - /// - /// The index of the item. - public void Remove(int index) - { - // Originally did a bounds check, but currently - // I've decided to let the Array implementation control that. - // if (index < 0 || index >= _binder.Length) - // throw new ArgumentOutOfRangeException(nameof(index)); - _binder[index] = null; - - //The application will throw before this operation - //so it's safe to push any index that's made it this far. - --_count; - _openSlots.Push(index); - } - - /// - /// Attempts to get the item at the specified index. - /// - /// The index of the item. - /// The item, if found. - /// True if the item was found; otherwise false. - public bool TryGetValue(int index, out T value) - { - value = null; - if (index < 0 || index >= _count) - return false; - value = _binder[index]; - if (value == null) - return false; - return true; - } - } - - /// - /// Binds stack allocated objects to an index. Requires a default value. - /// - /// - public class StructBinder : IBinder where T : struct - { - private T[] _binder = new T[10]; - private readonly Stack _openSlots = new Stack(); - private int _count = 0; - - /// - /// Gets the item at the specified index. - /// - /// The index of the item. - /// Item - public T this[int index] => _binder[index]; - - /// - /// Gets the number of bound items. - /// - public int Count => _count; - - /// - /// Gets the default value of this binder. - /// - public T Default { get; } - - /// - /// Creates a new StructBinder with default(T) as the default value. - /// - public StructBinder() - { - Default = default(T); - } - - /// - /// Creates a new StructBinder with the specified default value. - /// - /// - public StructBinder(T defaultValue) - { - Default = defaultValue; - } - - /// - /// Adds an item to the binder, returning it's index. - /// - /// The item to add. - /// Item index. - public int Add(T item) - { - int index; - if (_openSlots.Count == 0) - { - if (_count == _binder.Length) - { - var temp = new T[_count * 2]; - Array.Copy(_binder, temp, _count); - _binder = temp; - } - index = _count; - } - else - index = _openSlots.Pop(); - - ++_count; - return index; - } - - /// - /// Determines if the Binder contains an item with the specified index. - /// - /// The index of the item. - /// True if the item was found; otherwise false. - public bool Contains(int index) - { - return index >= 0 && index < _count && !_binder[index].Equals(Default); - } - - /// - /// Returns an enumerator used to enumerate through all of the bound items. - /// - /// - public IEnumerator GetEnumerator() - { - for(var i = 0; i < _count; i++) - { - if (!_binder[i].Equals(Default)) - yield return _binder[i]; - } - } - - /// - /// Removes the item at the specified index. - /// - /// The index of the item. - public void Remove(int index) - { - _binder[index] = Default; - - --_count; - _openSlots.Push(index); - } - - /// - /// Attempts to get the item at the specified index. - /// - /// The index of the item. - /// The item, if found. - /// True if the item was found; otherwise false. - public bool TryGetValue(int index, out T value) - { - value = Default; - if (index < 0 || index >= _count) - return false; - value = _binder[index]; - if (value.Equals(Default)) - return false; - return true; - } - } -} diff --git a/TaffyScript/Collections/FastList.cs b/TaffyScript/Collections/FastList.cs deleted file mode 100644 index e1a28c0..0000000 --- a/TaffyScript/Collections/FastList.cs +++ /dev/null @@ -1,141 +0,0 @@ -//Inspired by the FastList class found in Nez. -//Source: https://github.com/prime31/Nez/blob/master/Nez.Portable/Utils/Collections/FastList.cs -//License: https://github.com/prime31/Nez/blob/master/LICENSE - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace TaffyScript.Collections -{ - /// - /// An unordered List with O(1) removal. - /// - /// - public class FastList : IEnumerable - { - //Use fields for performance in case property calls can't be jitted away. - - /// - /// The backing array. Use to access elements. - /// - public T[] Buffer; - - /// - /// The number of elements in the list. - /// - public int Count = 0; - - /// - /// Creates a new list with the default initial capacity. - /// - public FastList() : this(5) { } - - /// - /// Creates a new list with the specified initial capacity. - /// - /// - public FastList(int capacity) - { - Buffer = new T[capacity]; - } - - /// - /// Creates a list from a collection of items. - /// - /// - public FastList(IEnumerable items) - { - Buffer = items.ToArray(); - Count = Buffer.Length; - } - - /// - /// Clears all items from the list. - /// - public void Clear() - { - Array.Clear(Buffer, 0, Count); - Count = 0; - } - - /// - /// Resets the list size to 0, without removing any items. - /// - public void Reset() - { - Count = 0; - } - - /// - /// Adds an item to the list. - /// - /// - public void Add(T item) - { - if (Count == Buffer.Length) - Array.Resize(ref Buffer, Count << 1); - Buffer[Count++] = item; - } - - /// - /// Removes an item from the list. O(n) time. - /// - /// - public void Remove(T item) - { - var comp = EqualityComparer.Default; - for (var i = 0; i < Count; ++i) - { - if (comp.Equals(Buffer[i], item)) - { - RemoveAt(i); - return; - } - } - } - - /// - /// Removes the specified index from the list. O(1) time. - /// - /// - public void RemoveAt(int index) - { - Buffer[index] = Buffer[Count - 1]; - Buffer[--Count] = default(T); - } - - /// - /// Determines if the list contains the specified item. - /// - /// - /// - public bool Contains(T item) - { - var comp = EqualityComparer.Default; - for (var i = 0; i < Count; --i) - { - if (comp.Equals(Buffer[i], item)) - return true; - } - return false; - } - - /// - /// Gets an enumerator used to iterate through the list. - /// - /// - public IEnumerator GetEnumerator() - { - for (var i = 0; i < Count; i++) - yield return Buffer[i]; - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -} diff --git a/TaffyScript/TaffyScript.csproj b/TaffyScript/TaffyScript.csproj index df834a0..f67c010 100644 --- a/TaffyScript/TaffyScript.csproj +++ b/TaffyScript/TaffyScript.csproj @@ -46,8 +46,6 @@ - - From b74b868c0e3265f28829c75752eb6ba0e11353c1 Mon Sep 17 00:00:00 2001 From: mystborn Date: Sun, 13 May 2018 20:12:49 -0700 Subject: [PATCH 23/54] Fixed Lambda + Enum Bug --- .../Backend/Compiler/MsilWeakCodeGen.cs | 15 ++++++++++++--- TaffyScriptCompiler/Program.cs | 2 -- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index 23e6032..e7ca713 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -2448,10 +2448,18 @@ public void Visit(LambdaNode lambda) _table.Enter(lambda.Scope); ++_closures; _argOffset = 1; + lambda.Body.Accept(this); + //Todo: Don't do this if last node was return stmt. + if (!emit.TryGetTop(out _)) + emit.Call(TsTypes.Empty); + + emit.Ret(); + --_closures; _argOffset = _closures > 0 ? 1 : 0; _table.Exit(); + emit = temp; if (owner.Self == null) emit.New(owner.Constructor, 0); @@ -2534,15 +2542,16 @@ public void Visit(MemberAccessNode memberAccess) { if (!_enums.TryGetValue(enumVar.Text, enumValue.Text, out var value)) { - _table.Enter(enumVar.Text); - if (_table.Defined(enumValue.Text, out symbol) && symbol is EnumLeaf leaf) + var node = (SymbolNode)_table.Defined(enumVar.Text); + //_table.Enter(enumVar.Text); + if (node.Children.TryGetValue(enumValue.Text, out symbol) && symbol is EnumLeaf leaf) { value = leaf.Value; _enums[enumVar.Text, leaf.Name] = value; } else _errors.Add(new CompileException($"The enum {enumVar.Text} does not declare value {enumValue.Text} {enumValue.Position}")); - _table.Exit(); + //_table.Exit(); } emit.LdFloat(value); } diff --git a/TaffyScriptCompiler/Program.cs b/TaffyScriptCompiler/Program.cs index 35d5367..1eed878 100644 --- a/TaffyScriptCompiler/Program.cs +++ b/TaffyScriptCompiler/Program.cs @@ -26,8 +26,6 @@ static void Main(string[] args) if (extra.Count != 0) path = extra[0]; - //path = @"C:\Users\Chris\Source\Repos\GmParser\Samples\TestSuite\Tests"; - if (generateBuild) { var build = new BuildConfig(); From a8b657a7204d5dfabe08127f5102be7cd9bed3b4 Mon Sep 17 00:00:00 2001 From: mystborn Date: Mon, 14 May 2018 00:08:55 -0700 Subject: [PATCH 24/54] Fixed Event Scoping Bug --- .../Backend/Compiler/MsilWeakCodeGen.cs | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs index e7ca713..2e48c0c 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -3814,19 +3814,32 @@ public void Visit(VariableToken variableToken) emit.LdStr(name); break; case SymbolType.Script: - ns = GetAssetNamespace(symbol); - if (!_methods.TryGetValue(ns, name, out var method)) + if (symbol.Scope == SymbolScope.Member) { - method = StartMethod(name, ns); - _pendingMethods.Add($"{ns}.{name}".TrimStart('.'), variableToken.Position); + // Todo: Consider forcing this to load the exact function. + // That would make it so the function couldn't be changed during runtime, + // but of course it makes execution faster. + emit.LdArg(0 + _argOffset) + .LdStr(name) + .Call(typeof(ITsInstance).GetMethod("GetDelegate")) + .New(TsTypes.Constructors[typeof(TsDelegate)]); + } + else + { + ns = GetAssetNamespace(symbol); + if (!_methods.TryGetValue(ns, name, out var method)) + { + method = StartMethod(name, ns); + _pendingMethods.Add($"{ns}.{name}".TrimStart('.'), variableToken.Position); + } + UnresolveNamespace(); + emit.LdNull() + .LdFtn(method) + .New(typeof(TsScript).GetConstructor(new[] { typeof(object), typeof(IntPtr) })) + .LdStr(symbol.Name) + .New(typeof(TsDelegate).GetConstructor(new[] { typeof(TsScript), typeof(string) })) + .New(TsTypes.Constructors[typeof(TsDelegate)]); } - UnresolveNamespace(); - emit.LdNull() - .LdFtn(method) - .New(typeof(TsScript).GetConstructor(new[] { typeof(object), typeof(IntPtr) })) - .LdStr(symbol.Name) - .New(typeof(TsDelegate).GetConstructor(new[] { typeof(TsScript), typeof(string) })) - .New(TsTypes.Constructors[typeof(TsDelegate)]); break; case SymbolType.Variable: if (_locals.TryGetValue(symbol, out var local)) From 13c98872eae26284a6d2e9c41a8f5b4dc6039093 Mon Sep 17 00:00:00 2001 From: mystborn Date: Mon, 14 May 2018 00:14:35 -0700 Subject: [PATCH 25/54] Better PascalCase Conversion --- TaffyScriptCompiler/StringUtils.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/TaffyScriptCompiler/StringUtils.cs b/TaffyScriptCompiler/StringUtils.cs index d8f026c..96f29c4 100644 --- a/TaffyScriptCompiler/StringUtils.cs +++ b/TaffyScriptCompiler/StringUtils.cs @@ -19,14 +19,21 @@ public static string ConvertToCamelCase(string value) else sb.Append(char.ToUpper(split[i][0])); - sb.Append(split[0].Substring(1, split[0].Length - 1)); + sb.Append(split[i].Substring(1, split[i].Length - 1)); } return sb.ToString(); } public static string ConvertToPascalCase(string value) { - return value.Split(new[] { "_" }, StringSplitOptions.RemoveEmptyEntries).Select(s => char.ToUpper(s[0]) + s.Substring(1, s.Length - 1)).Aggregate(string.Empty, (s1, s2) => s1 + s2); + var sb = new StringBuilder(); + var split = value.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries); + for (var i = 0; i < split.Length; i++) + { + sb.Append(char.ToUpper(split[i][0])); + sb.Append(split[i].Substring(1, split[i].Length - 1)); + } + return sb.ToString(); } public static string ConvertToSnakeCase(string value) From 28a372f5f87dd084ba0b031298f8b3b38db80092 Mon Sep 17 00:00:00 2001 From: mystborn Date: Mon, 14 May 2018 00:42:54 -0700 Subject: [PATCH 26/54] Project Restructure Part 1 --- TaffyScript.CommandLine/App.config | 6 ++ TaffyScript.CommandLine/ErrorLogger.cs | 53 ++++++++++++++++ .../Program.cs | 7 ++- .../Properties/AssemblyInfo.cs | 36 +++++++++++ .../TaffyScript.CommandLine.csproj | 63 +++++++++++++++++++ TaffyScript.CommandLine/packages.config | 4 ++ .../App.config | 0 .../Backend/BaseClassLibrary.cs | 2 +- .../Backend/BaseClassLibrary.cs.bak | 0 .../Backend/BuildConfig.cs | 2 +- .../Backend/Builder.cs | 2 +- .../Backend/Closure.cs | 2 +- .../Backend/Compiler/CompileException.cs | 2 +- .../Backend/Compiler/CompileMode.cs | 2 +- .../Backend/Compiler/CompilerResult.cs | 2 +- .../Backend/Compiler/ICompiler.cs | 2 +- .../Backend/Compiler/MsilWeakCodeGen.cs | 6 +- .../Backend/Compiler/MsilWeakCodeGen.cs.bak | 0 .../Backend/Compiler/MsilWeakCompiler.cs | 2 +- .../Backend/ILEmitter.cs | 2 +- .../Backend/ILEmitter.cs.bak | 0 .../Backend/ImportType.cs | 2 +- .../Backend/NameConflictException.cs | 2 +- .../DotNet/AssemblyLoader.cs | 2 +- .../DotNet/TaffyScriptTypes.cs | 2 +- .../DotNet/TaffyScriptTypes.cs.bak | 0 .../DotNet/TypeParser.cs | 4 +- .../Front End/InvalidTokenException.cs | 4 +- .../Front End/LexicalAnalysis/Token.cs | 2 +- .../LexicalAnalysis/TokenPosition.cs | 2 +- .../Front End/LexicalAnalysis/TokenType.cs | 2 +- .../Front End/LexicalAnalysis/Tokenizer.cs | 2 +- .../UnrecognizedTokenException.cs | 2 +- .../Front End/Parser.cs | 7 ++- .../Front End/Parser.cs.bak | 0 TaffyScript.Compiler/IErrorLogger.cs | 16 +++++ .../Properties/AssemblyInfo.cs | 4 +- .../StringUtils.cs | 2 +- .../Symbols/EnumLeaf.cs | 2 +- .../Symbols/ISymbol.cs | 2 +- .../Symbols/ImportLeaf.cs | 4 +- .../Symbols/ImportObjectLeaf.cs | 4 +- .../Symbols/InvalidSymbolException.cs | 2 +- .../Symbols/SymbolLeaf.cs | 2 +- .../Symbols/SymbolNode.cs | 2 +- .../Symbols/SymbolScope.cs | 2 +- .../Symbols/SymbolTable.cs | 2 +- .../Symbols/SymbolType.cs | 2 +- .../Symbols/SymbolType.cs.bak | 0 .../Symbols/VariableLeaf.cs | 2 +- .../Syntax/Concrete/AdditiveNode.cs | 2 +- .../Syntax/Concrete/ArgumentAccess.cs | 2 +- .../Syntax/Concrete/ArrayAccess.cs | 2 +- .../Syntax/Concrete/ArrayLiteral.cs | 2 +- .../Syntax/Concrete/Assign.cs | 2 +- .../Syntax/Concrete/Bitwise.cs | 2 +- .../Syntax/Concrete/Block.cs | 2 +- .../Syntax/Concrete/BreakToken.cs | 2 +- .../Syntax/Concrete/Case.cs | 2 +- .../Syntax/Concrete/Conditional.cs | 2 +- .../Syntax/Concrete/ConstantToken.cs | 2 +- .../Syntax/Concrete/ContinueToken.cs | 2 +- .../Syntax/Concrete/Declare.cs | 2 +- .../Syntax/Concrete/Default.cs | 2 +- .../Syntax/Concrete/Do.cs | 2 +- .../Syntax/Concrete/EndToken.cs | 2 +- .../Syntax/Concrete/EnumDeclaration.cs | 2 +- .../Syntax/Concrete/Equality.cs | 2 +- .../Syntax/Concrete/ExitToken.cs | 2 +- .../Syntax/Concrete/For.cs | 2 +- .../Syntax/Concrete/FunctionCall.cs | 2 +- .../Syntax/Concrete/If.cs | 2 +- .../Syntax/Concrete/Import.cs | 2 +- .../Concrete/ImportObject/ImportCasing.cs | 2 +- .../Concrete/ImportObject/ImportObject.cs | 2 +- .../ImportObject/ImportObjectConstructor.cs | 2 +- .../ImportObject/ImportObjectField.cs | 2 +- .../ImportObject/ImportObjectMethod.cs | 2 +- .../Syntax/Concrete/LambdaNode.cs | 2 +- .../Syntax/Concrete/Locals.cs | 2 +- .../Syntax/Concrete/Logical.cs | 2 +- .../Syntax/Concrete/MemberAccess.cs | 2 +- .../Syntax/Concrete/Multiplicative.cs | 2 +- .../Syntax/Concrete/NamespaceNode.cs | 2 +- .../Syntax/Concrete/NewNode.cs | 2 +- .../Syntax/Concrete/NewNode.cs.bak | 0 .../Syntax/Concrete/ObjectNode.cs | 2 +- .../Syntax/Concrete/Postfix.cs | 2 +- .../Syntax/Concrete/Prefix.cs | 2 +- .../Syntax/Concrete/ReadOnlyToken.cs | 2 +- .../Syntax/Concrete/Relational.cs | 2 +- .../Syntax/Concrete/RepeatNode.cs | 2 +- .../Syntax/Concrete/Return.cs | 2 +- .../Syntax/Concrete/Root.cs | 2 +- .../Syntax/Concrete/Script.cs | 2 +- .../Syntax/Concrete/Script.cs.bak | 0 .../Syntax/Concrete/Shift.cs | 2 +- .../Syntax/Concrete/Switch.cs | 2 +- .../Syntax/Concrete/UsingsNode.cs | 2 +- .../Syntax/Concrete/VariableToken.cs | 2 +- .../Syntax/Concrete/While.cs | 2 +- .../Syntax/Concrete/WithNode.cs | 2 +- .../Syntax/ConstantType.cs | 2 +- .../Syntax/IConstantToken.cs | 2 +- .../Syntax/ISyntaxElement.cs | 4 +- .../Syntax/ISyntaxElementFactory.cs | 2 +- .../Syntax/ISyntaxElementVisitor.cs | 2 +- .../Syntax/ISyntaxElementVisitor.cs.bak | 0 .../Syntax/ISyntaxNode.cs | 2 +- .../Syntax/ISyntaxToken.cs | 2 +- .../Syntax/ISyntaxTree.cs | 2 +- .../Syntax/SyntaxElementFactory.cs | 2 +- .../Syntax/SyntaxElementFactory.cs.bak | 0 .../Syntax/SyntaxNode.cs | 2 +- .../Syntax/SyntaxToken.cs | 2 +- .../Syntax/SyntaxTree.cs | 2 +- .../Syntax/SyntaxType.cs | 2 +- .../Syntax/SyntaxType.cs.bak | 0 .../TaffyScript.Compiler.csproj | 11 ++-- .../packages.config | 0 TaffyScript.sln | 57 ++++++++++------- 121 files changed, 332 insertions(+), 140 deletions(-) create mode 100644 TaffyScript.CommandLine/App.config create mode 100644 TaffyScript.CommandLine/ErrorLogger.cs rename {TaffyScriptCompiler => TaffyScript.CommandLine}/Program.cs (95%) create mode 100644 TaffyScript.CommandLine/Properties/AssemblyInfo.cs create mode 100644 TaffyScript.CommandLine/TaffyScript.CommandLine.csproj create mode 100644 TaffyScript.CommandLine/packages.config rename {TaffyScriptCompiler => TaffyScript.Compiler}/App.config (100%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/BaseClassLibrary.cs (99%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/BaseClassLibrary.cs.bak (100%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/BuildConfig.cs (97%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/Builder.cs (99%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/Closure.cs (94%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/Compiler/CompileException.cs (87%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/Compiler/CompileMode.cs (83%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/Compiler/CompilerResult.cs (96%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/Compiler/ICompiler.cs (85%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/Compiler/MsilWeakCodeGen.cs (99%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/Compiler/MsilWeakCodeGen.cs.bak (100%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/Compiler/MsilWeakCompiler.cs (99%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/ILEmitter.cs (99%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/ILEmitter.cs.bak (100%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/ImportType.cs (83%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Backend/NameConflictException.cs (88%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/DotNet/AssemblyLoader.cs (98%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/DotNet/TaffyScriptTypes.cs (99%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/DotNet/TaffyScriptTypes.cs.bak (100%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/DotNet/TypeParser.cs (95%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Front End/InvalidTokenException.cs (94%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Front End/LexicalAnalysis/Token.cs (95%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Front End/LexicalAnalysis/TokenPosition.cs (97%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Front End/LexicalAnalysis/TokenType.cs (97%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Front End/LexicalAnalysis/Tokenizer.cs (99%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Front End/LexicalAnalysis/UnrecognizedTokenException.cs (97%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Front End/Parser.cs (99%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Front End/Parser.cs.bak (100%) create mode 100644 TaffyScript.Compiler/IErrorLogger.cs rename {TaffyScriptCompiler => TaffyScript.Compiler}/Properties/AssemblyInfo.cs (93%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/StringUtils.cs (97%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Symbols/EnumLeaf.cs (92%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Symbols/ISymbol.cs (85%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Symbols/ImportLeaf.cs (86%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Symbols/ImportObjectLeaf.cs (90%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Symbols/InvalidSymbolException.cs (93%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Symbols/SymbolLeaf.cs (95%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Symbols/SymbolNode.cs (97%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Symbols/SymbolScope.cs (87%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Symbols/SymbolTable.cs (99%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Symbols/SymbolType.cs (89%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Symbols/SymbolType.cs.bak (100%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Symbols/VariableLeaf.cs (92%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/AdditiveNode.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ArgumentAccess.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ArrayAccess.cs (95%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ArrayLiteral.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Assign.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Bitwise.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Block.cs (89%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/BreakToken.cs (89%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Case.cs (93%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Conditional.cs (92%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ConstantToken.cs (94%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ContinueToken.cs (89%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Declare.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Default.cs (90%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Do.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/EndToken.cs (89%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/EnumDeclaration.cs (89%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Equality.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ExitToken.cs (89%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/For.cs (93%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/FunctionCall.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/If.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Import.cs (95%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ImportObject/ImportCasing.cs (85%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ImportObject/ImportObject.cs (99%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ImportObject/ImportObjectConstructor.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ImportObject/ImportObjectField.cs (94%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ImportObject/ImportObjectMethod.cs (97%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/LambdaNode.cs (96%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Locals.cs (89%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Logical.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/MemberAccess.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Multiplicative.cs (92%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/NamespaceNode.cs (89%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/NewNode.cs (92%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/NewNode.cs.bak (100%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ObjectNode.cs (90%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Postfix.cs (90%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Prefix.cs (90%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/ReadOnlyToken.cs (89%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Relational.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/RepeatNode.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Return.cs (90%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Root.cs (92%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Script.cs (95%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Script.cs.bak (100%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Shift.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/Switch.cs (93%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/UsingsNode.cs (95%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/VariableToken.cs (89%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/While.cs (91%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/Concrete/WithNode.cs (92%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/ConstantType.cs (87%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/IConstantToken.cs (90%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/ISyntaxElement.cs (84%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/ISyntaxElementFactory.cs (93%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/ISyntaxElementVisitor.cs (98%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/ISyntaxElementVisitor.cs.bak (100%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/ISyntaxNode.cs (89%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/ISyntaxToken.cs (83%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/ISyntaxTree.cs (86%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/SyntaxElementFactory.cs (99%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/SyntaxElementFactory.cs.bak (100%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/SyntaxNode.cs (96%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/SyntaxToken.cs (97%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/SyntaxTree.cs (96%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/SyntaxType.cs (96%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/Syntax/SyntaxType.cs.bak (100%) rename TaffyScriptCompiler/TaffyScriptCompiler.csproj => TaffyScript.Compiler/TaffyScript.Compiler.csproj (97%) rename {TaffyScriptCompiler => TaffyScript.Compiler}/packages.config (100%) diff --git a/TaffyScript.CommandLine/App.config b/TaffyScript.CommandLine/App.config new file mode 100644 index 0000000..88fa402 --- /dev/null +++ b/TaffyScript.CommandLine/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TaffyScript.CommandLine/ErrorLogger.cs b/TaffyScript.CommandLine/ErrorLogger.cs new file mode 100644 index 0000000..8906493 --- /dev/null +++ b/TaffyScript.CommandLine/ErrorLogger.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TaffyScript.Compiler; + +namespace TaffyScript.CommandLine +{ + public class CommandLineLogger : IErrorLogger + { + public List Errors { get; } = new List(); + public List Warnings { get; } = new List(); + + public void Error(string message, TokenPosition position) + { + if(position != null) + { + var sb = new StringBuilder(message); + if(position.File != null) + { + sb.Append(" in file "); + sb.Append(position.File); + } + sb.Append(" at line "); + sb.Append(position.Line); + sb.Append(", column "); + sb.Append(position.Column); + message = sb.ToString(); + } + Errors.Add(message); + } + + public void Warning(string message, TokenPosition position) + { + if (position != null) + { + var sb = new StringBuilder(message); + if (position.File != null) + { + sb.Append(" in file "); + sb.Append(position.File); + } + sb.Append(" at line "); + sb.Append(position.Line); + sb.Append(", column "); + sb.Append(position.Column); + message = sb.ToString(); + } + Warnings.Add(message); + } + } +} diff --git a/TaffyScriptCompiler/Program.cs b/TaffyScript.CommandLine/Program.cs similarity index 95% rename from TaffyScriptCompiler/Program.cs rename to TaffyScript.CommandLine/Program.cs index 1eed878..d679125 100644 --- a/TaffyScriptCompiler/Program.cs +++ b/TaffyScript.CommandLine/Program.cs @@ -2,9 +2,10 @@ using System; using System.Diagnostics; using System.IO; -using TaffyScriptCompiler.Backend; +using TaffyScript.Compiler; +using TaffyScript.Compiler.Backend; -namespace TaffyScriptCompiler +namespace TaffyScript.CommandLine { class Program { @@ -76,7 +77,7 @@ private static void RunOutput(string location) UseShellExecute = false, }; - using(var process = new Process()) + using (var process = new Process()) { process.StartInfo = psi; process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data); diff --git a/TaffyScript.CommandLine/Properties/AssemblyInfo.cs b/TaffyScript.CommandLine/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8fc3bea --- /dev/null +++ b/TaffyScript.CommandLine/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TaffyScript.CommandLine")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TaffyScript.CommandLine")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ff4bc25b-646a-4849-bfc1-4731cec9d456")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/TaffyScript.CommandLine/TaffyScript.CommandLine.csproj b/TaffyScript.CommandLine/TaffyScript.CommandLine.csproj new file mode 100644 index 0000000..6e6dc00 --- /dev/null +++ b/TaffyScript.CommandLine/TaffyScript.CommandLine.csproj @@ -0,0 +1,63 @@ + + + + + Debug + AnyCPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456} + Exe + TaffyScript.CommandLine + tsc + v4.5.2 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\NDesk.Options.0.2.1\lib\NDesk.Options.dll + + + + + + + + + + + + + + + + + + + + + + {4022f406-fce6-4a8d-b99f-6ef6c406248a} + TaffyScript.Compiler + + + + \ No newline at end of file diff --git a/TaffyScript.CommandLine/packages.config b/TaffyScript.CommandLine/packages.config new file mode 100644 index 0000000..c4987fe --- /dev/null +++ b/TaffyScript.CommandLine/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/TaffyScriptCompiler/App.config b/TaffyScript.Compiler/App.config similarity index 100% rename from TaffyScriptCompiler/App.config rename to TaffyScript.Compiler/App.config diff --git a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs b/TaffyScript.Compiler/Backend/BaseClassLibrary.cs similarity index 99% rename from TaffyScriptCompiler/Backend/BaseClassLibrary.cs rename to TaffyScript.Compiler/Backend/BaseClassLibrary.cs index eac1f23..5ce5f82 100644 --- a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs +++ b/TaffyScript.Compiler/Backend/BaseClassLibrary.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { /// /// Helper class used to generate the BCL of TaffyScript. diff --git a/TaffyScriptCompiler/Backend/BaseClassLibrary.cs.bak b/TaffyScript.Compiler/Backend/BaseClassLibrary.cs.bak similarity index 100% rename from TaffyScriptCompiler/Backend/BaseClassLibrary.cs.bak rename to TaffyScript.Compiler/Backend/BaseClassLibrary.cs.bak diff --git a/TaffyScriptCompiler/Backend/BuildConfig.cs b/TaffyScript.Compiler/Backend/BuildConfig.cs similarity index 97% rename from TaffyScriptCompiler/Backend/BuildConfig.cs rename to TaffyScript.Compiler/Backend/BuildConfig.cs index a250849..1692e5b 100644 --- a/TaffyScriptCompiler/Backend/BuildConfig.cs +++ b/TaffyScript.Compiler/Backend/BuildConfig.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using System.Xml.Serialization; -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { [XmlRoot(ElementName = "Build")] public class BuildConfig diff --git a/TaffyScriptCompiler/Backend/Builder.cs b/TaffyScript.Compiler/Backend/Builder.cs similarity index 99% rename from TaffyScriptCompiler/Backend/Builder.cs rename to TaffyScript.Compiler/Backend/Builder.cs index 9d400f6..16f3b53 100644 --- a/TaffyScriptCompiler/Backend/Builder.cs +++ b/TaffyScript.Compiler/Backend/Builder.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using System.Xml.Serialization; -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { /// /// Base class for any TaffyScript project builder. diff --git a/TaffyScriptCompiler/Backend/Closure.cs b/TaffyScript.Compiler/Backend/Closure.cs similarity index 94% rename from TaffyScriptCompiler/Backend/Closure.cs rename to TaffyScript.Compiler/Backend/Closure.cs index e41fd96..5eaec05 100644 --- a/TaffyScriptCompiler/Backend/Closure.cs +++ b/TaffyScript.Compiler/Backend/Closure.cs @@ -6,7 +6,7 @@ using System.Reflection; using System.Reflection.Emit; -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { public class Closure { diff --git a/TaffyScriptCompiler/Backend/Compiler/CompileException.cs b/TaffyScript.Compiler/Backend/Compiler/CompileException.cs similarity index 87% rename from TaffyScriptCompiler/Backend/Compiler/CompileException.cs rename to TaffyScript.Compiler/Backend/Compiler/CompileException.cs index a54a63c..03f93a8 100644 --- a/TaffyScriptCompiler/Backend/Compiler/CompileException.cs +++ b/TaffyScript.Compiler/Backend/Compiler/CompileException.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { public class CompileException : Exception { diff --git a/TaffyScriptCompiler/Backend/Compiler/CompileMode.cs b/TaffyScript.Compiler/Backend/Compiler/CompileMode.cs similarity index 83% rename from TaffyScriptCompiler/Backend/Compiler/CompileMode.cs rename to TaffyScript.Compiler/Backend/Compiler/CompileMode.cs index 8dd7e5b..dea5572 100644 --- a/TaffyScriptCompiler/Backend/Compiler/CompileMode.cs +++ b/TaffyScript.Compiler/Backend/Compiler/CompileMode.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { public enum CompileMode { diff --git a/TaffyScriptCompiler/Backend/Compiler/CompilerResult.cs b/TaffyScript.Compiler/Backend/Compiler/CompilerResult.cs similarity index 96% rename from TaffyScriptCompiler/Backend/Compiler/CompilerResult.cs rename to TaffyScript.Compiler/Backend/Compiler/CompilerResult.cs index 6675be5..c1cbcfa 100644 --- a/TaffyScriptCompiler/Backend/Compiler/CompilerResult.cs +++ b/TaffyScript.Compiler/Backend/Compiler/CompilerResult.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using System.Reflection; -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { public class CompilerResult { diff --git a/TaffyScriptCompiler/Backend/Compiler/ICompiler.cs b/TaffyScript.Compiler/Backend/Compiler/ICompiler.cs similarity index 85% rename from TaffyScriptCompiler/Backend/Compiler/ICompiler.cs rename to TaffyScript.Compiler/Backend/Compiler/ICompiler.cs index 0ecc618..1a81f09 100644 --- a/TaffyScriptCompiler/Backend/Compiler/ICompiler.cs +++ b/TaffyScript.Compiler/Backend/Compiler/ICompiler.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { public interface ICompiler { diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs similarity index 99% rename from TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs rename to TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs index 2e48c0c..1109e80 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -7,10 +7,10 @@ using System.Reflection.Emit; using TaffyScript; using TaffyScript.Collections; -using TaffyScriptCompiler.DotNet; -using TaffyScriptCompiler.Syntax; +using TaffyScript.Compiler.DotNet; +using TaffyScript.Compiler.Syntax; -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { /// /// Generates an assembly based off of an abstract syntax tree. diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs.bak b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs.bak similarity index 100% rename from TaffyScriptCompiler/Backend/Compiler/MsilWeakCodeGen.cs.bak rename to TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs.bak diff --git a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCompiler.cs b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCompiler.cs similarity index 99% rename from TaffyScriptCompiler/Backend/Compiler/MsilWeakCompiler.cs rename to TaffyScript.Compiler/Backend/Compiler/MsilWeakCompiler.cs index 6c8120a..2e65f29 100644 --- a/TaffyScriptCompiler/Backend/Compiler/MsilWeakCompiler.cs +++ b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCompiler.cs @@ -5,7 +5,7 @@ using System.Text; using System.Xml.Serialization; -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { public class MsilWeakCompiler : Builder { diff --git a/TaffyScriptCompiler/Backend/ILEmitter.cs b/TaffyScript.Compiler/Backend/ILEmitter.cs similarity index 99% rename from TaffyScriptCompiler/Backend/ILEmitter.cs rename to TaffyScript.Compiler/Backend/ILEmitter.cs index efc2a1e..c957b53 100644 --- a/TaffyScriptCompiler/Backend/ILEmitter.cs +++ b/TaffyScript.Compiler/Backend/ILEmitter.cs @@ -6,7 +6,7 @@ using System.Reflection; using System.Reflection.Emit; -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { // This class is extremely useful. // A) It emits OpCodes in a functional way, diff --git a/TaffyScriptCompiler/Backend/ILEmitter.cs.bak b/TaffyScript.Compiler/Backend/ILEmitter.cs.bak similarity index 100% rename from TaffyScriptCompiler/Backend/ILEmitter.cs.bak rename to TaffyScript.Compiler/Backend/ILEmitter.cs.bak diff --git a/TaffyScriptCompiler/Backend/ImportType.cs b/TaffyScript.Compiler/Backend/ImportType.cs similarity index 83% rename from TaffyScriptCompiler/Backend/ImportType.cs rename to TaffyScript.Compiler/Backend/ImportType.cs index e5f85d6..4d87436 100644 --- a/TaffyScriptCompiler/Backend/ImportType.cs +++ b/TaffyScript.Compiler/Backend/ImportType.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { public enum ImportType : byte { diff --git a/TaffyScriptCompiler/Backend/NameConflictException.cs b/TaffyScript.Compiler/Backend/NameConflictException.cs similarity index 88% rename from TaffyScriptCompiler/Backend/NameConflictException.cs rename to TaffyScript.Compiler/Backend/NameConflictException.cs index 5793768..756e328 100644 --- a/TaffyScriptCompiler/Backend/NameConflictException.cs +++ b/TaffyScript.Compiler/Backend/NameConflictException.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Backend +namespace TaffyScript.Compiler.Backend { public class NameConflictException : Exception { diff --git a/TaffyScriptCompiler/DotNet/AssemblyLoader.cs b/TaffyScript.Compiler/DotNet/AssemblyLoader.cs similarity index 98% rename from TaffyScriptCompiler/DotNet/AssemblyLoader.cs rename to TaffyScript.Compiler/DotNet/AssemblyLoader.cs index d8512a0..e0c9819 100644 --- a/TaffyScriptCompiler/DotNet/AssemblyLoader.cs +++ b/TaffyScript.Compiler/DotNet/AssemblyLoader.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Reflection; -namespace TaffyScriptCompiler.DotNet +namespace TaffyScript.Compiler.DotNet { public class DotNetAssemblyLoader { diff --git a/TaffyScriptCompiler/DotNet/TaffyScriptTypes.cs b/TaffyScript.Compiler/DotNet/TaffyScriptTypes.cs similarity index 99% rename from TaffyScriptCompiler/DotNet/TaffyScriptTypes.cs rename to TaffyScript.Compiler/DotNet/TaffyScriptTypes.cs index 58b278c..91fc995 100644 --- a/TaffyScriptCompiler/DotNet/TaffyScriptTypes.cs +++ b/TaffyScript.Compiler/DotNet/TaffyScriptTypes.cs @@ -6,7 +6,7 @@ using System.Reflection; using TaffyScript; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public class TsTypes { diff --git a/TaffyScriptCompiler/DotNet/TaffyScriptTypes.cs.bak b/TaffyScript.Compiler/DotNet/TaffyScriptTypes.cs.bak similarity index 100% rename from TaffyScriptCompiler/DotNet/TaffyScriptTypes.cs.bak rename to TaffyScript.Compiler/DotNet/TaffyScriptTypes.cs.bak diff --git a/TaffyScriptCompiler/DotNet/TypeParser.cs b/TaffyScript.Compiler/DotNet/TypeParser.cs similarity index 95% rename from TaffyScriptCompiler/DotNet/TypeParser.cs rename to TaffyScript.Compiler/DotNet/TypeParser.cs index f3f118e..4df4fb9 100644 --- a/TaffyScriptCompiler/DotNet/TypeParser.cs +++ b/TaffyScript.Compiler/DotNet/TypeParser.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using System.Text.RegularExpressions; -namespace TaffyScriptCompiler.DotNet +namespace TaffyScript.Compiler.DotNet { // This class is primarily used when trying to find the declaring type of an imported method. @@ -18,7 +18,7 @@ public class DotNetTypeParser // Base - The basic type name. // Generic - Any Generic parameters. For example, the type int and string in Dictionary. // Rank - Gets the array specifier and rank. - private Regex _typeRegex = new Regex(@"(?[a-zA-Z_][a-zA-Z0-9_.]*)\s*(\<(?(\s*,?\s*[a-zA-Z_][a-zA-Z0-9_]*\s*(\<.+\>)?(\[(\s*,)*\s*\])?)+)\>)?\s*(?\[(\s*,)*\s*\])?", RegexOptions.Compiled); + private static Regex _typeRegex = new Regex(@"(?[a-zA-Z_][a-zA-Z0-9_.]*)\s*(\<(?(\s*,?\s*[a-zA-Z_][a-zA-Z0-9_]*\s*(\<.+\>)?(\[(\s*,)*\s*\])?)+)\>)?\s*(?\[(\s*,)*\s*\])?", RegexOptions.Compiled); private Dictionary _typeNames = new Dictionary(); private DotNetAssemblyLoader _assemblies; diff --git a/TaffyScriptCompiler/Front End/InvalidTokenException.cs b/TaffyScript.Compiler/Front End/InvalidTokenException.cs similarity index 94% rename from TaffyScriptCompiler/Front End/InvalidTokenException.cs rename to TaffyScript.Compiler/Front End/InvalidTokenException.cs index 644bd9d..e972ffb 100644 --- a/TaffyScriptCompiler/Front End/InvalidTokenException.cs +++ b/TaffyScript.Compiler/Front End/InvalidTokenException.cs @@ -3,9 +3,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using TaffyScriptCompiler.FrontEnd; +using TaffyScript.Compiler.FrontEnd; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public class InvalidTokenException : Exception { diff --git a/TaffyScriptCompiler/Front End/LexicalAnalysis/Token.cs b/TaffyScript.Compiler/Front End/LexicalAnalysis/Token.cs similarity index 95% rename from TaffyScriptCompiler/Front End/LexicalAnalysis/Token.cs rename to TaffyScript.Compiler/Front End/LexicalAnalysis/Token.cs index 2bf8099..3a81a97 100644 --- a/TaffyScriptCompiler/Front End/LexicalAnalysis/Token.cs +++ b/TaffyScript.Compiler/Front End/LexicalAnalysis/Token.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.FrontEnd +namespace TaffyScript.Compiler.FrontEnd { public class Token { diff --git a/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenPosition.cs b/TaffyScript.Compiler/Front End/LexicalAnalysis/TokenPosition.cs similarity index 97% rename from TaffyScriptCompiler/Front End/LexicalAnalysis/TokenPosition.cs rename to TaffyScript.Compiler/Front End/LexicalAnalysis/TokenPosition.cs index d519652..74f6c95 100644 --- a/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenPosition.cs +++ b/TaffyScript.Compiler/Front End/LexicalAnalysis/TokenPosition.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { /// /// Represents a position within a document/stream where a was found. diff --git a/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs b/TaffyScript.Compiler/Front End/LexicalAnalysis/TokenType.cs similarity index 97% rename from TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs rename to TaffyScript.Compiler/Front End/LexicalAnalysis/TokenType.cs index da196e0..3fe9139 100644 --- a/TaffyScriptCompiler/Front End/LexicalAnalysis/TokenType.cs +++ b/TaffyScript.Compiler/Front End/LexicalAnalysis/TokenType.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.FrontEnd +namespace TaffyScript.Compiler.FrontEnd { public enum TokenType { diff --git a/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs b/TaffyScript.Compiler/Front End/LexicalAnalysis/Tokenizer.cs similarity index 99% rename from TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs rename to TaffyScript.Compiler/Front End/LexicalAnalysis/Tokenizer.cs index 52441e9..1eafedb 100644 --- a/TaffyScriptCompiler/Front End/LexicalAnalysis/Tokenizer.cs +++ b/TaffyScript.Compiler/Front End/LexicalAnalysis/Tokenizer.cs @@ -3,7 +3,7 @@ using System.IO; using System.Text; -namespace TaffyScriptCompiler.FrontEnd +namespace TaffyScript.Compiler.FrontEnd { // This class uses many switch statements and a few goto statements in an effort to be as swift as possible. diff --git a/TaffyScriptCompiler/Front End/LexicalAnalysis/UnrecognizedTokenException.cs b/TaffyScript.Compiler/Front End/LexicalAnalysis/UnrecognizedTokenException.cs similarity index 97% rename from TaffyScriptCompiler/Front End/LexicalAnalysis/UnrecognizedTokenException.cs rename to TaffyScript.Compiler/Front End/LexicalAnalysis/UnrecognizedTokenException.cs index 537704d..328f5aa 100644 --- a/TaffyScriptCompiler/Front End/LexicalAnalysis/UnrecognizedTokenException.cs +++ b/TaffyScript.Compiler/Front End/LexicalAnalysis/UnrecognizedTokenException.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.FrontEnd +namespace TaffyScript.Compiler.FrontEnd { /// /// This exception is thrown when a lexer or tokenizer encounters an undefined token. diff --git a/TaffyScriptCompiler/Front End/Parser.cs b/TaffyScript.Compiler/Front End/Parser.cs similarity index 99% rename from TaffyScriptCompiler/Front End/Parser.cs rename to TaffyScript.Compiler/Front End/Parser.cs index ed19865..9da3bb2 100644 --- a/TaffyScriptCompiler/Front End/Parser.cs +++ b/TaffyScript.Compiler/Front End/Parser.cs @@ -4,10 +4,10 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; -using TaffyScriptCompiler.FrontEnd; -using TaffyScriptCompiler.Syntax; +using TaffyScript.Compiler.FrontEnd; +using TaffyScript.Compiler.Syntax; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { /// /// Parses TaffyScript code and generates an AST based on the input. @@ -32,6 +32,7 @@ private static HashSet HexCharacters private SymbolTable _table; private ISyntaxElementFactory _factory; private int lambdaId = 0; + private IErrorLogger _logger; /// /// Flag used to determine whether = should mean assignment or equality. diff --git a/TaffyScriptCompiler/Front End/Parser.cs.bak b/TaffyScript.Compiler/Front End/Parser.cs.bak similarity index 100% rename from TaffyScriptCompiler/Front End/Parser.cs.bak rename to TaffyScript.Compiler/Front End/Parser.cs.bak diff --git a/TaffyScript.Compiler/IErrorLogger.cs b/TaffyScript.Compiler/IErrorLogger.cs new file mode 100644 index 0000000..90e1d37 --- /dev/null +++ b/TaffyScript.Compiler/IErrorLogger.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaffyScript.Compiler +{ + public interface IErrorLogger + { + List Errors { get; } + List Warnings { get; } + void Error(string message, TokenPosition position); + void Warning(string message, TokenPosition position); + } +} diff --git a/TaffyScriptCompiler/Properties/AssemblyInfo.cs b/TaffyScript.Compiler/Properties/AssemblyInfo.cs similarity index 93% rename from TaffyScriptCompiler/Properties/AssemblyInfo.cs rename to TaffyScript.Compiler/Properties/AssemblyInfo.cs index 02acd45..c64ea96 100644 --- a/TaffyScriptCompiler/Properties/AssemblyInfo.cs +++ b/TaffyScript.Compiler/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("TaffyScriptCompiler")] +[assembly: AssemblyTitle("TaffyScript.Compiler")] [assembly: AssemblyDescription("The source for the TaffyScript language compiler")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Precisamento")] -[assembly: AssemblyProduct("TaffyScriptCompiler")] +[assembly: AssemblyProduct("TaffyScript.Compiler")] [assembly: AssemblyCopyright("Copyright © 2018")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/TaffyScriptCompiler/StringUtils.cs b/TaffyScript.Compiler/StringUtils.cs similarity index 97% rename from TaffyScriptCompiler/StringUtils.cs rename to TaffyScript.Compiler/StringUtils.cs index 96f29c4..69b0758 100644 --- a/TaffyScriptCompiler/StringUtils.cs +++ b/TaffyScript.Compiler/StringUtils.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public static class StringUtils { diff --git a/TaffyScriptCompiler/Symbols/EnumLeaf.cs b/TaffyScript.Compiler/Symbols/EnumLeaf.cs similarity index 92% rename from TaffyScriptCompiler/Symbols/EnumLeaf.cs rename to TaffyScript.Compiler/Symbols/EnumLeaf.cs index f73e64c..7d64ed4 100644 --- a/TaffyScriptCompiler/Symbols/EnumLeaf.cs +++ b/TaffyScript.Compiler/Symbols/EnumLeaf.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public class EnumLeaf : SymbolLeaf { diff --git a/TaffyScriptCompiler/Symbols/ISymbol.cs b/TaffyScript.Compiler/Symbols/ISymbol.cs similarity index 85% rename from TaffyScriptCompiler/Symbols/ISymbol.cs rename to TaffyScript.Compiler/Symbols/ISymbol.cs index 1d1cebc..37d37cb 100644 --- a/TaffyScriptCompiler/Symbols/ISymbol.cs +++ b/TaffyScript.Compiler/Symbols/ISymbol.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public interface ISymbol { diff --git a/TaffyScriptCompiler/Symbols/ImportLeaf.cs b/TaffyScript.Compiler/Symbols/ImportLeaf.cs similarity index 86% rename from TaffyScriptCompiler/Symbols/ImportLeaf.cs rename to TaffyScript.Compiler/Symbols/ImportLeaf.cs index cd91463..5475639 100644 --- a/TaffyScriptCompiler/Symbols/ImportLeaf.cs +++ b/TaffyScript.Compiler/Symbols/ImportLeaf.cs @@ -3,9 +3,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using TaffyScriptCompiler.Syntax; +using TaffyScript.Compiler.Syntax; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public class ImportLeaf : SymbolLeaf { diff --git a/TaffyScriptCompiler/Symbols/ImportObjectLeaf.cs b/TaffyScript.Compiler/Symbols/ImportObjectLeaf.cs similarity index 90% rename from TaffyScriptCompiler/Symbols/ImportObjectLeaf.cs rename to TaffyScript.Compiler/Symbols/ImportObjectLeaf.cs index 665a550..3362d25 100644 --- a/TaffyScriptCompiler/Symbols/ImportObjectLeaf.cs +++ b/TaffyScript.Compiler/Symbols/ImportObjectLeaf.cs @@ -3,9 +3,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using TaffyScriptCompiler.Syntax; +using TaffyScript.Compiler.Syntax; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public class ImportObjectLeaf : SymbolLeaf { diff --git a/TaffyScriptCompiler/Symbols/InvalidSymbolException.cs b/TaffyScript.Compiler/Symbols/InvalidSymbolException.cs similarity index 93% rename from TaffyScriptCompiler/Symbols/InvalidSymbolException.cs rename to TaffyScript.Compiler/Symbols/InvalidSymbolException.cs index 852c65d..da3c4d7 100644 --- a/TaffyScriptCompiler/Symbols/InvalidSymbolException.cs +++ b/TaffyScript.Compiler/Symbols/InvalidSymbolException.cs @@ -1,6 +1,6 @@ using System; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public class InvalidSymbolException : Exception { diff --git a/TaffyScriptCompiler/Symbols/SymbolLeaf.cs b/TaffyScript.Compiler/Symbols/SymbolLeaf.cs similarity index 95% rename from TaffyScriptCompiler/Symbols/SymbolLeaf.cs rename to TaffyScript.Compiler/Symbols/SymbolLeaf.cs index be32ec4..d124c6e 100644 --- a/TaffyScriptCompiler/Symbols/SymbolLeaf.cs +++ b/TaffyScript.Compiler/Symbols/SymbolLeaf.cs @@ -1,6 +1,6 @@ using System; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public class SymbolLeaf : ISymbol { diff --git a/TaffyScriptCompiler/Symbols/SymbolNode.cs b/TaffyScript.Compiler/Symbols/SymbolNode.cs similarity index 97% rename from TaffyScriptCompiler/Symbols/SymbolNode.cs rename to TaffyScript.Compiler/Symbols/SymbolNode.cs index fc67b11..2347ada 100644 --- a/TaffyScriptCompiler/Symbols/SymbolNode.cs +++ b/TaffyScript.Compiler/Symbols/SymbolNode.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public class SymbolNode : ISymbol { diff --git a/TaffyScriptCompiler/Symbols/SymbolScope.cs b/TaffyScript.Compiler/Symbols/SymbolScope.cs similarity index 87% rename from TaffyScriptCompiler/Symbols/SymbolScope.cs rename to TaffyScript.Compiler/Symbols/SymbolScope.cs index ed8fd22..565c267 100644 --- a/TaffyScriptCompiler/Symbols/SymbolScope.cs +++ b/TaffyScript.Compiler/Symbols/SymbolScope.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public enum SymbolScope { diff --git a/TaffyScriptCompiler/Symbols/SymbolTable.cs b/TaffyScript.Compiler/Symbols/SymbolTable.cs similarity index 99% rename from TaffyScriptCompiler/Symbols/SymbolTable.cs rename to TaffyScript.Compiler/Symbols/SymbolTable.cs index c5c2828..d29dbef 100644 --- a/TaffyScriptCompiler/Symbols/SymbolTable.cs +++ b/TaffyScript.Compiler/Symbols/SymbolTable.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public class SymbolTable { diff --git a/TaffyScriptCompiler/Symbols/SymbolType.cs b/TaffyScript.Compiler/Symbols/SymbolType.cs similarity index 89% rename from TaffyScriptCompiler/Symbols/SymbolType.cs rename to TaffyScript.Compiler/Symbols/SymbolType.cs index 75f8e14..671dcf7 100644 --- a/TaffyScriptCompiler/Symbols/SymbolType.cs +++ b/TaffyScript.Compiler/Symbols/SymbolType.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public enum SymbolType { diff --git a/TaffyScriptCompiler/Symbols/SymbolType.cs.bak b/TaffyScript.Compiler/Symbols/SymbolType.cs.bak similarity index 100% rename from TaffyScriptCompiler/Symbols/SymbolType.cs.bak rename to TaffyScript.Compiler/Symbols/SymbolType.cs.bak diff --git a/TaffyScriptCompiler/Symbols/VariableLeaf.cs b/TaffyScript.Compiler/Symbols/VariableLeaf.cs similarity index 92% rename from TaffyScriptCompiler/Symbols/VariableLeaf.cs rename to TaffyScript.Compiler/Symbols/VariableLeaf.cs index cb26f27..17341a6 100644 --- a/TaffyScriptCompiler/Symbols/VariableLeaf.cs +++ b/TaffyScript.Compiler/Symbols/VariableLeaf.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public class VariableLeaf : SymbolLeaf { diff --git a/TaffyScriptCompiler/Syntax/Concrete/AdditiveNode.cs b/TaffyScript.Compiler/Syntax/Concrete/AdditiveNode.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/AdditiveNode.cs rename to TaffyScript.Compiler/Syntax/Concrete/AdditiveNode.cs index f3cdf5b..ce8405c 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/AdditiveNode.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/AdditiveNode.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class AdditiveNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/ArgumentAccess.cs b/TaffyScript.Compiler/Syntax/Concrete/ArgumentAccess.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/ArgumentAccess.cs rename to TaffyScript.Compiler/Syntax/Concrete/ArgumentAccess.cs index 944babb..5d27518 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ArgumentAccess.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ArgumentAccess.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ArgumentAccessNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/ArrayAccess.cs b/TaffyScript.Compiler/Syntax/Concrete/ArrayAccess.cs similarity index 95% rename from TaffyScriptCompiler/Syntax/Concrete/ArrayAccess.cs rename to TaffyScript.Compiler/Syntax/Concrete/ArrayAccess.cs index 909abee..a111130 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ArrayAccess.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ArrayAccess.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ArrayAccessNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/ArrayLiteral.cs b/TaffyScript.Compiler/Syntax/Concrete/ArrayLiteral.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/ArrayLiteral.cs rename to TaffyScript.Compiler/Syntax/Concrete/ArrayLiteral.cs index b0c70b0..d89ad5a 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ArrayLiteral.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ArrayLiteral.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ArrayLiteralNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Assign.cs b/TaffyScript.Compiler/Syntax/Concrete/Assign.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/Assign.cs rename to TaffyScript.Compiler/Syntax/Concrete/Assign.cs index 8dbd30e..e6a3616 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Assign.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Assign.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class AssignNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Bitwise.cs b/TaffyScript.Compiler/Syntax/Concrete/Bitwise.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/Bitwise.cs rename to TaffyScript.Compiler/Syntax/Concrete/Bitwise.cs index 85ef369..8232a5c 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Bitwise.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Bitwise.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class BitwiseNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Block.cs b/TaffyScript.Compiler/Syntax/Concrete/Block.cs similarity index 89% rename from TaffyScriptCompiler/Syntax/Concrete/Block.cs rename to TaffyScript.Compiler/Syntax/Concrete/Block.cs index 95cec4a..a82499a 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Block.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Block.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class BlockNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/BreakToken.cs b/TaffyScript.Compiler/Syntax/Concrete/BreakToken.cs similarity index 89% rename from TaffyScriptCompiler/Syntax/Concrete/BreakToken.cs rename to TaffyScript.Compiler/Syntax/Concrete/BreakToken.cs index 8e72a61..f816c22 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/BreakToken.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/BreakToken.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class BreakToken : SyntaxToken { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Case.cs b/TaffyScript.Compiler/Syntax/Concrete/Case.cs similarity index 93% rename from TaffyScriptCompiler/Syntax/Concrete/Case.cs rename to TaffyScript.Compiler/Syntax/Concrete/Case.cs index ed98fc6..feac106 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Case.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Case.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class CaseNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Conditional.cs b/TaffyScript.Compiler/Syntax/Concrete/Conditional.cs similarity index 92% rename from TaffyScriptCompiler/Syntax/Concrete/Conditional.cs rename to TaffyScript.Compiler/Syntax/Concrete/Conditional.cs index 23ac3c1..e8183bc 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Conditional.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Conditional.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ConditionalNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/ConstantToken.cs b/TaffyScript.Compiler/Syntax/Concrete/ConstantToken.cs similarity index 94% rename from TaffyScriptCompiler/Syntax/Concrete/ConstantToken.cs rename to TaffyScript.Compiler/Syntax/Concrete/ConstantToken.cs index 7529fde..c0a327c 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ConstantToken.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ConstantToken.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ConstantToken : SyntaxToken, IConstantToken { diff --git a/TaffyScriptCompiler/Syntax/Concrete/ContinueToken.cs b/TaffyScript.Compiler/Syntax/Concrete/ContinueToken.cs similarity index 89% rename from TaffyScriptCompiler/Syntax/Concrete/ContinueToken.cs rename to TaffyScript.Compiler/Syntax/Concrete/ContinueToken.cs index 0073477..8254472 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ContinueToken.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ContinueToken.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ContinueToken : SyntaxToken { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Declare.cs b/TaffyScript.Compiler/Syntax/Concrete/Declare.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/Declare.cs rename to TaffyScript.Compiler/Syntax/Concrete/Declare.cs index 27fbedb..d7f6100 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Declare.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Declare.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class DeclareNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Default.cs b/TaffyScript.Compiler/Syntax/Concrete/Default.cs similarity index 90% rename from TaffyScriptCompiler/Syntax/Concrete/Default.cs rename to TaffyScript.Compiler/Syntax/Concrete/Default.cs index 1964053..bd2fdae 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Default.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Default.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class DefaultNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Do.cs b/TaffyScript.Compiler/Syntax/Concrete/Do.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/Do.cs rename to TaffyScript.Compiler/Syntax/Concrete/Do.cs index 0088629..bac449c 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Do.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Do.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class DoNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/EndToken.cs b/TaffyScript.Compiler/Syntax/Concrete/EndToken.cs similarity index 89% rename from TaffyScriptCompiler/Syntax/Concrete/EndToken.cs rename to TaffyScript.Compiler/Syntax/Concrete/EndToken.cs index a6e03d7..97f7371 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/EndToken.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/EndToken.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class EndToken : SyntaxToken { diff --git a/TaffyScriptCompiler/Syntax/Concrete/EnumDeclaration.cs b/TaffyScript.Compiler/Syntax/Concrete/EnumDeclaration.cs similarity index 89% rename from TaffyScriptCompiler/Syntax/Concrete/EnumDeclaration.cs rename to TaffyScript.Compiler/Syntax/Concrete/EnumDeclaration.cs index 02bffc6..bd602d4 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/EnumDeclaration.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/EnumDeclaration.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class EnumNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Equality.cs b/TaffyScript.Compiler/Syntax/Concrete/Equality.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/Equality.cs rename to TaffyScript.Compiler/Syntax/Concrete/Equality.cs index cccfeff..b484da7 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Equality.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Equality.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class EqualityNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/ExitToken.cs b/TaffyScript.Compiler/Syntax/Concrete/ExitToken.cs similarity index 89% rename from TaffyScriptCompiler/Syntax/Concrete/ExitToken.cs rename to TaffyScript.Compiler/Syntax/Concrete/ExitToken.cs index 7f6f5eb..ef268e0 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ExitToken.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ExitToken.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ExitToken : SyntaxToken { diff --git a/TaffyScriptCompiler/Syntax/Concrete/For.cs b/TaffyScript.Compiler/Syntax/Concrete/For.cs similarity index 93% rename from TaffyScriptCompiler/Syntax/Concrete/For.cs rename to TaffyScript.Compiler/Syntax/Concrete/For.cs index 7d8ee81..0c1eb95 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/For.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/For.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ForNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/FunctionCall.cs b/TaffyScript.Compiler/Syntax/Concrete/FunctionCall.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/FunctionCall.cs rename to TaffyScript.Compiler/Syntax/Concrete/FunctionCall.cs index bd40fda..4167f75 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/FunctionCall.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/FunctionCall.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class FunctionCallNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/If.cs b/TaffyScript.Compiler/Syntax/Concrete/If.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/If.cs rename to TaffyScript.Compiler/Syntax/Concrete/If.cs index 2648a11..abeecb1 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/If.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/If.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class IfNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Import.cs b/TaffyScript.Compiler/Syntax/Concrete/Import.cs similarity index 95% rename from TaffyScriptCompiler/Syntax/Concrete/Import.cs rename to TaffyScript.Compiler/Syntax/Concrete/Import.cs index 54ef7f7..e6a3119 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Import.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Import.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ImportNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportCasing.cs b/TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportCasing.cs similarity index 85% rename from TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportCasing.cs rename to TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportCasing.cs index 5cca909..6d6fa56 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportCasing.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportCasing.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public enum ImportCasing { diff --git a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObject.cs b/TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportObject.cs similarity index 99% rename from TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObject.cs rename to TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportObject.cs index e01a0f5..668e498 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObject.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportObject.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ImportObjectNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectConstructor.cs b/TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportObjectConstructor.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectConstructor.cs rename to TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportObjectConstructor.cs index 6265e8d..e0acb88 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectConstructor.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportObjectConstructor.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ImportObjectConstructor { diff --git a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectField.cs b/TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportObjectField.cs similarity index 94% rename from TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectField.cs rename to TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportObjectField.cs index 5a52c0f..2c2d652 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectField.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportObjectField.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ImportObjectField { diff --git a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectMethod.cs b/TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportObjectMethod.cs similarity index 97% rename from TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectMethod.cs rename to TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportObjectMethod.cs index ddf8094..30b43b3 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ImportObject/ImportObjectMethod.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ImportObject/ImportObjectMethod.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ImportObjectMethod { diff --git a/TaffyScriptCompiler/Syntax/Concrete/LambdaNode.cs b/TaffyScript.Compiler/Syntax/Concrete/LambdaNode.cs similarity index 96% rename from TaffyScriptCompiler/Syntax/Concrete/LambdaNode.cs rename to TaffyScript.Compiler/Syntax/Concrete/LambdaNode.cs index 15cce26..0da0d83 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/LambdaNode.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/LambdaNode.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class LambdaNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Locals.cs b/TaffyScript.Compiler/Syntax/Concrete/Locals.cs similarity index 89% rename from TaffyScriptCompiler/Syntax/Concrete/Locals.cs rename to TaffyScript.Compiler/Syntax/Concrete/Locals.cs index f00265c..e3eb90d 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Locals.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Locals.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class LocalsNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Logical.cs b/TaffyScript.Compiler/Syntax/Concrete/Logical.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/Logical.cs rename to TaffyScript.Compiler/Syntax/Concrete/Logical.cs index e00a79b..a5500e1 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Logical.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Logical.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class LogicalNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/MemberAccess.cs b/TaffyScript.Compiler/Syntax/Concrete/MemberAccess.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/MemberAccess.cs rename to TaffyScript.Compiler/Syntax/Concrete/MemberAccess.cs index 0a9e5fb..34961ec 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/MemberAccess.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/MemberAccess.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class MemberAccessNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Multiplicative.cs b/TaffyScript.Compiler/Syntax/Concrete/Multiplicative.cs similarity index 92% rename from TaffyScriptCompiler/Syntax/Concrete/Multiplicative.cs rename to TaffyScript.Compiler/Syntax/Concrete/Multiplicative.cs index ae25184..814751e 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Multiplicative.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Multiplicative.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class MultiplicativeNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/NamespaceNode.cs b/TaffyScript.Compiler/Syntax/Concrete/NamespaceNode.cs similarity index 89% rename from TaffyScriptCompiler/Syntax/Concrete/NamespaceNode.cs rename to TaffyScript.Compiler/Syntax/Concrete/NamespaceNode.cs index d4b344a..0448d43 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/NamespaceNode.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/NamespaceNode.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class NamespaceNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/NewNode.cs b/TaffyScript.Compiler/Syntax/Concrete/NewNode.cs similarity index 92% rename from TaffyScriptCompiler/Syntax/Concrete/NewNode.cs rename to TaffyScript.Compiler/Syntax/Concrete/NewNode.cs index 8b4e283..0493463 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/NewNode.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/NewNode.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class NewNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/NewNode.cs.bak b/TaffyScript.Compiler/Syntax/Concrete/NewNode.cs.bak similarity index 100% rename from TaffyScriptCompiler/Syntax/Concrete/NewNode.cs.bak rename to TaffyScript.Compiler/Syntax/Concrete/NewNode.cs.bak diff --git a/TaffyScriptCompiler/Syntax/Concrete/ObjectNode.cs b/TaffyScript.Compiler/Syntax/Concrete/ObjectNode.cs similarity index 90% rename from TaffyScriptCompiler/Syntax/Concrete/ObjectNode.cs rename to TaffyScript.Compiler/Syntax/Concrete/ObjectNode.cs index 70a5362..aceaf02 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ObjectNode.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ObjectNode.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ObjectNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Postfix.cs b/TaffyScript.Compiler/Syntax/Concrete/Postfix.cs similarity index 90% rename from TaffyScriptCompiler/Syntax/Concrete/Postfix.cs rename to TaffyScript.Compiler/Syntax/Concrete/Postfix.cs index 0639060..6c46d4c 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Postfix.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Postfix.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class PostfixNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Prefix.cs b/TaffyScript.Compiler/Syntax/Concrete/Prefix.cs similarity index 90% rename from TaffyScriptCompiler/Syntax/Concrete/Prefix.cs rename to TaffyScript.Compiler/Syntax/Concrete/Prefix.cs index a9a8b2f..ebd1505 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Prefix.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Prefix.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class PrefixNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/ReadOnlyToken.cs b/TaffyScript.Compiler/Syntax/Concrete/ReadOnlyToken.cs similarity index 89% rename from TaffyScriptCompiler/Syntax/Concrete/ReadOnlyToken.cs rename to TaffyScript.Compiler/Syntax/Concrete/ReadOnlyToken.cs index 09162bc..7aa3c46 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/ReadOnlyToken.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/ReadOnlyToken.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ReadOnlyToken : SyntaxToken { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Relational.cs b/TaffyScript.Compiler/Syntax/Concrete/Relational.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/Relational.cs rename to TaffyScript.Compiler/Syntax/Concrete/Relational.cs index 496db26..a7da6a9 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Relational.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Relational.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class RelationalNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/RepeatNode.cs b/TaffyScript.Compiler/Syntax/Concrete/RepeatNode.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/RepeatNode.cs rename to TaffyScript.Compiler/Syntax/Concrete/RepeatNode.cs index 438615b..9fc1ef2 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/RepeatNode.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/RepeatNode.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class RepeatNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Return.cs b/TaffyScript.Compiler/Syntax/Concrete/Return.cs similarity index 90% rename from TaffyScriptCompiler/Syntax/Concrete/Return.cs rename to TaffyScript.Compiler/Syntax/Concrete/Return.cs index 4768924..92a913a 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Return.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Return.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ReturnNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Root.cs b/TaffyScript.Compiler/Syntax/Concrete/Root.cs similarity index 92% rename from TaffyScriptCompiler/Syntax/Concrete/Root.cs rename to TaffyScript.Compiler/Syntax/Concrete/Root.cs index f1fad70..1786a87 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Root.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Root.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class RootNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Script.cs b/TaffyScript.Compiler/Syntax/Concrete/Script.cs similarity index 95% rename from TaffyScriptCompiler/Syntax/Concrete/Script.cs rename to TaffyScript.Compiler/Syntax/Concrete/Script.cs index c2d2891..cb6b750 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Script.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Script.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ScriptNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Script.cs.bak b/TaffyScript.Compiler/Syntax/Concrete/Script.cs.bak similarity index 100% rename from TaffyScriptCompiler/Syntax/Concrete/Script.cs.bak rename to TaffyScript.Compiler/Syntax/Concrete/Script.cs.bak diff --git a/TaffyScriptCompiler/Syntax/Concrete/Shift.cs b/TaffyScript.Compiler/Syntax/Concrete/Shift.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/Shift.cs rename to TaffyScript.Compiler/Syntax/Concrete/Shift.cs index 59c4e3c..46848bd 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Shift.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Shift.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class ShiftNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/Switch.cs b/TaffyScript.Compiler/Syntax/Concrete/Switch.cs similarity index 93% rename from TaffyScriptCompiler/Syntax/Concrete/Switch.cs rename to TaffyScript.Compiler/Syntax/Concrete/Switch.cs index f008d08..ce47603 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/Switch.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Switch.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class SwitchNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/UsingsNode.cs b/TaffyScript.Compiler/Syntax/Concrete/UsingsNode.cs similarity index 95% rename from TaffyScriptCompiler/Syntax/Concrete/UsingsNode.cs rename to TaffyScript.Compiler/Syntax/Concrete/UsingsNode.cs index bfa68fa..c1b20fd 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/UsingsNode.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/UsingsNode.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class UsingsNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/VariableToken.cs b/TaffyScript.Compiler/Syntax/Concrete/VariableToken.cs similarity index 89% rename from TaffyScriptCompiler/Syntax/Concrete/VariableToken.cs rename to TaffyScript.Compiler/Syntax/Concrete/VariableToken.cs index b07195f..b99431d 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/VariableToken.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/VariableToken.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class VariableToken : SyntaxToken { diff --git a/TaffyScriptCompiler/Syntax/Concrete/While.cs b/TaffyScript.Compiler/Syntax/Concrete/While.cs similarity index 91% rename from TaffyScriptCompiler/Syntax/Concrete/While.cs rename to TaffyScript.Compiler/Syntax/Concrete/While.cs index dcee1fa..0096280 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/While.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/While.cs @@ -1,4 +1,4 @@ -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class WhileNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/Concrete/WithNode.cs b/TaffyScript.Compiler/Syntax/Concrete/WithNode.cs similarity index 92% rename from TaffyScriptCompiler/Syntax/Concrete/WithNode.cs rename to TaffyScript.Compiler/Syntax/Concrete/WithNode.cs index 2bf8748..64e1956 100644 --- a/TaffyScriptCompiler/Syntax/Concrete/WithNode.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/WithNode.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class WithNode : SyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/ConstantType.cs b/TaffyScript.Compiler/Syntax/ConstantType.cs similarity index 87% rename from TaffyScriptCompiler/Syntax/ConstantType.cs rename to TaffyScript.Compiler/Syntax/ConstantType.cs index a776f32..2d61d56 100644 --- a/TaffyScriptCompiler/Syntax/ConstantType.cs +++ b/TaffyScript.Compiler/Syntax/ConstantType.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public enum ConstantType { diff --git a/TaffyScriptCompiler/Syntax/IConstantToken.cs b/TaffyScript.Compiler/Syntax/IConstantToken.cs similarity index 90% rename from TaffyScriptCompiler/Syntax/IConstantToken.cs rename to TaffyScript.Compiler/Syntax/IConstantToken.cs index 97a970d..8e0bb95 100644 --- a/TaffyScriptCompiler/Syntax/IConstantToken.cs +++ b/TaffyScript.Compiler/Syntax/IConstantToken.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public interface IConstantToken : ISyntaxToken { diff --git a/TaffyScriptCompiler/Syntax/ISyntaxElement.cs b/TaffyScript.Compiler/Syntax/ISyntaxElement.cs similarity index 84% rename from TaffyScriptCompiler/Syntax/ISyntaxElement.cs rename to TaffyScript.Compiler/Syntax/ISyntaxElement.cs index 5b725f0..4f119fa 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxElement.cs +++ b/TaffyScript.Compiler/Syntax/ISyntaxElement.cs @@ -3,9 +3,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using TaffyScriptCompiler.FrontEnd; +using TaffyScript.Compiler.FrontEnd; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public interface ISyntaxElement { diff --git a/TaffyScriptCompiler/Syntax/ISyntaxElementFactory.cs b/TaffyScript.Compiler/Syntax/ISyntaxElementFactory.cs similarity index 93% rename from TaffyScriptCompiler/Syntax/ISyntaxElementFactory.cs rename to TaffyScript.Compiler/Syntax/ISyntaxElementFactory.cs index 8e754a3..676479a 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxElementFactory.cs +++ b/TaffyScript.Compiler/Syntax/ISyntaxElementFactory.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public interface ISyntaxElementFactory { diff --git a/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs b/TaffyScript.Compiler/Syntax/ISyntaxElementVisitor.cs similarity index 98% rename from TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs rename to TaffyScript.Compiler/Syntax/ISyntaxElementVisitor.cs index 5051564..5e02a32 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs +++ b/TaffyScript.Compiler/Syntax/ISyntaxElementVisitor.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public interface ISyntaxElementVisitor { diff --git a/TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs.bak b/TaffyScript.Compiler/Syntax/ISyntaxElementVisitor.cs.bak similarity index 100% rename from TaffyScriptCompiler/Syntax/ISyntaxElementVisitor.cs.bak rename to TaffyScript.Compiler/Syntax/ISyntaxElementVisitor.cs.bak diff --git a/TaffyScriptCompiler/Syntax/ISyntaxNode.cs b/TaffyScript.Compiler/Syntax/ISyntaxNode.cs similarity index 89% rename from TaffyScriptCompiler/Syntax/ISyntaxNode.cs rename to TaffyScript.Compiler/Syntax/ISyntaxNode.cs index ee73058..c15783a 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxNode.cs +++ b/TaffyScript.Compiler/Syntax/ISyntaxNode.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public interface ISyntaxNode : ISyntaxElement { diff --git a/TaffyScriptCompiler/Syntax/ISyntaxToken.cs b/TaffyScript.Compiler/Syntax/ISyntaxToken.cs similarity index 83% rename from TaffyScriptCompiler/Syntax/ISyntaxToken.cs rename to TaffyScript.Compiler/Syntax/ISyntaxToken.cs index be59078..3fe628e 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxToken.cs +++ b/TaffyScript.Compiler/Syntax/ISyntaxToken.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public interface ISyntaxToken : ISyntaxElement { diff --git a/TaffyScriptCompiler/Syntax/ISyntaxTree.cs b/TaffyScript.Compiler/Syntax/ISyntaxTree.cs similarity index 86% rename from TaffyScriptCompiler/Syntax/ISyntaxTree.cs rename to TaffyScript.Compiler/Syntax/ISyntaxTree.cs index c3db62f..45adc07 100644 --- a/TaffyScriptCompiler/Syntax/ISyntaxTree.cs +++ b/TaffyScript.Compiler/Syntax/ISyntaxTree.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public interface ISyntaxTree { diff --git a/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs b/TaffyScript.Compiler/Syntax/SyntaxElementFactory.cs similarity index 99% rename from TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs rename to TaffyScript.Compiler/Syntax/SyntaxElementFactory.cs index 3b9adf6..29f9e2c 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs +++ b/TaffyScript.Compiler/Syntax/SyntaxElementFactory.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public class SyntaxElementFactory : ISyntaxElementFactory { diff --git a/TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs.bak b/TaffyScript.Compiler/Syntax/SyntaxElementFactory.cs.bak similarity index 100% rename from TaffyScriptCompiler/Syntax/SyntaxElementFactory.cs.bak rename to TaffyScript.Compiler/Syntax/SyntaxElementFactory.cs.bak diff --git a/TaffyScriptCompiler/Syntax/SyntaxNode.cs b/TaffyScript.Compiler/Syntax/SyntaxNode.cs similarity index 96% rename from TaffyScriptCompiler/Syntax/SyntaxNode.cs rename to TaffyScript.Compiler/Syntax/SyntaxNode.cs index 47c6ea0..668264e 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxNode.cs +++ b/TaffyScript.Compiler/Syntax/SyntaxNode.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public abstract class SyntaxNode : ISyntaxNode { diff --git a/TaffyScriptCompiler/Syntax/SyntaxToken.cs b/TaffyScript.Compiler/Syntax/SyntaxToken.cs similarity index 97% rename from TaffyScriptCompiler/Syntax/SyntaxToken.cs rename to TaffyScript.Compiler/Syntax/SyntaxToken.cs index db36a8f..7432853 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxToken.cs +++ b/TaffyScript.Compiler/Syntax/SyntaxToken.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { public abstract class SyntaxToken : ISyntaxToken { diff --git a/TaffyScriptCompiler/Syntax/SyntaxTree.cs b/TaffyScript.Compiler/Syntax/SyntaxTree.cs similarity index 96% rename from TaffyScriptCompiler/Syntax/SyntaxTree.cs rename to TaffyScript.Compiler/Syntax/SyntaxTree.cs index 24b218e..ab2812c 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxTree.cs +++ b/TaffyScript.Compiler/Syntax/SyntaxTree.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler.Syntax +namespace TaffyScript.Compiler.Syntax { /// /// Default implementation of a syntax tree. diff --git a/TaffyScriptCompiler/Syntax/SyntaxType.cs b/TaffyScript.Compiler/Syntax/SyntaxType.cs similarity index 96% rename from TaffyScriptCompiler/Syntax/SyntaxType.cs rename to TaffyScript.Compiler/Syntax/SyntaxType.cs index 5e4fcd9..865a642 100644 --- a/TaffyScriptCompiler/Syntax/SyntaxType.cs +++ b/TaffyScript.Compiler/Syntax/SyntaxType.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScriptCompiler +namespace TaffyScript.Compiler { public enum SyntaxType { diff --git a/TaffyScriptCompiler/Syntax/SyntaxType.cs.bak b/TaffyScript.Compiler/Syntax/SyntaxType.cs.bak similarity index 100% rename from TaffyScriptCompiler/Syntax/SyntaxType.cs.bak rename to TaffyScript.Compiler/Syntax/SyntaxType.cs.bak diff --git a/TaffyScriptCompiler/TaffyScriptCompiler.csproj b/TaffyScript.Compiler/TaffyScript.Compiler.csproj similarity index 97% rename from TaffyScriptCompiler/TaffyScriptCompiler.csproj rename to TaffyScript.Compiler/TaffyScript.Compiler.csproj index c90f73b..333453b 100644 --- a/TaffyScriptCompiler/TaffyScriptCompiler.csproj +++ b/TaffyScript.Compiler/TaffyScript.Compiler.csproj @@ -5,9 +5,9 @@ Debug AnyCPU {4022F406-FCE6-4A8D-B99F-6EF6C406248A} - Exe - TaffyScriptCompiler - tsc + Library + TaffyScript.Compiler + TaffyScript.Compiler v4.5.2 512 true @@ -47,6 +47,9 @@ prompt 4 + + + @@ -82,6 +85,7 @@ + @@ -148,7 +152,6 @@ - diff --git a/TaffyScriptCompiler/packages.config b/TaffyScript.Compiler/packages.config similarity index 100% rename from TaffyScriptCompiler/packages.config rename to TaffyScript.Compiler/packages.config diff --git a/TaffyScript.sln b/TaffyScript.sln index 501fe04..6007640 100644 --- a/TaffyScript.sln +++ b/TaffyScript.sln @@ -5,16 +5,10 @@ VisualStudioVersion = 15.0.27205.2004 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaffyScript", "TaffyScript\TaffyScript.csproj", "{68399D06-20DF-4CE8-9920-BD82DF2B8F69}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaffyScriptCompiler", "TaffyScriptCompiler\TaffyScriptCompiler.csproj", "{4022F406-FCE6-4A8D-B99F-6EF6C406248A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaffyScript.Compiler", "TaffyScript.Compiler\TaffyScript.Compiler.csproj", "{4022F406-FCE6-4A8D-B99F-6EF6C406248A}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{72AE5BB0-7F7F-440D-B6F3-285D2BB6AE36}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Moddable", "Moddable", "{C1D06C64-8F79-4F33-9D02-0769F22546B9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moddable", "Samples\Moddable\Moddable\Moddable.csproj", "{C3E9CCDE-C338-42BD-8F87-03699FE0DC08}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModdableExtern", "Samples\Moddable\ModdableExtern\ModdableExtern.csproj", "{A4B77AD8-18D2-41C4-8B0F-FDF39E2EBC32}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Threading", "Threading", "{17440014-AC44-4587-B789-DAA19E97867F}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaffyScript.Threading", "Samples\Threading\TaffyScript.Threading\TaffyScript.Threading.csproj", "{3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}" @@ -23,68 +17,83 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestSuite", "TestSuite", "{ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaffyScript.Tests", "Samples\TestSuite\TaffyScript.Tests\TaffyScript.Tests.csproj", "{0C33B274-4C13-4F74-9A4C-83C3ADB82408}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaffyScript.CommandLine", "TaffyScript.CommandLine\TaffyScript.CommandLine.csproj", "{FF4BC25B-646A-4849-BFC1-4731CEC9D456}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {68399D06-20DF-4CE8-9920-BD82DF2B8F69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {68399D06-20DF-4CE8-9920-BD82DF2B8F69}.Debug|Any CPU.Build.0 = Debug|Any CPU + {68399D06-20DF-4CE8-9920-BD82DF2B8F69}.Debug|x64.ActiveCfg = Debug|Any CPU + {68399D06-20DF-4CE8-9920-BD82DF2B8F69}.Debug|x64.Build.0 = Debug|Any CPU {68399D06-20DF-4CE8-9920-BD82DF2B8F69}.Debug|x86.ActiveCfg = Debug|Any CPU {68399D06-20DF-4CE8-9920-BD82DF2B8F69}.Debug|x86.Build.0 = Debug|Any CPU {68399D06-20DF-4CE8-9920-BD82DF2B8F69}.Release|Any CPU.ActiveCfg = Release|Any CPU {68399D06-20DF-4CE8-9920-BD82DF2B8F69}.Release|Any CPU.Build.0 = Release|Any CPU + {68399D06-20DF-4CE8-9920-BD82DF2B8F69}.Release|x64.ActiveCfg = Release|Any CPU + {68399D06-20DF-4CE8-9920-BD82DF2B8F69}.Release|x64.Build.0 = Release|Any CPU {68399D06-20DF-4CE8-9920-BD82DF2B8F69}.Release|x86.ActiveCfg = Release|Any CPU {68399D06-20DF-4CE8-9920-BD82DF2B8F69}.Release|x86.Build.0 = Release|Any CPU {4022F406-FCE6-4A8D-B99F-6EF6C406248A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4022F406-FCE6-4A8D-B99F-6EF6C406248A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4022F406-FCE6-4A8D-B99F-6EF6C406248A}.Debug|x64.ActiveCfg = Debug|Any CPU + {4022F406-FCE6-4A8D-B99F-6EF6C406248A}.Debug|x64.Build.0 = Debug|Any CPU {4022F406-FCE6-4A8D-B99F-6EF6C406248A}.Debug|x86.ActiveCfg = Debug|Any CPU {4022F406-FCE6-4A8D-B99F-6EF6C406248A}.Debug|x86.Build.0 = Debug|Any CPU {4022F406-FCE6-4A8D-B99F-6EF6C406248A}.Release|Any CPU.ActiveCfg = Release|Any CPU {4022F406-FCE6-4A8D-B99F-6EF6C406248A}.Release|Any CPU.Build.0 = Release|Any CPU + {4022F406-FCE6-4A8D-B99F-6EF6C406248A}.Release|x64.ActiveCfg = Release|Any CPU + {4022F406-FCE6-4A8D-B99F-6EF6C406248A}.Release|x64.Build.0 = Release|Any CPU {4022F406-FCE6-4A8D-B99F-6EF6C406248A}.Release|x86.ActiveCfg = Release|Any CPU {4022F406-FCE6-4A8D-B99F-6EF6C406248A}.Release|x86.Build.0 = Release|Any CPU - {C3E9CCDE-C338-42BD-8F87-03699FE0DC08}.Debug|Any CPU.ActiveCfg = Debug|x86 - {C3E9CCDE-C338-42BD-8F87-03699FE0DC08}.Debug|x86.ActiveCfg = Debug|x86 - {C3E9CCDE-C338-42BD-8F87-03699FE0DC08}.Debug|x86.Build.0 = Debug|x86 - {C3E9CCDE-C338-42BD-8F87-03699FE0DC08}.Release|Any CPU.ActiveCfg = Release|x86 - {C3E9CCDE-C338-42BD-8F87-03699FE0DC08}.Release|x86.ActiveCfg = Release|x86 - {C3E9CCDE-C338-42BD-8F87-03699FE0DC08}.Release|x86.Build.0 = Release|x86 - {A4B77AD8-18D2-41C4-8B0F-FDF39E2EBC32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A4B77AD8-18D2-41C4-8B0F-FDF39E2EBC32}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A4B77AD8-18D2-41C4-8B0F-FDF39E2EBC32}.Debug|x86.ActiveCfg = Debug|Any CPU - {A4B77AD8-18D2-41C4-8B0F-FDF39E2EBC32}.Debug|x86.Build.0 = Debug|Any CPU - {A4B77AD8-18D2-41C4-8B0F-FDF39E2EBC32}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A4B77AD8-18D2-41C4-8B0F-FDF39E2EBC32}.Release|Any CPU.Build.0 = Release|Any CPU - {A4B77AD8-18D2-41C4-8B0F-FDF39E2EBC32}.Release|x86.ActiveCfg = Release|Any CPU - {A4B77AD8-18D2-41C4-8B0F-FDF39E2EBC32}.Release|x86.Build.0 = Release|Any CPU {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}.Debug|x64.ActiveCfg = Debug|Any CPU + {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}.Debug|x64.Build.0 = Debug|Any CPU {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}.Debug|x86.ActiveCfg = Debug|Any CPU {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}.Debug|x86.Build.0 = Debug|Any CPU {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}.Release|Any CPU.ActiveCfg = Release|Any CPU {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}.Release|Any CPU.Build.0 = Release|Any CPU + {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}.Release|x64.ActiveCfg = Release|Any CPU + {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}.Release|x64.Build.0 = Release|Any CPU {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}.Release|x86.ActiveCfg = Release|Any CPU {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4}.Release|x86.Build.0 = Release|Any CPU {0C33B274-4C13-4F74-9A4C-83C3ADB82408}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0C33B274-4C13-4F74-9A4C-83C3ADB82408}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C33B274-4C13-4F74-9A4C-83C3ADB82408}.Debug|x64.ActiveCfg = Debug|Any CPU + {0C33B274-4C13-4F74-9A4C-83C3ADB82408}.Debug|x64.Build.0 = Debug|Any CPU {0C33B274-4C13-4F74-9A4C-83C3ADB82408}.Debug|x86.ActiveCfg = Debug|Any CPU {0C33B274-4C13-4F74-9A4C-83C3ADB82408}.Debug|x86.Build.0 = Debug|Any CPU {0C33B274-4C13-4F74-9A4C-83C3ADB82408}.Release|Any CPU.ActiveCfg = Release|Any CPU {0C33B274-4C13-4F74-9A4C-83C3ADB82408}.Release|Any CPU.Build.0 = Release|Any CPU + {0C33B274-4C13-4F74-9A4C-83C3ADB82408}.Release|x64.ActiveCfg = Release|Any CPU + {0C33B274-4C13-4F74-9A4C-83C3ADB82408}.Release|x64.Build.0 = Release|Any CPU {0C33B274-4C13-4F74-9A4C-83C3ADB82408}.Release|x86.ActiveCfg = Release|Any CPU {0C33B274-4C13-4F74-9A4C-83C3ADB82408}.Release|x86.Build.0 = Release|Any CPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456}.Debug|x64.ActiveCfg = Debug|Any CPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456}.Debug|x64.Build.0 = Debug|Any CPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456}.Debug|x86.ActiveCfg = Debug|Any CPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456}.Debug|x86.Build.0 = Debug|Any CPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456}.Release|Any CPU.Build.0 = Release|Any CPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456}.Release|x64.ActiveCfg = Release|Any CPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456}.Release|x64.Build.0 = Release|Any CPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456}.Release|x86.ActiveCfg = Release|Any CPU + {FF4BC25B-646A-4849-BFC1-4731CEC9D456}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {C1D06C64-8F79-4F33-9D02-0769F22546B9} = {72AE5BB0-7F7F-440D-B6F3-285D2BB6AE36} - {C3E9CCDE-C338-42BD-8F87-03699FE0DC08} = {C1D06C64-8F79-4F33-9D02-0769F22546B9} - {A4B77AD8-18D2-41C4-8B0F-FDF39E2EBC32} = {C1D06C64-8F79-4F33-9D02-0769F22546B9} {17440014-AC44-4587-B789-DAA19E97867F} = {72AE5BB0-7F7F-440D-B6F3-285D2BB6AE36} {3D25DE02-F1A9-47E0-B570-1DCF3882D7D4} = {17440014-AC44-4587-B789-DAA19E97867F} {975D9075-A453-42F9-914E-845D3181A1E9} = {72AE5BB0-7F7F-440D-B6F3-285D2BB6AE36} From 02ee71d14fbded956191234ae59ca78a48b2d088 Mon Sep 17 00:00:00 2001 From: mystborn Date: Mon, 14 May 2018 12:00:26 -0700 Subject: [PATCH 27/54] Restructure Part 2 --- TaffyScript.CommandLine/ErrorLogger.cs | 12 +- TaffyScript.CommandLine/Program.cs | 16 +- .../TaffyScript.CommandLine.csproj | 2 +- TaffyScript.Compiler/Backend/Builder.cs | 34 +-- .../Backend/{Compiler => }/CompileMode.cs | 0 .../Backend/{ => Compiler}/Closure.cs | 0 .../Backend/{ => Compiler}/ILEmitter.cs | 0 .../Backend/Compiler/MsilWeakCodeGen.cs | 262 ++++++++---------- .../Backend/Compiler/MsilWeakCompiler.cs | 47 ++-- .../Backend/{Compiler => }/CompilerResult.cs | 17 +- .../TsTypes.cs} | 0 ...ibrary.cs => BaseClassLibraryGenerator.cs} | 4 +- .../Front End/LexicalAnalysis/Tokenizer.cs | 16 +- TaffyScript.Compiler/Front End/Parser.cs | 67 ++--- TaffyScript.Compiler/IErrorLogger.cs | 2 + .../TaffyScript.Compiler.csproj | 16 +- TaffyScript.Compiler/packages.config | 4 - 17 files changed, 248 insertions(+), 251 deletions(-) rename TaffyScript.Compiler/Backend/{Compiler => }/CompileMode.cs (100%) rename TaffyScript.Compiler/Backend/{ => Compiler}/Closure.cs (100%) rename TaffyScript.Compiler/Backend/{ => Compiler}/ILEmitter.cs (100%) rename TaffyScript.Compiler/Backend/{Compiler => }/CompilerResult.cs (62%) rename TaffyScript.Compiler/{DotNet/TaffyScriptTypes.cs => Backend/TsTypes.cs} (100%) rename TaffyScript.Compiler/{Backend/BaseClassLibrary.cs => BaseClassLibraryGenerator.cs} (98%) delete mode 100644 TaffyScript.Compiler/packages.config diff --git a/TaffyScript.CommandLine/ErrorLogger.cs b/TaffyScript.CommandLine/ErrorLogger.cs index 8906493..678691b 100644 --- a/TaffyScript.CommandLine/ErrorLogger.cs +++ b/TaffyScript.CommandLine/ErrorLogger.cs @@ -7,11 +7,16 @@ namespace TaffyScript.CommandLine { - public class CommandLineLogger : IErrorLogger + public class ErrorLogger : IErrorLogger { public List Errors { get; } = new List(); public List Warnings { get; } = new List(); + public void Error(string message) + { + Errors.Add(message); + } + public void Error(string message, TokenPosition position) { if(position != null) @@ -31,6 +36,11 @@ public void Error(string message, TokenPosition position) Errors.Add(message); } + public void Warning(string message) + { + Warnings.Add(message); + } + public void Warning(string message, TokenPosition position) { if (position != null) diff --git a/TaffyScript.CommandLine/Program.cs b/TaffyScript.CommandLine/Program.cs index d679125..118baec 100644 --- a/TaffyScript.CommandLine/Program.cs +++ b/TaffyScript.CommandLine/Program.cs @@ -37,7 +37,9 @@ static void Main(string[] args) Console.WriteLine("Compile Start..."); - var compiler = new MsilWeakCompiler(); + var logger = new ErrorLogger(); + + var compiler = new MsilWeakCompiler(logger); CompilerResult result; if (!generateBcl) @@ -45,10 +47,18 @@ static void Main(string[] args) result = compiler.CompileProject(path); } else - result = compiler.CompileCode(BaseClassLibrary.Generate(), new BuildConfig() { Mode = CompileMode.Release, Output = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "Libraries", "TaffyScript.BCL") }); + result = compiler.CompileCode(BaseClassLibraryGenerator.Generate(), new BuildConfig() { Mode = CompileMode.Release, Output = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "Libraries", "TaffyScript.BCL") }); if (result.Errors.Count == 0) { + if(result.Warnings.Count > 0) + { + Console.WriteLine("Warnings:\n"); + foreach (var warning in result.Warnings) + Console.WriteLine(warning); + Console.WriteLine('\n'); + } + Console.WriteLine("Compile succeeded..."); Console.WriteLine($"Output: {result.PathToAssembly}"); if (run && result.PathToAssembly.EndsWith(".exe")) @@ -62,7 +72,7 @@ static void Main(string[] args) Console.WriteLine("Compile failed..."); Console.WriteLine("Errors: \n"); foreach (var error in result.Errors) - Console.WriteLine(error.Message); + Console.WriteLine(error); } } diff --git a/TaffyScript.CommandLine/TaffyScript.CommandLine.csproj b/TaffyScript.CommandLine/TaffyScript.CommandLine.csproj index 6e6dc00..b4fcc17 100644 --- a/TaffyScript.CommandLine/TaffyScript.CommandLine.csproj +++ b/TaffyScript.CommandLine/TaffyScript.CommandLine.csproj @@ -54,7 +54,7 @@ - + {4022f406-fce6-4a8d-b99f-6ef6c406248a} TaffyScript.Compiler diff --git a/TaffyScript.Compiler/Backend/Builder.cs b/TaffyScript.Compiler/Backend/Builder.cs index 16f3b53..e655db1 100644 --- a/TaffyScript.Compiler/Backend/Builder.cs +++ b/TaffyScript.Compiler/Backend/Builder.cs @@ -13,22 +13,29 @@ namespace TaffyScript.Compiler.Backend /// public abstract class Builder { + protected IErrorLogger _logger; + public abstract CompilerResult CompileCode(string code, BuildConfig config); public abstract CompilerResult CompileCode(string code, string output); public abstract CompilerResult CompileProject(string projectDir); - protected BuildConfig GetBuildConfig(string projectDir, out Exception exception) + public Builder(IErrorLogger errorLogger) + { + _logger = errorLogger; + } + + protected BuildConfig GetBuildConfig(string projectDir) { if (!Directory.Exists(projectDir)) { - exception = new DirectoryNotFoundException($"Could not find the project directory {projectDir}"); + _logger.Error($"Could not find the project directory {projectDir}", null); return null; } var projectFile = Path.Combine(projectDir, "build.cfg"); if (!File.Exists(Path.Combine(projectDir, "build.cfg"))) { - exception = new FileNotFoundException("Could not find the project file."); + _logger.Error("Could not find build.cfg", null); return null; } @@ -40,15 +47,12 @@ protected BuildConfig GetBuildConfig(string projectDir, out Exception exception) { config = (BuildConfig)cereal.Deserialize(sr); } - catch(Exception e) + catch { - exception = e; + _logger.Error("Could not deserialize build.cfg. Make sure the file is properly formatted.", null); return null; } } - - exception = null; - return config; } @@ -74,9 +78,8 @@ protected void ParseFilesInProjectDirectory(string directory, Parser parser, Has ParseFilesInProjectDirectory(dir, parser, exclude); } - protected List VerifyReferencesExists(string projectDir, string outputDir, BuildConfig config) + protected void VerifyReferencesExists(string projectDir, string outputDir, BuildConfig config) { - var errors = new List(); for (var i = 0; i < config.References.Count; i++) { var find = Path.Combine(projectDir, config.References[i]); @@ -85,7 +88,7 @@ protected List VerifyReferencesExists(string projectDir, string outpu { find = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), "Libraries", config.References[i]); if (!File.Exists(find)) - errors.Add(new FileNotFoundException($"Could not find the specified reference: {config.References[i]}")); + _logger.Error($"Could not find the specified reference: {config.References[i]}", null); else CopyFileIfNewer(find, output); } @@ -93,10 +96,9 @@ protected List VerifyReferencesExists(string projectDir, string outpu CopyFileIfNewer(find, output); config.References[i] = find; } - return errors; } - protected List VerifyReferencesExists(string projectDir, Action onReference, BuildConfig config) + protected void VerifyReferencesExists(string projectDir, Action onReference, BuildConfig config) { //Todo: Look for assemblies in the global assembly cache //Update: After some tinkering, it seems this is not easily achieved. @@ -123,8 +125,7 @@ protected List VerifyReferencesExists(string projectDir, Action(); + for(var i = 0; i < config.References.Count; i++) { var asmExpectedLocation = Path.Combine(projectDir, config.References[i]); @@ -132,14 +133,13 @@ protected List VerifyReferencesExists(string projectDir, Action /// Row=Namespace, Col=MethodName, Value=MethodInfo @@ -64,16 +65,6 @@ internal partial class MsilWeakCodeGen : ISyntaxElementVisitor private readonly BindingFlags _methodFlags = BindingFlags.Public | BindingFlags.Static; private readonly Dictionary _baseTypes = new Dictionary(); - /// - /// Keeps a list of any errors encountered during the compile. - /// - private List _errors = new List(); - - /// - /// Keeps a list of any warnings the compiler generates. - /// - private List _warnings = new List(); - /// /// Used to memoize unary operaters. /// @@ -206,8 +197,9 @@ private ILEmitter Initializer /// /// The symbols defined for this code generator. /// The build config used when creating the final assembly. - public MsilWeakCodeGen(SymbolTable table, BuildConfig config) + public MsilWeakCodeGen(SymbolTable table, BuildConfig config, IErrorLogger errorLogger) { + _logger = errorLogger; _table = table; _isDebug = config.Mode == CompileMode.Debug; _asmName = new AssemblyName(System.IO.Path.GetFileName(config.Output)); @@ -294,14 +286,14 @@ public CompilerResult CompileTree(ISyntaxTree tree) } catch(Exception e) { - _errors.Add(new CompileException($"The compiler encountered an error. Please report it.\n Exception: {e}")); + _logger.Error($"The compiler encountered an error. Please report it.\n Exception: {e}"); } foreach (var pending in _pendingMethods) - _errors.Add(new CompileException($"Could not find function {pending.Key} {pending.Value}")); + _logger.Error($"Could not find function {pending.Key}", pending.Value); - if (_errors.Count != 0) - return new CompilerResult(_errors); + if (_logger.Errors.Count != 0) + return new CompilerResult(_logger); Initializer.Ret(); @@ -327,7 +319,7 @@ public CompilerResult CompileTree(ISyntaxTree tree) _stream = null; } - return new CompilerResult(_asm, System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), _asmName.Name + output)); + return new CompilerResult(_asm, System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), _asmName.Name + output), _logger); } #endregion @@ -474,12 +466,12 @@ private MethodBuilder StartMethod(string name, string ns) { var m = result as MethodBuilder; if (m == null) - _errors.Add(new NameConflictException($"Function with name {name} is already defined by {m?.GetModule().ToString() ?? ""}")); + _logger.Error($"Function with name {name} is already defined by {m?.GetModule().ToString() ?? ""}"); return m; } if (!_table.Defined(name, out var symbol) || symbol.Type != SymbolType.Script) { - _errors.Add(new CompileException($"Tried to call an undefined function: {name}")); + _logger.Error($"Tried to call an undefined function: {name}"); return null; } var mb = GetBaseType(GetAssetNamespace(symbol)).DefineMethod(name, MethodAttributes.Public | MethodAttributes.Static, typeof(TsObject), ScriptArgs); @@ -543,7 +535,7 @@ private void GenerateWeakMethodForImport(MethodInfo method, string importName) else if (TsTypes.Constructors.TryGetValue(method.ReturnType, out var ctor)) emit.New(ctor); else if (method.ReturnType != typeof(TsObject)) - _errors.Add(new InvalidProgramException($"Imported method {importName} had an invalid return type {method.ReturnType}.")); + _logger.Error($"Imported method {importName} had an invalid return type {method.ReturnType}."); emit.Ret(); var name = $"{_namespace}.{importName}".TrimStart('.'); @@ -685,12 +677,12 @@ private MethodInfo GetOperator(string op, Type type, TokenPosition pos) else if (!_operators.TryGetValue(op, out name)) { //This doesn't specify a token position, but it also should never be encountered. - _errors.Add(new CompileException($"Operator {op} does not exist {pos}.")); + _logger.Error($"Operator {op} does not exist", pos); return null; } method = type.GetMethod(name, _methodFlags, null, new[] { type }, null); if (method == null) - _errors.Add(new CompileException($"No operator function is defined for the operator {op} and the type {type} {pos}.")); + _logger.Error($"No operator function is defined for the operator {op} and the type {type}", pos); } return method; } @@ -714,8 +706,7 @@ private MethodInfo GetOperator(string op, Type left, Type right, TokenPosition p { if (!_operators.TryGetValue(op, out var opName)) { - //This doesn't specify a token position, but it also should never be encountered. - _errors.Add(new CompileException($"Operator {op} does not exist {pos}.")); + _logger.Error($"Operator {op} does not exist", pos); return null; } @@ -723,7 +714,7 @@ private MethodInfo GetOperator(string op, Type left, Type right, TokenPosition p method = left.GetMethod(opName, _methodFlags, null, argTypes, null) ?? right.GetMethod(opName, _methodFlags, null, argTypes, null); if (method == null) - _errors.Add(new CompileException($"No operator function is defined for the operator {op} and the types {left} and {right} {pos}.")); + _logger.Error($"No operator function is defined for the operator {op} and the types {left} and {right}", pos); } return method; @@ -785,7 +776,7 @@ private void CallInstanceMethod(MethodInfo method, TokenPosition pos) else if (top == typeof(TsObject).MakePointerType()) emit.Call(method); else - _errors.Add(new CompileException($"Something went wrong {pos}")); + _logger.Error("Invalid syntax detected.", pos); } /// @@ -960,7 +951,7 @@ private ISyntaxElement ResolveNamespace(MemberAccessNode node) if (node.Left is ISyntaxToken left) ns.Push(left); else - _errors.Add(new CompileException($"Invalid syntax detected {node.Left.Position}")); + _logger.Error("Invalid syntax detected", node.Left.Position); var sb = new System.Text.StringBuilder(); var iterations = 0; @@ -1014,7 +1005,7 @@ private bool TryResolveNamespace(MemberAccessNode node, out ISyntaxElement resol if (node.Left is ISyntaxToken left) ns.Push(left); else - _errors.Add(new CompileException($"Invalid syntax detected {node.Left.Position}")); + _logger.Error("Invalid syntax detected", node.Left.Position); var sb = new System.Text.StringBuilder(); var iterations = 0; @@ -1063,7 +1054,7 @@ private void CopyTable(SymbolTable src, SymbolTable dest, TokenPosition position foreach (var symbol in src.Symbols) { if (!dest.AddChild(symbol)) - _warnings.Add($"Encountered name conflict {position}"); + _logger.Warning($"Encountered name conflict: {symbol.Name}", position); } } @@ -1080,7 +1071,7 @@ private void AcceptDeclarations(ISyntaxNode block) foreach(var child in block.Children) { if (!_declarationTypes.Contains(child.Type)) - _errors.Add(new CompileException($"Encountered invalid declaration {child.Position}")); + _logger.Error($"Encountered invalid declaration {child.Position}"); else child.Accept(this); } @@ -1120,13 +1111,6 @@ private void ConvertTopToObject(ILEmitter emitter) } } - private void LogError(Exception exception, bool loadEmptyObject = true) - { - _errors.Add(exception); - if (loadEmptyObject) - emit.Call(TsTypes.Empty); - } - #endregion #region Visitor @@ -1159,14 +1143,14 @@ public void Visit(AdditiveNode additive) } else if (right == typeof(string)) { - LogError(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}"), false); + _logger.Error($"Cannot {additive.Text} types {left} and {right}", additive.Position); return; } else if (right == typeof(TsObject)) emit.Call(GetOperator(additive.Text, left, right, additive.Position)); else { - LogError(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}"), false); + _logger.Error($"Cannot {additive.Text} types {left} and {right}", additive.Position); return; } } @@ -1174,12 +1158,12 @@ public void Visit(AdditiveNode additive) { if (additive.Text != "+") { - LogError(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}"), false); + _logger.Error($"Cannot {additive.Text} types {left} and {right}", additive.Position); return; } if (right == typeof(float)) { - LogError(new CompileException($"Cannot {additive.Text} types {left} and {right} {additive.Position}"), false); + _logger.Error($"Cannot {additive.Text} types {left} and {right}", additive.Position); return; } else if(right == typeof(string)) @@ -1205,7 +1189,7 @@ public void Visit(ArgumentAccessNode argumentAccess) { emit.Pop() .Call(TsTypes.Empty); - LogError(new CompileException($"Invalid argument access {argumentAccess.Position}"), false); + _logger.Error("Invalid argument access", argumentAccess.Position); return; } @@ -1232,7 +1216,7 @@ public void Visit(ArrayAccessNode arrayAccess) } else if (top != typeof(TsObject).MakePointerType()) { - LogError(new CompileException($"Encountered invalid syntax {arrayAccess.Position}"), false); + _logger.Error("Encountered invalid syntax", arrayAccess.Position); return; } @@ -1380,7 +1364,7 @@ public void Visit(AssignNode assign) } else if (top != typeof(TsObject).MakePointerType()) { - LogError(new CompileException($"Encountered invalid syntax {array.Position}"), false); + _logger.Error("Encountered invalid syntax", array.Position); return; } @@ -1463,16 +1447,16 @@ public void Visit(AssignNode assign) if (_table.Defined(variable.Text, out var symbol)) { var leaf = symbol as VariableLeaf; - if(leaf is null) - _errors.Add(new CompileException($"Cannot assign to the value {symbol.Name} {variable.Position}")); - - if(leaf.IsCaptured) + if (leaf is null) + _logger.Error($"Cannot assign to the value {symbol.Name}", variable.Position); + + if (leaf.IsCaptured) emit.LdLocal(_closure.Self); assign.Right.Accept(this); ConvertTopToObject(); - if(leaf.IsCaptured) + if (leaf.IsCaptured) emit.StFld(_closure.Fields[leaf.Name]); else emit.StLocal(_locals[symbol]); @@ -1504,7 +1488,7 @@ public void Visit(AssignNode assign) emit.Call(typeof(TsInstance).GetMethod("get_Other")); break; default: - _errors.Add(new CompileException($"Cannot access member on non-global readonly value {token.Position}")); + _logger.Error($"Cannot access member on readonly value {token.Text}", token.Position); return; } emit.LdStr(right.Text); @@ -1513,7 +1497,7 @@ public void Visit(AssignNode assign) emit.Call(typeof(ITsInstance).GetMethod("set_Item")); } else - _errors.Add(new CompileException($"Cannot access readonly value from global {member.Right.Position}")); + _logger.Error("Cannot access readonly value from global", member.Right.Position); } else { @@ -1527,7 +1511,7 @@ public void Visit(AssignNode assign) FreeLocal(secret); } else if (top != typeof(TsObject).MakePointerType()) - _errors.Add(new CompileException($"Invalid syntax detected {member.Left.Position}")); + _logger.Error("Invalid syntax detected", member.Left.Position); emit.LdStr(member.Right.Text); assign.Right.Accept(this); @@ -1539,9 +1523,9 @@ public void Visit(AssignNode assign) } var argTypes = new[] { typeof(string), top }; var assignMethod = typeof(TsObject).GetMethod("MemberSet", argTypes); - if(assignMethod == null) + if (assignMethod == null) { - _errors.Add(new CompileException($"Invalid syntax detected {assign.Right.Position}")); + _logger.Error("Invalid syntax detected", assign.Right.Position); emit.Call(TsTypes.Empty); } else @@ -1549,7 +1533,8 @@ public void Visit(AssignNode assign) } } else - _errors.Add(new CompileException($"This assignment is not yet supported {assign.Position}")); + //Todo: This should never be hit. Consider removing it. + _logger.Error("This type of assignment is not yet supported", assign.Position); } private void ProcessAssignExtra(AssignNode assign) @@ -1581,7 +1566,7 @@ private void ProcessAssignExtra(AssignNode assign) } else if (top != typeof(TsObject).MakePointerType()) { - LogError(new CompileException($"Encountered invalid syntax {array.Position}"), false); + _logger.Error("Invalid syntax detected", array.Position); return; } @@ -1723,7 +1708,7 @@ private void ProcessAssignExtra(AssignNode assign) if (_table.Defined(variable.Text, out var symbol)) { if (symbol.Type != SymbolType.Variable) - _errors.Add(new CompileException($"Cannot assign to the value {symbol.Name} {variable.Position}")); + _logger.Error($"Cannot assign to the value {symbol.Name}", variable.Position); GetAddressIfPossible(assign.Left); emit.Dup() .LdObj(typeof(TsObject)); @@ -1747,7 +1732,7 @@ private void ProcessAssignExtra(AssignNode assign) { if(!(member.Right is VariableToken value)) { - _errors.Add(new CompileException($"Cannot assign to readonly value {member.Right.Position}")); + _logger.Error($"Cannot assign to readonly value {member.Right.Text}", member.Right.Position); return; } if(member.Left is ReadOnlyToken read) @@ -1814,7 +1799,7 @@ public void Visit(BitwiseNode bitwise) { var leftConst = bitwise.Left as IConstantToken; if (leftConst == null) - _errors.Add(new CompileException($"Cannot perform operator {bitwise.Text} on the constant type {(bitwise.Left as IConstantToken).ConstantType} {bitwise.Position}")); + _logger.Error($"Cannot perform operator {bitwise.Text} on the constant type {(bitwise.Left as IConstantToken).ConstantType}", bitwise.Position); else emit.LdLong((long)leftConst.Value); } @@ -1823,15 +1808,15 @@ public void Visit(BitwiseNode bitwise) GetAddressIfPossible(bitwise.Left); var top = emit.GetTop(); if (top != typeof(TsObject) && top != typeof(TsObject).MakePointerType()) - _errors.Add(new CompileException($"Cannot perform operator {bitwise.Text} on the type {emit.GetTop()} {bitwise.Position}")); - emit.Call(TsTypes.ObjectCasts[typeof(long)]); + _logger.Error($"Cannot perform operator {bitwise.Text} on the type {emit.GetTop()}", bitwise.Position); + CallInstanceMethod(TsTypes.ObjectCasts[typeof(long)], bitwise.Left.Position); } if(bitwise.Right.Type == SyntaxType.Constant) { var rightConst = bitwise.Right as IConstantToken; - if(rightConst == null) - _errors.Add(new CompileException($"Cannot perform operator {bitwise.Text} on the constant type {(bitwise.Right as IConstantToken).ConstantType} {bitwise.Position}")); + if (rightConst == null) + _logger.Error($"Cannot perform operator {bitwise.Text} on the constant type {(bitwise.Right as IConstantToken).ConstantType}", bitwise.Position); else emit.LdLong((long)rightConst.Value); } @@ -1840,7 +1825,7 @@ public void Visit(BitwiseNode bitwise) GetAddressIfPossible(bitwise.Right); var top = emit.GetTop(); if (top != typeof(TsObject) && top != typeof(TsObject).MakePointerType()) - _errors.Add(new CompileException($"Cannot perform operator {bitwise.Text} on the type {top} {bitwise.Position}")); + _logger.Error($"Cannot perform operator {bitwise.Text} on the type {top}", bitwise.Position); emit.Call(TsTypes.ObjectCasts[typeof(long)]); } @@ -1857,7 +1842,7 @@ public void Visit(BitwiseNode bitwise) break; default: //Should be impossible. - _errors.Add(new CompileException($"Invalid bitwise operator detected: {bitwise.Text} {bitwise.Position}")); + _logger.Error($"Invalid bitwise operator detected: {bitwise.Text}", bitwise.Position); break; } emit.ConvertFloat(); @@ -1883,7 +1868,7 @@ public void Visit(CaseNode caseNode) { //Due to the way that a switch statements logic gets seperated, the SwitchNode implements //the logic for both Default and CaseNodes. - _errors.Add(new CompileException($"Encountered invalid program {caseNode.Position}")); + _logger.Error($"Encountered invalid program", caseNode.Position); } public void Visit(ConditionalNode conditionalNode) @@ -1894,8 +1879,8 @@ public void Visit(ConditionalNode conditionalNode) CallInstanceMethod(TsTypes.ObjectCasts[typeof(bool)], conditionalNode.Test.Position); else if (top == typeof(float)) emit.ConvertInt(false); - else if(top != typeof(bool)) - _errors.Add(new CompileException($"Detected invalid syntax {conditionalNode.Test.Position}")); + else if (top != typeof(bool)) + _logger.Error("Detected invalid syntax", conditionalNode.Test.Position); var brFalse = emit.DefineLabel(); var brFinal = emit.DefineLabel(); emit.BrFalse(brFalse); @@ -1949,14 +1934,14 @@ public void Visit(DeclareNode declare) .StLocal(local); } else - _errors.Add(new NameConflictException($"Tried to overwrite the symbol {symbol} {declare.Position}")); + _logger.Error($"Tried to overwrite the symbol {symbol}", declare.Position); } public void Visit(DefaultNode defaultNode) { //Due to the way that a switch statements logic gets seperated, the SwitchNode implements //the logic for both Default and CaseNodes. - _errors.Add(new CompileException($"Encountered invalid program {defaultNode.Position}")); + _logger.Error($"Encountered invalid program", defaultNode.Position); } public void Visit(DoNode doNode) @@ -2008,10 +1993,10 @@ public void Visit(EnumNode enumNode) if (expr.Children[0] is IConstantToken value) current = (long)value.Value; else - _errors.Add(new InvalidSymbolException($"Enum value must be equal to an integer constant {expr.Position}.")); + _logger.Error("Enum value must be equal to an integer constant", expr.Position); } else if (expr.Type != SyntaxType.Declare) - _errors.Add(new CompileException($"Encountered error while compiling enum {enumNode.Text} {expr.Position}.")); + _logger.Error($"Encountered error while compiling enum {enumNode.Text}", expr.Position); _enums[name, expr.Text] = current; type.DefineLiteral(expr.Text, current++); @@ -2063,7 +2048,7 @@ private void TestEquality(string op, Type left, Type right, TokenPosition pos) else if (right == typeof(TsObject)) emit.Call(GetOperator(op, left, right, pos)); else - _errors.Add(new CompileException($"Cannot {op} types {left} and {right} {pos}")); + _logger.Error($"Cannot {op} types {left} and {right}", pos); } else if (left == typeof(string)) { @@ -2079,12 +2064,12 @@ private void TestEquality(string op, Type left, Type right, TokenPosition pos) else if (right == typeof(string) || right == typeof(TsObject)) emit.Call(GetOperator(op, left, right, pos)); else - _errors.Add(new CompileException($"Cannot {op} types {left} and {right} {pos}")); + _logger.Error($"Cannot {op} types {left} and {right}", pos); } else if (left == typeof(TsObject)) emit.Call(GetOperator(op, left, right, pos)); else - _errors.Add(new CompileException($"Cannot {op} types {left} and {right} {pos}")); + _logger.Error($"Cannot {op} types {left} and {right}", pos); } public void Visit(ExitToken exitToken) @@ -2153,7 +2138,7 @@ public void Visit(FunctionCallNode functionCall) name = (memberAccess.Right as VariableToken)?.Text; if (name == null) { - _errors.Add(new CompileException($"Invalid id for script/event {memberAccess.Right.Position}")); + _logger.Error("Invalid id for script/event", memberAccess.Right.Position); emit.Call(TsTypes.Empty); return; } @@ -2176,7 +2161,7 @@ public void Visit(FunctionCallNode functionCall) } else if(emit.GetTop() != typeof(TsObject).MakePointerType()) { - _errors.Add(new CompileException($"Invalid syntax detected {functionCall.Children[0].Position}")); + _logger.Error("Invalid syntax detected", functionCall.Children[0].Position); emit.Call(TsTypes.Empty); return; } @@ -2202,7 +2187,7 @@ public void Visit(FunctionCallNode functionCall) } else if (symbol.Type != SymbolType.Script) { - _errors.Add(new CompileException($"Tried to call something that wasn't a script. Check for name conflict {functionCall.Position}")); + _logger.Error("Tried to call something that wasn't a script. Check for name conflict", functionCall.Position); emit.Call(TsTypes.Empty); return; } @@ -2280,7 +2265,7 @@ private void CallEvent(string name, bool loadId, FunctionCallNode functionCall, CallInstanceMethod(TsTypes.ObjectCasts[typeof(ITsInstance)], start); else if (!typeof(ITsInstance).IsAssignableFrom(top)) { - _errors.Add(new CompileException($"Internal Compile Exception encountered {start}")); + _logger.Error("Invalid syntax detected", start); emit.Call(TsTypes.Empty); return; } @@ -2330,7 +2315,7 @@ public void Visit(ImportNode import) for (var i = 0; i < args.Length; i++) { if (!TsTypes.BasicTypes.TryGetValue(argWrappers[i].Value, out var argType)) - _errors.Add(new CompileException($"Could not import the function {internalName} because one of the arguments was invalid {argWrappers[i].Value} {argWrappers[i].Position}")); + _logger.Error($"Could not import the function {internalName} because one of the arguments was invalid {argWrappers[i].Value}", argWrappers[i].Position); args[i] = argType; } @@ -2341,7 +2326,7 @@ public void Visit(ImportNode import) var method = GetMethodToImport(owner, methodName, args); if(method == null) { - _errors.Add(new CompileException($"Failed to find the import function {externalName} {import.ExternalName.Position}")); + _logger.Error($"Failed to find the import function {externalName}", import.ExternalName.Position); StartMethod(methodName, _namespace); return; } @@ -2371,7 +2356,7 @@ public void Visit(ImportNode import) } else { - _warnings.Add($"Could not directly import method with the WeakMethod attribute: {method} {import.Position}\nPlease check the method signature."); + _logger.Warning($"Could not directly import method with the WeakMethod attribute: {method}. Please check the method signature.\n ", import.Position); GenerateWeakMethodForImport(method, internalName); } } @@ -2397,7 +2382,7 @@ private void LoadElementAsInt(ISyntaxElement element) } else { - _errors.Add(new CompileException($"Invalid syntax detected {element.Position}")); + _logger.Error("Invalid syntax detected", element.Position); emit.LdInt(0); } } @@ -2493,7 +2478,7 @@ public void Visit(LogicalNode logical) else if (left == typeof(TsObject) || left == typeof(TsObject).MakePointerType()) CallInstanceMethod(TsTypes.ObjectCasts[typeof(bool)], logical.Left.Position); else if (left != typeof(bool)) - _errors.Add(new CompileException($"Encountered invalid syntax {logical.Left.Position}")); + _logger.Error("Encountered invalid syntax", logical.Left.Position); if (logical.Text == "&&") { emit.Dup() @@ -2516,7 +2501,7 @@ public void Visit(LogicalNode logical) else if (right == typeof(TsObject) || right == typeof(TsObject).MakePointerType()) CallInstanceMethod(TsTypes.ObjectCasts[typeof(bool)], logical.Right.Position); else if (right != typeof(bool)) - _errors.Add(new CompileException($"Encountered invalid syntax {logical.Right.Position}")); + _logger.Error("Encountered invalid syntax", logical.Right.Position); emit.MarkLabel(end); } @@ -2540,30 +2525,29 @@ public void Visit(MemberAccessNode memberAccess) { if (memberAccess.Right is VariableToken enumValue) { + // Todo: refactor Visit(EnumNode) to match this implementation. if (!_enums.TryGetValue(enumVar.Text, enumValue.Text, out var value)) { var node = (SymbolNode)_table.Defined(enumVar.Text); - //_table.Enter(enumVar.Text); if (node.Children.TryGetValue(enumValue.Text, out symbol) && symbol is EnumLeaf leaf) { value = leaf.Value; _enums[enumVar.Text, leaf.Name] = value; } else - _errors.Add(new CompileException($"The enum {enumVar.Text} does not declare value {enumValue.Text} {enumValue.Position}")); - //_table.Exit(); + _logger.Error($"The enum {enumVar.Text} does not declare value {enumValue.Text}", enumValue.Position); } emit.LdFloat(value); } else - _errors.Add(new CompileException($"Invalid enum access syntax {enumVar.Position}")); + _logger.Error("Invalid enum access", enumVar.Position); } else if(memberAccess.Left is ReadOnlyToken read) { if (_resolveNamespace != "" || !(memberAccess.Right is VariableToken right)) { UnresolveNamespace(); - _errors.Add(new CompileException($"Invalid syntax detected {read.Position}")); + _logger.Error("Invalid syntax detected", read.Position); emit.Call(TsTypes.Empty); return; } @@ -2579,7 +2563,7 @@ public void Visit(MemberAccessNode memberAccess) emit.Call(typeof(TsInstance).GetMethod("get_Other")); break; default: - _errors.Add(new CompileException($"Invalid syntax detected {right.Position}")); + _logger.Error("Invalid syntax detected", right.Position); emit.Call(TsTypes.Empty); return; } @@ -2591,7 +2575,7 @@ public void Visit(MemberAccessNode memberAccess) if (_resolveNamespace != "") { UnresolveNamespace(); - _errors.Add(new CompileException($"Invalid syntax detected {memberAccess.Left}")); + _logger.Error("Invalid syntax detected", memberAccess.Left.Position); emit.Call(TsTypes.Empty); return; } @@ -2607,7 +2591,7 @@ public void Visit(MemberAccessNode memberAccess) } else if(left != typeof(TsObject).MakePointerType()) { - _errors.Add(new NotImplementedException($"Accessing a variable through a type is not yet supported {memberAccess.Left} {memberAccess.Left.Position}")); + _logger.Error($"Static member access is not yet supported.", memberAccess.Left.Position); emit.Call(TsTypes.Empty); return; } @@ -2621,14 +2605,14 @@ public void Visit(MemberAccessNode memberAccess) { if (readOnly.Text != "self") { - _errors.Add(new NotImplementedException($"Only the read only variables id and self can be accessed from an instance currently {readOnly.Position}")); + _logger.Error("Only the read only variables id and self can be accessed from an instance currently", readOnly.Position); emit.Call(TsTypes.Empty); return; } emit.Call(typeof(TsObject).GetMethod("GetInstance")); } else - _errors.Add(new CompileException($"Invalid syntax detected {memberAccess.Position}")); + _logger.Error("Invalid syntax detected", memberAccess.Position); } UnresolveNamespace(); @@ -2670,15 +2654,14 @@ public void Visit(MultiplicativeNode multiplicative) } } else if (right == typeof(string)) - _errors.Add(new CompileException($"Cannot {multiplicative.Text} types {left} and {right} {multiplicative.Position}")); + _logger.Error($"Cannot {multiplicative.Text} types {left} and {right}", multiplicative.Position); else if (right == typeof(TsObject)) emit.Call(GetOperator(multiplicative.Text, left, right, multiplicative.Position)); else - _errors.Add(new CompileException($"Cannot {multiplicative.Text} types {left} and {right} {multiplicative.Position}")); - } - else if (left == typeof(string)) { - _errors.Add(new CompileException($"Cannot {multiplicative.Text} types {left} and {right} {multiplicative.Position}")); + _logger.Error($"Cannot {multiplicative.Text} types {left} and {right}", multiplicative.Position); } + else if (left == typeof(string)) + _logger.Error($"Cannot {multiplicative.Text} types {left} and {right}", multiplicative.Position); else if (left == typeof(TsObject)) emit.Call(GetOperator(multiplicative.Text, left, right, multiplicative.Position)); } @@ -2756,13 +2739,13 @@ public void Visit(NewNode newNode) } else { - _errors.Add(new CompileException($"Tried to create an instance of something that wasn't an object: {newNode.Text} {newNode.Position}")); + _logger.Error($"Tried to create an instance of something that wasn't an object: {newNode.Text}", newNode.Position); emit.Call(TsTypes.Empty); } } else { - _errors.Add(new CompileException($"Tried to create an instance of a type that doesn't exist: {newNode.Text} {newNode.Position}")); + _logger.Error($"Tried to create an instance of a type that doesn't exist: {newNode.Text}", newNode.Position); emit.Call(TsTypes.Empty); } } @@ -2776,14 +2759,14 @@ public void Visit(ObjectNode objectNode) _table.Enter(objectNode.Text); var parentNode = objectNode.Inherits as IConstantToken; if (parentNode == null) - _errors.Add(new CompileException($"Invalid syntax detected {objectNode.Inherits.Position}")); + _logger.Error("Invalid syntax detected", objectNode.Inherits.Position); string parent = null; if(parentNode.Value != null && _table.Defined(parentNode.Value, out var symbol)) { if (symbol.Type == SymbolType.Object) parent = $"{GetAssetNamespace(symbol)}.{symbol.Name}".TrimStart('.'); else - _errors.Add(new CompileException($"Tried to inherit from non object identifier {objectNode.Inherits.Position}")); + _logger.Error("Tried to inherit from non object identifier", objectNode.Inherits.Position); } var addMethod = typeof(LookupTable).GetMethod("Add", new[] { typeof(string), typeof(string), typeof(TsDelegate) }); @@ -2869,7 +2852,7 @@ public void Visit(PostfixNode postfix) .LdLocal(secret); FreeLocal(secret); } - else if(postfix.Child.Type == SyntaxType.ArrayAccess) + else if (postfix.Child.Type == SyntaxType.ArrayAccess) { var value = GetLocal(); var result = GetLocal(); @@ -2886,11 +2869,11 @@ public void Visit(PostfixNode postfix) } else if (top != typeof(TsObject).MakePointerType()) { - _errors.Add(new CompileException($"Encountered invalid syntax {array.Position}")); + _logger.Error("Encountered invalid syntax", array.Position); emit.Call(TsTypes.Empty); return; } - + var secret = GetLocal(typeof(ITsInstance)); if (CanBeArrayAccess(array)) @@ -3034,7 +3017,7 @@ public void Visit(PostfixNode postfix) if (_table.Defined(variable.Text, out var symbol)) { if (symbol.Type != SymbolType.Variable) - _errors.Add(new CompileException($"Cannot perform {postfix.Text} on an identifier that is not a variable {postfix.Position}")); + _logger.Error($"Cannot perform {postfix.Text} on an identifier that is not a variable", postfix.Position); GetAddressIfPossible(variable); emit.Dup() .Dup() @@ -3063,7 +3046,7 @@ public void Visit(PostfixNode postfix) var value = member.Right as VariableToken; if (value is null) { - _errors.Add(new CompileException($"Invalid member access {member.Position}")); + _logger.Error("Invalid member access", member.Position); emit.Call(TsTypes.Empty); return; } @@ -3103,7 +3086,7 @@ public void Visit(PostfixNode postfix) FreeLocal(secret); } else - _errors.Add(new CompileException($"Invalid syntax detected {postfix.Child.Position}")); + _logger.Error("Invalid syntax detected", postfix.Child.Position); } private Func GetReadOnlyLoadFunc(ReadOnlyToken read) @@ -3151,7 +3134,7 @@ public void Visit(PrefixNode prefix) } else if (top != typeof(TsObject).MakePointerType()) { - _errors.Add(new CompileException($"Encountered invalid syntax {array.Position}")); + _logger.Error("Invalid syntax detected", array.Position); emit.Call(TsTypes.Empty); return; } @@ -3291,7 +3274,7 @@ public void Visit(PrefixNode prefix) if (_table.Defined(variable.Text, out var symbol)) { if (symbol.Type != SymbolType.Variable) - _errors.Add(new CompileException($"Tried to access an identifier that wasn't a variable {prefix.Child.Position}")); + _logger.Error("Tried to access an identifier that wasn't a variable", prefix.Child.Position); variable.Accept(this); emit.Call(GetOperator(prefix.Text, typeof(TsObject), prefix.Position)) .StLocal(_locals[symbol]) @@ -3314,7 +3297,7 @@ public void Visit(PrefixNode prefix) { if (!(member.Right is VariableToken value)) { - _errors.Add(new CompileException($"Cannot assign to readonly value {member.Right.Position}")); + _logger.Error("Cannot assign to readonly value", member.Right.Position); emit.Call(TsTypes.Empty); return; } @@ -3356,7 +3339,7 @@ public void Visit(PrefixNode prefix) FreeLocal(secret); } else - _errors.Add(new CompileException($"Invalid syntax detected {prefix.Position}")); + _logger.Error("Invalid syntax detected", prefix.Position); } else { @@ -3412,7 +3395,7 @@ public void Visit(ReadOnlyToken readOnlyToken) emit.LdFloat(-4f); break; default: - _errors.Add(new NotImplementedException($"Currently the readonly value {readOnlyToken.Text} is not implemented {readOnlyToken.Position}")); + _logger.Error($"Currently the readonly value {readOnlyToken.Text} is not implemented", readOnlyToken.Position); break; } } @@ -3466,7 +3449,7 @@ public void Visit(RelationalNode relational) emit.Cge(); break; default: - _errors.Add(new CompileException($"Cannot {relational.Text} types {left} and {right} {relational.Position}")); + _logger.Error($"Cannot {relational.Text} types {left} and {right}", relational.Position); break; } } @@ -3476,7 +3459,7 @@ public void Visit(RelationalNode relational) else if (left == typeof(TsObject)) emit.Call(GetOperator(relational.Text, left, right, relational.Position)); else - _errors.Add(new CompileException($"Invalid syntax detected {relational.Position}")); + _logger.Error("Invalid syntax detected", relational.Position); return; } @@ -3502,7 +3485,7 @@ public void Visit(RepeatNode repeat) else if (top == typeof(float)) emit.Clt(); else - _errors.Add(new CompileException($"Invalid syntax detected {repeat.Condition.Position}")); + _logger.Error("Invalid syntax detected", repeat.Body.Position); emit.BrFalse(end); repeat.Body.Accept(this); emit.LdLocal(secret) @@ -3517,10 +3500,11 @@ public void Visit(RepeatNode repeat) public void Visit(ReturnNode returnNode) { + // Todo: Allow return by itself. returnNode.ReturnValue.Accept(this); if (!emit.TryGetTop(out var returnType)) - _errors.Add(new CompileException($"Tried to return without a return value. If this is expected, use exit instead {returnNode.Position}")); + _logger.Error("Tried to return without a return value. If this is expected, use exit instead", returnNode.Position); ConvertTopToObject(); @@ -3597,7 +3581,7 @@ private void ProcessScriptArguments(ScriptNode script) left = (VariableToken)assign.Left; if (!_table.Defined(left.Text, out var symbol)) { - _errors.Add(new CompileException($"Unknown exception occurred {left.Position}")); + _logger.Error("Unknown exception occurred", left.Position); continue; } var leaf = symbol as VariableLeaf; @@ -3657,7 +3641,7 @@ private void ProcessScriptArguments(ScriptNode script) { if(!_table.Defined(variable.Text, out var symbol)) { - _errors.Add(new CompileException($"Unknown exception occurred {variable.Position}")); + _logger.Error("Unknown exception occurred", variable.Position); continue; } emit.Dup() @@ -3681,7 +3665,7 @@ public void Visit(ShiftNode shift) left = typeof(long); } else if (left == typeof(string)) - _errors.Add(new CompileException($"Tried to shift a string {shift.Left.Position}")); + _logger.Error("Tried to shift a string", shift.Left.Position); GetAddressIfPossible(shift.Right); var right = emit.GetTop(); if (right == typeof(float)) @@ -3689,13 +3673,13 @@ public void Visit(ShiftNode shift) emit.ConvertInt(true); right = typeof(int); } - else if(right == typeof(TsObject) || right == typeof(TsObject).MakePointerType()) + else if (right == typeof(TsObject) || right == typeof(TsObject).MakePointerType()) { CallInstanceMethod(TsTypes.ObjectCasts[typeof(int)], shift.Right.Position); right = typeof(int); } else - _errors.Add(new CompileException($"Tried to shift a string {shift.Right.Position}")); + _logger.Error("Tried to shift a string", shift.Right.Position); if (left == typeof(long)) { @@ -3705,17 +3689,17 @@ public void Visit(ShiftNode shift) .ConvertFloat(); } else - _errors.Add(new CompileException($"Must shift by a real value {shift.Right.Position}")); + _logger.Error("Must shift by a real value", shift.Right.Position); } else if (left == typeof(TsObject)) { if (right == typeof(int)) emit.Call(GetOperator(shift.Text, left, right, shift.Position)); else - _errors.Add(new CompileException($"Must shift by a real value {shift.Right.Position}")); + _logger.Error("Must shift by a real value", shift.Right.Position); } else - _errors.Add(new CompileException($"Invalid syntax detected {shift.Position}")); + _logger.Error("Invalid syntax detected", shift.Position); } public void Visit(SwitchNode switchNode) @@ -3776,7 +3760,7 @@ public void Visit(SwitchNode switchNode) else if (cases[i] is DefaultNode defaultNode) defaultNode.Expressions.Accept(this); else - _errors.Add(new CompileException($"Invalid syntax detected {cases[i].Position}")); + _logger.Error("Invalid syntax detected", cases[i].Position); } emit.MarkLabel(end); @@ -3849,7 +3833,7 @@ public void Visit(VariableToken variableToken) else emit.LdLocal(local); } - else if(symbol is VariableLeaf leaf && leaf.IsCaptured) + else if (symbol is VariableLeaf leaf && leaf.IsCaptured) { var field = _closure.Fields[symbol.Name]; @@ -3864,10 +3848,10 @@ public void Visit(VariableToken variableToken) emit.LdFld(field); } else - _errors.Add(new CompileException($"Tried to reference a non-existant variable {variableToken.Text} {variableToken.Position}")); + _logger.Error($"Tried to reference a non-existant variable {variableToken.Text}", variableToken.Position); break; default: - _errors.Add(new NotImplementedException($"Currently cannot reference indentifier {symbol.Type} by it's raw value.")); + _logger.Error($"Currently cannot reference indentifier {symbol.Type} by it's raw value.", variableToken.Position); break; } } @@ -3901,7 +3885,7 @@ public void Visit(WithNode with) else if(!typeof(ITsInstance).IsAssignableFrom(top)) { emit.Pop(); - LogError(new CompileException($"Invalid target for with statement {with.Target.Position}"), false); + _logger.Error("Invalid target for with statement", with.Target.Position); return; } var other = GetLocal(typeof(ITsInstance)); @@ -3935,7 +3919,7 @@ public void Visit(ImportObjectNode importNode) var importType = _typeParser.GetType(importNode.Text); if (importType.IsAbstract || importType.IsEnum || !importType.IsClass) - _errors.Add(new CompileException($"Could not import the type {importType.Name}. Imported types must be concrete and currently must be a class.")); + _logger.Error($"Could not import the type {importType.Name}. Imported types must be concrete and currently must be a class.", importNode.Position); var ns = GetAssetNamespace(leaf); var name = $"{ns}.{importNode.ImportName.Value}".TrimStart('.'); @@ -3945,7 +3929,7 @@ public void Visit(ImportObjectNode importNode) var ctor = importType.GetConstructor(new[] { typeof(TsObject[]) }); if(ctor is null) { - LogError(new CompileException($"Could not import type that inherits from ITsInstance because it does not have a valid constructor: {importNode.Position}"), false); + _logger.Error($"Could not import type that inherits from ITsInstance because it does not have a valid constructor", importNode.Position); return; } @@ -4029,7 +4013,7 @@ public void Visit(ImportObjectNode importNode) var field = importType.GetMember(fld.ExternalName, MemberTypes.Field | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(); if(field == null) { - _errors.Add(new CompileException($"Could not find the Field or Property {fld.ExternalName} on the type {importType.Name} {fld.Position}")); + _logger.Error($"Could not find the Field or Property {fld.ExternalName} on the type {importType.Name}", fld.Position); continue; } switch(field) @@ -4051,7 +4035,7 @@ public void Visit(ImportObjectNode importNode) if (TsTypes.BasicTypes.TryGetValue(mthd.ArgumentTypes[i], out var argType)) args[i] = argType; else - _errors.Add(new CompileException($"Could not import the method {mthd.ExternalName} because one of the arguments was invalid {mthd.ArgumentTypes[i]} {mthd.Position}")); + _logger.Error($"Could not import the method {mthd.ExternalName} because one of the arguments was invalid {mthd.ArgumentTypes[i]}", mthd.Position); } var method = importType.GetMethod(mthd.ExternalName, BindingFlags.Public | BindingFlags.Instance, null, args, null); @@ -4065,12 +4049,12 @@ public void Visit(ImportObjectNode importNode) if (TsTypes.BasicTypes.TryGetValue(ctorArgNames[i], out var argType)) ctorArgs[i] = argType; else - _errors.Add(new CompileException($"Could not import the constructor for the type {name} because one of the arguments was invalid {ctorArgs[i]} {importNode.Constructor.Position}")); + _logger.Error($"Could not import the constructor for the type {name} because one of the arguments was invalid {ctorArgs[i]}", importNode.Constructor.Position); } var ctor = importType.GetConstructor(ctorArgs); if (ctor is null) - _errors.Add(new CompileException($"Could not find ctor on the type {name} with the arguments {string.Join(", ", ctorArgNames)}")); + _logger.Error($"Could not find ctor on the type {name} with the arguments {string.Join(", ", ctorArgNames)}", importNode.Constructor.Position); else AddConstructorToTypeWrapper(ctor, type, source, importNode.WeaklyTyped, leaf); } @@ -4167,7 +4151,7 @@ public void Visit(ImportObjectNode importNode) AddMethodToTypeWrapper(mi, weakFlags, type, transformName(mi.Name), importNode.Position, source, call, tryd, readOnly); if (!foundConstructor) - _errors.Add(new CompileException($"No valid constructor was found for the imported type {importType} {importNode.Position}")); + _logger.Error($"No valid constructor was found for the imported type {importType}", importNode.Position); } if (importNode.WeaklyTyped) @@ -4498,7 +4482,7 @@ private void AddMethodToTypeWrapper(MethodInfo method, else if (TsTypes.Constructors.TryGetValue(method.ReturnType, out var objCtor)) weak.New(objCtor); else if (method.ReturnType != typeof(TsObject)) - _errors.Add(new CompileException($"Imported method { method.Name } had an invalid return type { method.ReturnType}.")); + _logger.Error($"Imported method { method.Name } had an invalid return type {method.ReturnType}"); weak.Ret(); var next = call.DefineLabel(); diff --git a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCompiler.cs b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCompiler.cs index 2e65f29..454adef 100644 --- a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCompiler.cs +++ b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCompiler.cs @@ -9,7 +9,8 @@ namespace TaffyScript.Compiler.Backend { public class MsilWeakCompiler : Builder { - public MsilWeakCompiler() + public MsilWeakCompiler(IErrorLogger errorLogger) + : base(errorLogger) { } @@ -20,13 +21,15 @@ public MsilWeakCompiler() /// public override CompilerResult CompileProject(string projectDir) { - var config = GetBuildConfig(projectDir, out var exception); + var config = GetBuildConfig(projectDir); if(config == null) - return new CompilerResult(null, null, exception); + return new CompilerResult(_logger); if (string.IsNullOrEmpty(config.Output)) - return new CompilerResult(null, null, - new InvalidOperationException("The config file must conatin an output path.")); + { + _logger.Error("The config file must contain an output path.", null); + return new CompilerResult(_logger); + } var dir = Path.Combine(projectDir, Path.GetDirectoryName(config.Output)); Directory.CreateDirectory(dir); @@ -34,29 +37,29 @@ public override CompilerResult CompileProject(string projectDir) config.Output = Path.GetFileName(config.Output); var expectedOutput = Path.Combine(dir, config.Output); - var errors = VerifyReferencesExists(projectDir, dir, config); - if (errors.Count != 0) - return new CompilerResult(errors); + VerifyReferencesExists(projectDir, dir, config); + if (_logger.Errors.Count != 0) + return new CompilerResult(_logger); - var parser = new Parser(); + var parser = new Parser(_logger); ParseFilesInProjectDirectory(projectDir, parser, GetExcludeSet(projectDir, config)); - if(parser.Errors.Count != 0) - return new CompilerResult(parser.Errors); + if(_logger.Errors.Count != 0) + return new CompilerResult(_logger); - var generator = new MsilWeakCodeGen(parser.Table, config); + var generator = new MsilWeakCodeGen(parser.Table, config, _logger); var result = generator.CompileTree(parser.Tree); if (result.Errors.Count > 0) return result; else { expectedOutput += Path.GetExtension(result.PathToAssembly); - CopyFileIfNewer(typeof(TaffyScript.TsObject).Assembly.Location, Path.Combine(dir, typeof(TaffyScript.TsObject).Assembly.GetName().Name + ".dll")); + CopyFileIfNewer(typeof(TsObject).Assembly.Location, Path.Combine(dir, typeof(TsObject).Assembly.GetName().Name + ".dll")); if (result.PathToAssembly != expectedOutput) { if (File.Exists(expectedOutput)) File.Delete(expectedOutput); MoveFile(result.PathToAssembly, expectedOutput); - return new CompilerResult(result.CompiledAssebmly, expectedOutput, result.Errors.ToArray()); + return new CompilerResult(result.CompiledAssebmly, expectedOutput, _logger); } } return result; @@ -94,16 +97,16 @@ public override CompilerResult CompileCode(string code, BuildConfig config) var expectedOutput = Path.Combine(dir, config.Output); //var errors = new List(); - var errors = VerifyReferencesExists(GetType().Assembly.Location, dir, config); - if (errors.Count != 0) - return new CompilerResult(errors); + VerifyReferencesExists(GetType().Assembly.Location, dir, config); + if (_logger.Errors.Count != 0) + return new CompilerResult(_logger); - var parser = new Parser(); + var parser = new Parser(_logger); parser.Parse(code); - if (parser.Errors.Count != 0) - return new CompilerResult(parser.Errors); + if (_logger.Errors.Count != 0) + return new CompilerResult(_logger); - var generator = new MsilWeakCodeGen(parser.Table, config); + var generator = new MsilWeakCodeGen(parser.Table, config, _logger); var result = generator.CompileTree(parser.Tree); if (result.Errors.Count > 0) return result; @@ -114,7 +117,7 @@ public override CompilerResult CompileCode(string code, BuildConfig config) if (result.PathToAssembly != expectedOutput) { MoveFile(result.PathToAssembly, expectedOutput); - return new CompilerResult(result.CompiledAssebmly, expectedOutput, result.Errors.ToArray()); + return new CompilerResult(result.CompiledAssebmly, expectedOutput, _logger); } } return result; diff --git a/TaffyScript.Compiler/Backend/Compiler/CompilerResult.cs b/TaffyScript.Compiler/Backend/CompilerResult.cs similarity index 62% rename from TaffyScript.Compiler/Backend/Compiler/CompilerResult.cs rename to TaffyScript.Compiler/Backend/CompilerResult.cs index c1cbcfa..214b7b7 100644 --- a/TaffyScript.Compiler/Backend/Compiler/CompilerResult.cs +++ b/TaffyScript.Compiler/Backend/CompilerResult.cs @@ -17,25 +17,32 @@ public class CompilerResult /// /// If the compile failed, contains a list of the encountered errors. /// - public List Errors { get; } + public List Errors { get; } + + /// + /// Warnings that aren't breaking, but are generally considered bad practice. + /// + public List Warnings { get; } /// /// If the compile was successful, contains the path to the output assembly. /// public string PathToAssembly { get; } - public CompilerResult(Assembly asm, string path, params Exception[] errors) + public CompilerResult(Assembly asm, string path, IErrorLogger errorLogger) { CompiledAssebmly = asm; PathToAssembly = path; - Errors = errors == null ? new List() : new List(errors); + Errors = errorLogger.Errors; + Warnings = errorLogger.Warnings; } - public CompilerResult(IEnumerable errors) + public CompilerResult(IErrorLogger errorLogger) { CompiledAssebmly = null; PathToAssembly = null; - Errors = new List(errors); + Errors = errorLogger.Errors; + Warnings = errorLogger.Warnings; } } } diff --git a/TaffyScript.Compiler/DotNet/TaffyScriptTypes.cs b/TaffyScript.Compiler/Backend/TsTypes.cs similarity index 100% rename from TaffyScript.Compiler/DotNet/TaffyScriptTypes.cs rename to TaffyScript.Compiler/Backend/TsTypes.cs diff --git a/TaffyScript.Compiler/Backend/BaseClassLibrary.cs b/TaffyScript.Compiler/BaseClassLibraryGenerator.cs similarity index 98% rename from TaffyScript.Compiler/Backend/BaseClassLibrary.cs rename to TaffyScript.Compiler/BaseClassLibraryGenerator.cs index 5ce5f82..69ed8d3 100644 --- a/TaffyScript.Compiler/Backend/BaseClassLibrary.cs +++ b/TaffyScript.Compiler/BaseClassLibraryGenerator.cs @@ -4,12 +4,12 @@ using System.Text; using System.Threading.Tasks; -namespace TaffyScript.Compiler.Backend +namespace TaffyScript.Compiler { /// /// Helper class used to generate the BCL of TaffyScript. /// - public static class BaseClassLibrary + public static class BaseClassLibraryGenerator { /// /// Generates the TaffyScript base class library as a string. diff --git a/TaffyScript.Compiler/Front End/LexicalAnalysis/Tokenizer.cs b/TaffyScript.Compiler/Front End/LexicalAnalysis/Tokenizer.cs index 1eafedb..ce34573 100644 --- a/TaffyScript.Compiler/Front End/LexicalAnalysis/Tokenizer.cs +++ b/TaffyScript.Compiler/Front End/LexicalAnalysis/Tokenizer.cs @@ -16,6 +16,7 @@ public class Tokenizer : IDisposable private static Dictionary _definitions; private TextReader _reader; + private IErrorLogger _logger; private int _line = 1; private int _column; private int _index; @@ -29,17 +30,13 @@ public class Tokenizer : IDisposable /// public bool Finished => _current == '\0'; - /// - /// Gets invoked when an error occurs during the lexical analysis phase. - /// - public Action ErrorEncountered; - /// /// Creates a Tokenizer using a string as the input code. /// /// The code to convert into a stream of s. - public Tokenizer(string input) + public Tokenizer(string input, IErrorLogger errorLogger) { + _logger = errorLogger; _reader = new StringReader(input); Init(); } @@ -48,8 +45,9 @@ public Tokenizer(string input) /// Creates a Tokenizer using a as the input code. /// /// The code to convert into a stream of s. - public Tokenizer(FileStream stream) + public Tokenizer(FileStream stream, IErrorLogger errorLogger) { + _logger = errorLogger; _fname = stream.Name; _reader = new StreamReader(stream); Init(); @@ -308,7 +306,7 @@ private void Advance() _token = new Token(TokenType.Identifier, next, pos); break; default: - ErrorEncountered?.Invoke(new UnrecognizedTokenException(next[0], pos)); + _logger.Error("Encountered an unrecognized token: " + next[0], pos); break; } @@ -392,7 +390,7 @@ private string ReadNext() sb.Append(ReadHexNumber()); //There must be at least one character after the x in a hex number. if (sb.Length == 2) - ErrorEncountered?.Invoke(new UnrecognizedTokenException(_current, new TokenPosition(_index, _line, _column, _fname))); + _logger.Error("Encountered an unrecognized token: " + _current, new TokenPosition(_index, _line, _column, _fname)); return sb.ToString(); } else diff --git a/TaffyScript.Compiler/Front End/Parser.cs b/TaffyScript.Compiler/Front End/Parser.cs index 9da3bb2..15f6d13 100644 --- a/TaffyScript.Compiler/Front End/Parser.cs +++ b/TaffyScript.Compiler/Front End/Parser.cs @@ -41,13 +41,13 @@ private static HashSet HexCharacters public SymbolTable Table => _table; public ISyntaxTree Tree => _tree; - public List Errors { get; } = new List(); /// /// Creates a new TaffyScript parser. /// - public Parser() + public Parser(IErrorLogger errorLogger) { + _logger = errorLogger; _table = new SymbolTable(); _tree = new SyntaxTree(_table); _factory = new SyntaxElementFactory(); @@ -59,7 +59,7 @@ public Parser() /// The TaffyScript code to parse. public void Parse(string code) { - using (_stream = new Tokenizer(code)) + using (_stream = new Tokenizer(code, _logger)) { Parse(_tree.Root); } @@ -73,7 +73,7 @@ public void ParseFile(string file) { using (var fs = new System.IO.FileStream(file, System.IO.FileMode.Open)) { - using(_stream = new Tokenizer(fs)) + using(_stream = new Tokenizer(fs, _logger)) { Parse(_tree.Root); } @@ -84,7 +84,6 @@ private void Parse(ISyntaxNode root) { if (_stream.Finished) return; - _stream.ErrorEncountered += (e) => Errors.Add(e); root.AddChild(Usings()); } @@ -149,7 +148,7 @@ private ISyntaxElement Declaration() } catch(Exception e) { - Throw(e); + _logger.Error(e.Message, token.Position); return null; } AddDeclarations(ns); @@ -225,7 +224,7 @@ private ISyntaxElement Declaration() Confirm(TokenType.SemiColon); return null; default: - Throw(new InvalidTokenException(_stream.Peek(), $"Expected declaration, got {_stream.Read().Type}")); + _logger.Error($"Expected declaration, got {_stream.Peek().Type}", _stream.Read().Position); return null; } } @@ -277,7 +276,7 @@ private ISyntaxElement ImportObject(TokenPosition pos) if(Try(TokenType.New, out var newToken)) { if (hasCtor) - Throw(new InvalidTokenException(newToken, $"Import types can only define one constructor")); + _logger.Error($"Import types can only define one constructor", newToken.Position); var newNode = new ImportObjectConstructor(newToken.Position); Confirm(TokenType.OpenParen); if (!Try(TokenType.CloseParen)) @@ -289,7 +288,7 @@ private ISyntaxElement ImportObject(TokenPosition pos) if (type == "array") type = "array1d"; if (!TsTypes.BasicTypes.ContainsKey(type)) - Throw(new InvalidTokenException(token, $"Import type must be one of the following: {string.Join(", ", TsTypes.BasicTypes.Keys)}\n")); + _logger.Error($"Import type must be one of the following: {string.Join(", ", TsTypes.BasicTypes.Keys)}\n ", token.Position); else newNode.ArgumentTypes.Add(type); } @@ -325,7 +324,7 @@ private ISyntaxElement ImportObject(TokenPosition pos) if (type == "array") type = "array1d"; if (!TsTypes.BasicTypes.ContainsKey(type)) - Throw(new InvalidTokenException(token, $"Import type must be one of the following: {string.Join(", ", TsTypes.BasicTypes.Keys)}\n")); + _logger.Error($"Import type must be one of the following: {string.Join(", ", TsTypes.BasicTypes.Keys)}\n ", token.Position); else methodNode.ArgumentTypes.Add(type); } @@ -382,7 +381,7 @@ private ISyntaxElement ImportScript(TokenPosition pos) type = "array1d"; if (!TsTypes.BasicTypes.ContainsKey(type)) { - Throw(new InvalidTokenException(token, $"Import type must be one of the following: {string.Join(", ", TsTypes.BasicTypes.Keys)}\n")); + _logger.Error($"Import type must be one of the following: {string.Join(", ", TsTypes.BasicTypes.Keys)}\n ", token.Position); node.AddChild(null); } else @@ -403,7 +402,7 @@ private ISyntaxElement Script(SymbolScope scope) { if (!(Validate(TokenType.Script) || Validate(TokenType.Event))) { - Throw(new InvalidTokenException(_stream.Peek(), $"Expected a script, got {_stream.Read().Type}")); + _logger.Error($"Expected a script, got {_stream.Peek().Type}", _stream.Read().Position); return null; } @@ -445,7 +444,7 @@ private ISyntaxElement Script(SymbolScope scope) value = _factory.CreateToken(SyntaxType.ReadOnlyValue, read.Value, read.Position); break; default: - Throw(new InvalidTokenException(_stream.Peek(), "Optional arguments must have a constant value")); + _logger.Error("Optional arguments must have a constant value", _stream.Peek().Position); Validate(TokenType.Identifier); continue; } @@ -461,7 +460,7 @@ private ISyntaxElement Script(SymbolScope scope) else { if (optional) - Throw(new InvalidTokenException(parameterToken, "Can't have non-optional arguments after an optional argument.")); + _logger.Error("Can't have non-optional arguments after an optional argument.", parameterToken.Position); parameterElement = parameter; } @@ -487,7 +486,7 @@ private ISyntaxElement Statement() if (!_table.Defined(localName.Value, out var symbol)) _table.AddLeaf(localName.Value, SymbolType.Variable, SymbolScope.Local); else if (symbol.Type != SymbolType.Variable) - Throw(new InvalidTokenException(localName, $"Id already defined for higher priority type: {localName.Value} = {symbol.Type}")); + _logger.Error($"Id already defined for higher priority type: {localName.Value} = {symbol.Type}", localName.Position); if (Try(TokenType.Assign, out var equalToken)) { @@ -609,7 +608,7 @@ private ISyntaxElement SimpleStatement() temp.AddChild(_factory.CreateNode(SyntaxType.Block, next.Position)); Confirm(TokenType.SemiColon); if (Try(TokenType.SemiColon)) - Throw(new InvalidTokenException(_stream.Peek(), "Expected expression in for declaration")); + _logger.Error("Expected expression in for declaration", _stream.Peek().Position); else temp.AddChild(Expression()); Confirm(TokenType.SemiColon); @@ -638,7 +637,7 @@ private ISyntaxElement SimpleStatement() caseNode = _factory.CreateNode(SyntaxType.Default, defaultToken.Position); else { - Throw(new InvalidTokenException(_stream.Peek(), $"Expected case declaration, got {_stream.Read().Value}")); + _logger.Error($"Expected case declaration, got {_stream.Peek().Value}", _stream.Read().Position); continue; } var blockStart = Confirm(TokenType.Colon); @@ -943,15 +942,13 @@ private ISyntaxElement PrimaryExpression() else if (Try(TokenType.ReadOnly, out next)) { if (next.Value != "self") - { - Throw(new InvalidTokenException(next, "Invalid readonly token on the right side of an access expression")); - return null; - } + _logger.Error("Invalid readonly token on the right side of an access expression", next.Position); + temp.AddChild(_factory.CreateToken(SyntaxType.ReadOnlyValue, next.Value, next.Position)); } else { - Throw(new InvalidTokenException(next, "The value after a period in an access expression must be a variable.")); + _logger.Error("The value after a period in an access expression must be a variable.", next.Position); return null; } value = temp; @@ -959,10 +956,8 @@ private ISyntaxElement PrimaryExpression() else if (Try(TokenType.OpenBracket, out var accessToken)) { if (value.Type == SyntaxType.New) - { - Throw(new InvalidTokenException(accessToken, "Cannot use an accessor on a newed value")); - return value; - } + _logger.Error("Cannot use an accessor on a newed value", accessToken.Position); + ISyntaxNode access = _factory.CreateNode(SyntaxType.ArrayAccess, value.Position); access.AddChild(value); @@ -1055,7 +1050,7 @@ private ISyntaxElement PrimaryExpressionStart() } else { - Throw(new InvalidTokenException(_stream.Read())); + _logger.Error("Could not parse syntax", _stream.Read().Position); return null; } } @@ -1091,12 +1086,13 @@ private Token Confirm(TokenType next) { if (_stream.Finished) { - Throw(new System.IO.EndOfStreamException($"Expected {next}, reached the end of file instead.")); + //Todo: test if this works. + _logger.Error($"Expected {next}, reached the end of file instead.", _stream.Peek().Position); return null; } var result = _stream.Read(); if (result.Type != next) - Throw(new InvalidTokenException(result, $"Expected {next}, got {result.Type}")); + _logger.Error($"Expected {next}, got {result.Type}", result.Position); return result; } @@ -1123,7 +1119,7 @@ private ISyntaxToken Constant() else value = value.Trim('"'); var match = StringParser.Match(value); - while(match.Success) + while (match.Success) { switch (value[match.Index + 1]) { @@ -1135,14 +1131,14 @@ private ISyntaxToken Constant() if (num == "") { var errorPos = new TokenPosition(token.Position.Index, token.Position.Line, token.Position.Column + i, token.Position.File); - Throw(new InvalidOperationException($"Invalid hex constant {errorPos}")); + _logger.Error($"Invalid hex constant", errorPos); } num = num.PadLeft(4, '0'); byte[] hex = new byte[2]; hex[1] = (byte)int.Parse(num.Substring(0, 2), System.Globalization.NumberStyles.HexNumber); hex[0] = (byte)int.Parse(num.Substring(2, 2), System.Globalization.NumberStyles.HexNumber); Console.WriteLine($"{hex[0]}, {hex[1]}"); - if(i - match.Index != 6) + if (i - match.Index != 6) { if (value[i] == '\\') i++; @@ -1177,7 +1173,7 @@ private ISyntaxToken Constant() else if (Try(TokenType.Bool, out token)) return _factory.CreateConstant(ConstantType.Bool, token.Value, token.Position); else - Throw(new InvalidTokenException(_stream.Peek(), $"Expected literal, got {_stream.Peek().Type}")); + _logger.Error($"Expected literal, got {_stream.Peek().Type}", _stream.Read().Position); return null; } @@ -1236,11 +1232,6 @@ private bool IsAssignment() } } - private void Throw(Exception exception) - { - Errors.Add(exception); - } - private string GetNamespace() { var first = Confirm(TokenType.Identifier); diff --git a/TaffyScript.Compiler/IErrorLogger.cs b/TaffyScript.Compiler/IErrorLogger.cs index 90e1d37..b656000 100644 --- a/TaffyScript.Compiler/IErrorLogger.cs +++ b/TaffyScript.Compiler/IErrorLogger.cs @@ -10,7 +10,9 @@ public interface IErrorLogger { List Errors { get; } List Warnings { get; } + void Error(string message); void Error(string message, TokenPosition position); + void Warning(string message); void Warning(string message, TokenPosition position); } } diff --git a/TaffyScript.Compiler/TaffyScript.Compiler.csproj b/TaffyScript.Compiler/TaffyScript.Compiler.csproj index 333453b..fe46db0 100644 --- a/TaffyScript.Compiler/TaffyScript.Compiler.csproj +++ b/TaffyScript.Compiler/TaffyScript.Compiler.csproj @@ -52,9 +52,6 @@ - - ..\packages\NDesk.Options.0.2.1\lib\NDesk.Options.dll - @@ -65,21 +62,21 @@ - + - + - - + + - + - + @@ -168,7 +165,6 @@ - diff --git a/TaffyScript.Compiler/packages.config b/TaffyScript.Compiler/packages.config deleted file mode 100644 index cc315dc..0000000 --- a/TaffyScript.Compiler/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file From 2667bfe6c7d78d0941989717c3b71868b5afe137 Mon Sep 17 00:00:00 2001 From: mystborn Date: Thu, 17 May 2018 15:59:00 -0700 Subject: [PATCH 28/54] Better Block CodeGen + Hex Parser Fix --- .../Backend/Compiler/ILEmitter.cs | 1 + .../Backend/Compiler/MsilWeakCodeGen.cs | 23 ++++++++++++++++--- TaffyScript.Compiler/Front End/Parser.cs | 2 +- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/TaffyScript.Compiler/Backend/Compiler/ILEmitter.cs b/TaffyScript.Compiler/Backend/Compiler/ILEmitter.cs index c957b53..1f86a0d 100644 --- a/TaffyScript.Compiler/Backend/Compiler/ILEmitter.cs +++ b/TaffyScript.Compiler/Backend/Compiler/ILEmitter.cs @@ -32,6 +32,7 @@ public class ILEmitter private Type[] _paramTypes; public MethodBase Method { get; } + public Stack Types => _types; public ILEmitter(MethodBuilder builder, Type[] input) { diff --git a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs index f012848..8f41a12 100644 --- a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -1854,14 +1854,31 @@ public void Visit(BlockNode block) for (var i = 0; i < size; ++i) { block.Children[i].Accept(this); - if (block.Children[i].Type == SyntaxType.FunctionCall || block.Children[i].Type == SyntaxType.Postfix || block.Children[i].Type == SyntaxType.Prefix) - emit.Pop(); + //Each child in a block is either a statement which leaves nothing on the stack, + //or an expression which will leave one value. + //If there's a value left, pop it. + //If there's more than one value, the compiler failed somehow. + //It should never happen, but we log an error just in case. + switch(emit.Types.Count) + { + case 0: + break; + case 1: + emit.Pop(); + break; + default: + _logger.Error("Stack is unbalanced inside of a block", block.Position); + break; + } } } public void Visit(BreakToken breakToken) { - emit.Br(_loopEnd.Peek()); + if (_loopEnd.Count > 0) + emit.Br(_loopEnd.Peek()); + else + _logger.Error("Tried to break outside of a loop", breakToken.Position); } public void Visit(CaseNode caseNode) diff --git a/TaffyScript.Compiler/Front End/Parser.cs b/TaffyScript.Compiler/Front End/Parser.cs index 15f6d13..2db56b1 100644 --- a/TaffyScript.Compiler/Front End/Parser.cs +++ b/TaffyScript.Compiler/Front End/Parser.cs @@ -22,7 +22,7 @@ private static HashSet HexCharacters get { if(_hexCharacters == null) - _hexCharacters = new HashSet() { 'a', 'b', 'c', 'd', 'e', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' }; + _hexCharacters = new HashSet() { 'a', 'b', 'c', 'd', 'e', 'f', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' }; return _hexCharacters; } } From c2d9a5ebe93e51e1f7074dd95898d671012e6f95 Mon Sep 17 00:00:00 2001 From: mystborn Date: Thu, 17 May 2018 23:46:55 -0700 Subject: [PATCH 29/54] Improved SymbolTable --- Samples/TestSuite/Tests/lambda.tfs | 31 +- TaffyScript.CommandLine/Program.cs | 2 + .../Backend/Compiler/MsilWeakCodeGen.cs | 401 ++++++++---------- TaffyScript.Compiler/Symbols/SymbolTable.cs | 96 +++-- 4 files changed, 265 insertions(+), 265 deletions(-) diff --git a/Samples/TestSuite/Tests/lambda.tfs b/Samples/TestSuite/Tests/lambda.tfs index 5f6309c..da859a1 100644 --- a/Samples/TestSuite/Tests/lambda.tfs +++ b/Samples/TestSuite/Tests/lambda.tfs @@ -10,7 +10,10 @@ namespace LanguageTests { lambda_no_capture, lambda_capture_local, lambda_capture_argument, - lambda_capture_default_argument); + lambda_capture_default_argument + //lambda_local, + //lambda_nested_lambda + ); tests.run_tests(); } @@ -51,4 +54,30 @@ namespace LanguageTests { script scr_get_arg_capture_script(arg = 2) { return script { return arg; } } + + /*script lambda_local() { + test_it("lambda { var i = 0 }"); + var s = script { + var i = 1; + return i; + } + var result = s(); + assert_equal(result, 1); + } + + script lambda_nested_lambda() { + test_it("lambda { lambda {} }"); + var s = scr_get_nested_lambda(); + var result = s(); + assert_equal(result, 3); + } + + script scr_get_nested_lambda() { + return script { + var i = 2; + var f = script { i++; } + f(); + return i; + } + }*/ } \ No newline at end of file diff --git a/TaffyScript.CommandLine/Program.cs b/TaffyScript.CommandLine/Program.cs index 118baec..fe01e6e 100644 --- a/TaffyScript.CommandLine/Program.cs +++ b/TaffyScript.CommandLine/Program.cs @@ -27,6 +27,8 @@ static void Main(string[] args) if (extra.Count != 0) path = extra[0]; + path = @"C:\Users\Chris\Source\Repos\GmParser\Samples\TestSuite\Tests"; + if (generateBuild) { var build = new BuildConfig(); diff --git a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs index 8f41a12..efee74c 100644 --- a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -139,8 +139,6 @@ internal partial class MsilWeakCodeGen : ISyntaxElementVisitor /// private Dictionary> _secrets = new Dictionary>(); - private string _resolveNamespace = ""; - private LocalBuilder _argumentCount = null; private Closure _closure = null; @@ -341,7 +339,8 @@ private void ProcessWeakAssembly(Assembly asm) if (type.GetCustomAttribute() != null) { var count = _table.EnterNamespace(type.Namespace); - _table.TryCreate(type.Name, SymbolType.Object); + if (!_table.TryCreate(type.Name, SymbolType.Object)) + _logger.Warning($"Name conflict encountered with object {type.Name} defined in assembly {asm.GetName().Name}"); _table.Exit(count); } else if(type.IsEnum) @@ -829,13 +828,8 @@ private void ScriptStart(string scriptName, MethodBuilder method, Type[] args) { emit = new ILEmitter(method, args); _table.Enter(scriptName); - var locals = new List(_table.Symbols); - _table.Exit(); - foreach(var local in locals) + foreach(var local in _table.Symbols) { - //Raise local variables up one level. - _table.AddChild(local); - if (local is VariableLeaf leaf && leaf.IsCaptured) { if (_closure == null) @@ -852,8 +846,7 @@ private void ScriptStart(string scriptName, MethodBuilder method, Type[] args) private void ScriptEnd() { - foreach (var local in _locals.Keys) - _table.Undefine(local.Name); + _table.Exit(); _locals.Clear(); _secrets.Clear(); _secret = 0; @@ -926,65 +919,11 @@ private void FreeLocal(LocalBuilder local) locals.Push(local); } - private ISyntaxElement ResolveNamespace(MemberAccessNode node) - { - if (node.Left.Text != null && _table.Defined(node.Left.Text, out var symbol) && symbol.Type == SymbolType.Namespace) - { - _table.Enter(symbol.Name); - _resolveNamespace = symbol.Name; - return node.Right; - } - else if (node.Left is MemberAccessNode) - { - var ns = new Stack(); - var result = node.Right; - var start = node; - while (node.Left is MemberAccessNode member) - { - node = member; - if (node.Right is ISyntaxToken id) - ns.Push(id); - else - return start; - } - - if (node.Left is ISyntaxToken left) - ns.Push(left); - else - _logger.Error("Invalid syntax detected", node.Left.Position); - - var sb = new System.Text.StringBuilder(); - var iterations = 0; - while (ns.Count > 0) - { - var top = ns.Pop(); - sb.Append(top.Text); - sb.Append("."); - if (_table.Defined(top.Text, out symbol) && symbol.Type == SymbolType.Namespace) - { - _table.Enter(top.Text); - iterations++; - } - else - { - _table.Exit(iterations); - return start; - } - } - _resolveNamespace = sb.ToString().TrimEnd('.'); - return result; - } - else - return node; - } - - private bool TryResolveNamespace(MemberAccessNode node, out ISyntaxElement resolved) + private bool TryResolveNamespace(MemberAccessNode node, out ISyntaxElement resolved, out SymbolNode namespaceNode) { - resolved = default(ISyntaxElement); if (node.Left.Text != null && _table.Defined(node.Left.Text, out var symbol) && symbol.Type == SymbolType.Namespace) { - _table.Enter(symbol.Name); - _resolveNamespace = symbol.Name; + namespaceNode = (SymbolNode)symbol; resolved = node.Right; return true; } @@ -999,7 +938,10 @@ private bool TryResolveNamespace(MemberAccessNode node, out ISyntaxElement resol if (node.Right is ISyntaxToken id) ns.Push(id); else + { + namespaceNode = default(SymbolNode); return false; + } } if (node.Left is ISyntaxToken left) @@ -1021,23 +963,18 @@ private bool TryResolveNamespace(MemberAccessNode node, out ISyntaxElement resol } else { + namespaceNode = default(SymbolNode); _table.Exit(iterations); return false; } } - _resolveNamespace = sb.ToString().TrimEnd('.'); + namespaceNode = _table.Current; + _table.Exit(iterations); return true; } - else - return false; - } - - private void UnresolveNamespace() - { - if (_resolveNamespace == "") - return; - _table.ExitNamespace(_resolveNamespace); - _resolveNamespace = ""; + resolved = default(ISyntaxElement); + namespaceNode = default(SymbolNode); + return false; } private SymbolTable CopyTable(SymbolTable table) @@ -1049,23 +986,6 @@ private SymbolTable CopyTable(SymbolTable table) return copy; } - private void CopyTable(SymbolTable src, SymbolTable dest, TokenPosition position) - { - foreach (var symbol in src.Symbols) - { - if (!dest.AddChild(symbol)) - _logger.Warning($"Encountered name conflict: {symbol.Name}", position); - } - } - - private void TryCopyTable(SymbolTable src, SymbolTable dest) - { - foreach(var symbol in src.Symbols) - { - dest.AddChild(symbol); - } - } - private void AcceptDeclarations(ISyntaxNode block) { foreach(var child in block.Children) @@ -2141,11 +2061,22 @@ public void Visit(FunctionCallNode functionCall) name = token.Text; else if (nameElem is MemberAccessNode memberAccess) { - if (TryResolveNamespace(memberAccess, out nameElem)) + if (TryResolveNamespace(memberAccess, out nameElem, out var namespaceNode)) { //explicit namespace -> function call //e.g. name.space.func_name(); name = nameElem.Text; + if(namespaceNode.Children.TryGetValue(nameElem.Text, out var scriptSymbol)) + { + CallScript(GetAssetNamespace(scriptSymbol), scriptSymbol, functionCall); + return; + } + else + { + _logger.Error($"Namespace {(GetAssetNamespace(namespaceNode) + "." + namespaceNode.Name).TrimStart('.')} does not define script {nameElem}"); + emit.Call(TsTypes.Empty); + return; + } } else { @@ -2209,11 +2140,17 @@ public void Visit(FunctionCallNode functionCall) return; } var ns = GetAssetNamespace(symbol); - if (!_methods.TryGetValue(ns, name, out var method)) + + CallScript(ns, symbol, functionCall); + } + + private void CallScript(string ns, ISymbol scriptSymbol, FunctionCallNode functionCall) + { + if (!_methods.TryGetValue(ns, scriptSymbol.Name, out var method)) { // Special case hack needed for getting the MethodInfo for weak methods before // their ImportNode has been hit. - if (symbol is ImportLeaf leaf) + if (scriptSymbol is ImportLeaf leaf) { var temp = _namespace; _namespace = ns; @@ -2223,13 +2160,11 @@ public void Visit(FunctionCallNode functionCall) } else { - method = StartMethod(name, ns); - _pendingMethods.Add($"{ns}.{name}".TrimStart('.'), functionCall.Position); + method = StartMethod(scriptSymbol.Name, ns); + _pendingMethods.Add($"{ns}.{scriptSymbol.Name}".TrimStart('.'), functionCall.Position); } } - UnresolveNamespace(); - MarkSequencePoint(functionCall); //Load the target @@ -2525,46 +2460,48 @@ public void Visit(LogicalNode logical) public void Visit(MemberAccessNode memberAccess) { - var resolved = ResolveNamespace(memberAccess); - if(_resolveNamespace != "") + ISymbol enumSymbol; + if(TryResolveNamespace(memberAccess, out var resolved, out var namespaceNode)) { if (resolved is MemberAccessNode member) - memberAccess = member; - else { - resolved.Accept(this); - return; + if (member.Left is VariableToken enumType && namespaceNode.Children.TryGetValue(enumType.Text, out enumSymbol)) + ProcessEnumAccess(member, enumType, enumSymbol); + else + { + emit.Call(TsTypes.Empty); + _logger.Error("Invalid member access syntax. Expected enum at the end of namespace", member.Position); + } } - } - //If left is enum name, find it in _enums. - //Otherwise, Accept left, and call member access on right. - if (memberAccess.Left is VariableToken enumVar && _table.Defined(enumVar.Text, out var symbol) && symbol.Type == SymbolType.Enum) - { - if (memberAccess.Right is VariableToken enumValue) + else if (resolved is VariableToken variable) { - // Todo: refactor Visit(EnumNode) to match this implementation. - if (!_enums.TryGetValue(enumVar.Text, enumValue.Text, out var value)) + if (namespaceNode.Children.TryGetValue(variable.Text, out var symbol)) + ProcessVariableToken(variable, symbol); + else { - var node = (SymbolNode)_table.Defined(enumVar.Text); - if (node.Children.TryGetValue(enumValue.Text, out symbol) && symbol is EnumLeaf leaf) - { - value = leaf.Value; - _enums[enumVar.Text, leaf.Name] = value; - } - else - _logger.Error($"The enum {enumVar.Text} does not declare value {enumValue.Text}", enumValue.Position); + emit.Call(TsTypes.Empty); + _logger.Error("Invalid id at the end of namespace access", resolved.Position); } - emit.LdFloat(value); } else - _logger.Error("Invalid enum access", enumVar.Position); + { + emit.Call(TsTypes.Empty); + _logger.Error("Invalid token at the end of namespace access."); + } + return; + } + //If left is enum name, find it in _enums. + //Otherwise, Accept left, and call member access on right. + if (memberAccess.Left is VariableToken enumVar && _table.Defined(enumVar.Text, out enumSymbol) && enumSymbol.Type == SymbolType.Enum) + { + ProcessEnumAccess(memberAccess, enumVar, enumSymbol); } - else if(memberAccess.Left is ReadOnlyToken read) + if (memberAccess.Left is ReadOnlyToken read) { - if (_resolveNamespace != "" || !(memberAccess.Right is VariableToken right)) + var right = memberAccess.Right as VariableToken; + if(right is null) { - UnresolveNamespace(); - _logger.Error("Invalid syntax detected", read.Position); + _logger.Error("Could not access readonly variable from readonly variable."); emit.Call(TsTypes.Empty); return; } @@ -2589,14 +2526,6 @@ public void Visit(MemberAccessNode memberAccess) } else { - if (_resolveNamespace != "") - { - UnresolveNamespace(); - _logger.Error("Invalid syntax detected", memberAccess.Left.Position); - emit.Call(TsTypes.Empty); - return; - } - GetAddressIfPossible(memberAccess.Left); var left = emit.GetTop(); if(left == typeof(TsObject)) @@ -2631,8 +2560,31 @@ public void Visit(MemberAccessNode memberAccess) else _logger.Error("Invalid syntax detected", memberAccess.Position); } + } - UnresolveNamespace(); + private void ProcessEnumAccess(MemberAccessNode memberAccess, VariableToken enumType, ISymbol enumSymbol) + { + if (memberAccess.Right is VariableToken enumValue) + { + // Todo: refactor Visit(EnumNode) to match this implementation. + if (!_enums.TryGetValue(enumType.Text, enumValue.Text, out var value)) + { + var node = (SymbolNode)enumSymbol; + if (node.Children.TryGetValue(enumValue.Text, out enumSymbol) && enumSymbol is EnumLeaf leaf) + { + value = leaf.Value; + _enums[enumType.Text, leaf.Name] = value; + } + else + _logger.Error($"The enum {enumType.Text} does not declare value {enumValue.Text}", enumValue.Position); + } + emit.LdFloat(value); + } + else + { + _logger.Error("Invalid enum access", enumType.Position); + emit.LdFloat(0f); + } } public void Visit(MultiplicativeNode multiplicative) @@ -2686,18 +2638,24 @@ public void Visit(MultiplicativeNode multiplicative) public void Visit(NamespaceNode namespaceNode) { var parent = _namespace; - if (parent == "") - _namespace = namespaceNode.Text; - else + if(parent != "") + { + _table.AddSymbolToDefinitionLookup(_table.Current); _namespace += "." + namespaceNode.Text; - _table.EnterNamespace(namespaceNode.Text); - var temp = _table; - _table = CopyTable(_table); - temp.ExitNamespace(namespaceNode.Text); - CopyTable(temp, _table, namespaceNode.Position); + } + else + _namespace = namespaceNode.Text; + + var count = _table.EnterNamespace(namespaceNode.Text); + AcceptDeclarations(namespaceNode); + + _table.Exit(count); + + if (parent != "") + _table.RemoveSymbolFromDefinitionLookup(_table.Current); + _namespace = parent; - _table = temp; } public void Visit(NewNode newNode) @@ -3787,96 +3745,91 @@ public void Visit(SwitchNode switchNode) public void Visit(UsingsNode usings) { - var temp = _table; - _table = CopyTable(temp); - foreach (var ns in usings.Modules) - { - var count = temp.EnterNamespace(ns.Text); - CopyTable(temp, _table, ns.Position); - temp.Exit(count); - } + _table.AddNamespaceToDefinitionLookup(ns.Text); + AcceptDeclarations(usings.Declarations); - _table = temp; + _table.RemoveAllNamespacesFromDefinitionLookup(); } public void Visit(VariableToken variableToken) + { + if (_table.Defined(variableToken.Text, out var symbol)) + ProcessVariableToken(variableToken, symbol); + else + { + emit.LdArg(0 + _argOffset) + .LdStr(variableToken.Text) + .Call(typeof(ITsInstance).GetMethod("get_Item")); + } + } + + private void ProcessVariableToken(VariableToken variableToken, ISymbol variableSymbol) { var name = variableToken.Text; - if (_table.Defined(name, out var symbol)) + switch (variableSymbol.Type) { - switch(symbol.Type) - { - case SymbolType.Object: - UnresolveNamespace(); - var ns = GetAssetNamespace(symbol); - if (ns != "") - name = $"{ns}.{name}"; - emit.LdStr(name); - break; - case SymbolType.Script: - if (symbol.Scope == SymbolScope.Member) + case SymbolType.Object: + var ns = GetAssetNamespace(variableSymbol); + if (ns != "") + name = $"{ns}.{name}"; + emit.LdStr(name); + break; + case SymbolType.Script: + if (variableSymbol.Scope == SymbolScope.Member) + { + // Todo: Consider forcing this to load the exact function. + // That would make it so the function couldn't be changed during runtime, + // but of course it makes execution faster. + emit.LdArg(0 + _argOffset) + .LdStr(name) + .Call(typeof(ITsInstance).GetMethod("GetDelegate")) + .New(TsTypes.Constructors[typeof(TsDelegate)]); + } + else + { + ns = GetAssetNamespace(variableSymbol); + if (!_methods.TryGetValue(ns, name, out var method)) { - // Todo: Consider forcing this to load the exact function. - // That would make it so the function couldn't be changed during runtime, - // but of course it makes execution faster. - emit.LdArg(0 + _argOffset) - .LdStr(name) - .Call(typeof(ITsInstance).GetMethod("GetDelegate")) - .New(TsTypes.Constructors[typeof(TsDelegate)]); + method = StartMethod(name, ns); + _pendingMethods.Add($"{ns}.{name}".TrimStart('.'), variableToken.Position); } + emit.LdNull() + .LdFtn(method) + .New(typeof(TsScript).GetConstructor(new[] { typeof(object), typeof(IntPtr) })) + .LdStr(variableSymbol.Name) + .New(typeof(TsDelegate).GetConstructor(new[] { typeof(TsScript), typeof(string) })) + .New(TsTypes.Constructors[typeof(TsDelegate)]); + } + break; + case SymbolType.Variable: + if (_locals.TryGetValue(variableSymbol, out var local)) + { + if (_needAddress) + emit.LdLocalA(local); else - { - ns = GetAssetNamespace(symbol); - if (!_methods.TryGetValue(ns, name, out var method)) - { - method = StartMethod(name, ns); - _pendingMethods.Add($"{ns}.{name}".TrimStart('.'), variableToken.Position); - } - UnresolveNamespace(); - emit.LdNull() - .LdFtn(method) - .New(typeof(TsScript).GetConstructor(new[] { typeof(object), typeof(IntPtr) })) - .LdStr(symbol.Name) - .New(typeof(TsDelegate).GetConstructor(new[] { typeof(TsScript), typeof(string) })) - .New(TsTypes.Constructors[typeof(TsDelegate)]); - } - break; - case SymbolType.Variable: - if (_locals.TryGetValue(symbol, out var local)) - { - if (_needAddress) - emit.LdLocalA(local); - else - emit.LdLocal(local); - } - else if (symbol is VariableLeaf leaf && leaf.IsCaptured) - { - var field = _closure.Fields[symbol.Name]; + emit.LdLocal(local); + } + else if (variableSymbol is VariableLeaf leaf && leaf.IsCaptured) + { + var field = _closure.Fields[variableSymbol.Name]; - if (_closures == 0) - emit.LdLocal(_closure.Self); - else - emit.LdArg(0); + if (_closures == 0) + emit.LdLocal(_closure.Self); + else + emit.LdArg(0); - if (_needAddress) - emit.LdFldA(field); - else - emit.LdFld(field); - } + if (_needAddress) + emit.LdFldA(field); else - _logger.Error($"Tried to reference a non-existant variable {variableToken.Text}", variableToken.Position); - break; - default: - _logger.Error($"Currently cannot reference indentifier {symbol.Type} by it's raw value.", variableToken.Position); - break; - } - } - else - { - emit.LdArg(0 + _argOffset) - .LdStr(variableToken.Text) - .Call(typeof(ITsInstance).GetMethod("get_Item")); + emit.LdFld(field); + } + else + _logger.Error($"Tried to reference a non-existant variable {variableToken.Text}", variableToken.Position); + break; + default: + _logger.Error($"Currently cannot reference indentifier {variableSymbol.Type} by it's raw value.", variableToken.Position); + break; } } diff --git a/TaffyScript.Compiler/Symbols/SymbolTable.cs b/TaffyScript.Compiler/Symbols/SymbolTable.cs index d29dbef..3a301e9 100644 --- a/TaffyScript.Compiler/Symbols/SymbolTable.cs +++ b/TaffyScript.Compiler/Symbols/SymbolTable.cs @@ -8,20 +8,17 @@ namespace TaffyScript.Compiler { public class SymbolTable { - private Stack _current = new Stack(); + // Stores other nodes that are in the current scope, + // typically entered via the "using name.space" syntax. + private List _others = new List(); - public SymbolNode Current - { - get => _current.Peek(); - private set => _current.Push(value); - } + public SymbolNode Current { get; set; } public IEnumerable Symbols => Current.Children.Values; public SymbolTable() { - var root = new SymbolNode(null, "__0Root", SymbolType.Block); - _current.Push(root); + Current = new SymbolNode(null, "__0Root", SymbolType.Block); } /// @@ -42,7 +39,7 @@ public void Enter(string scopeName) /// public void Exit() { - _current.Pop(); + Current = Current.Parent; } public void Exit(int count) @@ -111,6 +108,39 @@ public void ExitNamespace(string ns) } } + public void AddSymbolToDefinitionLookup(SymbolNode node) + { + // Todo: Measure performance impact of Contains. + // Consider switching to HashSet. + if (!_others.Contains(node)) + _others.Add(node); + } + + public void RemoveSymbolFromDefinitionLookup(SymbolNode node) + { + _others.Remove(node); + } + + /// + /// Adds the values in a namespace to the definition lookup mechanism. + /// + /// + /// + public SymbolNode AddNamespaceToDefinitionLookup(string ns) + { + var count = EnterNamespace(ns); + var node = Current; + Exit(count); + if(!_others.Contains(node)) + _others.Add(node); + return node; + } + + public void RemoveAllNamespacesFromDefinitionLookup() + { + _others.Clear(); + } + /// /// Determines if a symbol is defined in the current scope. /// @@ -118,14 +148,19 @@ public void ExitNamespace(string ns) /// The symbol, it's defined. public bool Defined(string name, out ISymbol symbol) { - var current = new Queue(_current); - symbol = default(ISymbol); - while(current.Count != 0) + var current = Current; + while(current != null) { - if(current.Peek().Children.TryGetValue(name, out symbol)) + if(current.Children.TryGetValue(name, out symbol)) return true; - current.Dequeue(); + current = current.Parent; } + for(var i = 0; i < _others.Count; i++) + { + if (_others[i].Children.TryGetValue(name, out symbol)) + return true; + } + symbol = default(ISymbol); return false; } @@ -210,7 +245,13 @@ public bool Undefine(string name) /// public void PrintTable() { - var top = _current.Reverse().First(); + var top = Current; + var node = top; + while(node != null) + { + top = node; + node = node.Parent; + } var sb = new StringBuilder(); PrintNode(sb, top, 0); Console.WriteLine(sb); @@ -224,30 +265,5 @@ private void PrintNode(StringBuilder sb, ISymbol symbol, int indent) foreach(var child in node.Children.Values) PrintNode(sb, child, indent + 2); } - - /// - /// Prints all pending variables to the Console. - /// - public void PrintPending() - { - var top = _current.Reverse().First(); - var sb = new StringBuilder(); - PrintPending(sb, top, 0); - Console.WriteLine(sb); - } - - private void PrintPending(StringBuilder sb, ISymbol symbol, int indent) - { - if(symbol is SymbolNode node) - { - foreach(var pending in node.Pending) - { - sb.Append(' ', indent); - sb.AppendLine(pending); - } - foreach (var child in node.Children.Values) - PrintPending(sb, child, indent); - } - } } } From a5f14e309e1da499000f1eb5001d692c6462e88e Mon Sep 17 00:00:00 2001 From: mystborn Date: Fri, 18 May 2018 00:41:04 -0700 Subject: [PATCH 30/54] Fixed Certain Closure Bugs --- Samples/TestSuite/Tests/lambda.tfs | 13 +++-- Samples/TestSuite/Tests/prefix.tfs | 52 ------------------ .../Backend/Compiler/MsilWeakCodeGen.cs | 53 +++++++++++++------ 3 files changed, 44 insertions(+), 74 deletions(-) diff --git a/Samples/TestSuite/Tests/lambda.tfs b/Samples/TestSuite/Tests/lambda.tfs index da859a1..b61700c 100644 --- a/Samples/TestSuite/Tests/lambda.tfs +++ b/Samples/TestSuite/Tests/lambda.tfs @@ -10,10 +10,9 @@ namespace LanguageTests { lambda_no_capture, lambda_capture_local, lambda_capture_argument, - lambda_capture_default_argument - //lambda_local, - //lambda_nested_lambda - ); + lambda_capture_default_argument, + lambda_local, + lambda_nested_lambda); tests.run_tests(); } @@ -55,7 +54,7 @@ namespace LanguageTests { return script { return arg; } } - /*script lambda_local() { + script lambda_local() { test_it("lambda { var i = 0 }"); var s = script { var i = 1; @@ -71,7 +70,7 @@ namespace LanguageTests { var result = s(); assert_equal(result, 3); } - + script scr_get_nested_lambda() { return script { var i = 2; @@ -79,5 +78,5 @@ namespace LanguageTests { f(); return i; } - }*/ + } } \ No newline at end of file diff --git a/Samples/TestSuite/Tests/prefix.tfs b/Samples/TestSuite/Tests/prefix.tfs index 8fe4e25..49520f5 100644 --- a/Samples/TestSuite/Tests/prefix.tfs +++ b/Samples/TestSuite/Tests/prefix.tfs @@ -106,58 +106,6 @@ namespace LanguageTests { assert_equal(list[0], 0); } - /*script prefix_increment_grid() { - test_it("++grid"); - var grid = ds_grid_create(2, 2); - grid[# 0, 0] = 2; - ++grid[# 0, 0]; - assert_equal(grid[# 0, 0], 3); - var j = ++grid[# 0, 0]; - assert_equal(j, 4); - assert_equal(grid[# 0, 0], 4); - - ds_grid_destroy(grid); - } - - script prefix_decrement_grid() { - test_it("--grid"); - var grid = ds_grid_create(2, 2); - grid[# 0, 0] = 2; - --grid[# 0, 0]; - assert_equal(grid[# 0, 0], 1); - var j = --grid[# 0, 0]; - assert_equal(j, 0); - assert_equal(grid[# 0, 0], 0); - - ds_grid_destroy(grid); - } - - script prefix_increment_map() { - test_it("++map"); - var map = ds_map_create(); - map[? "moo"] = 2; - ++map[? "moo"]; - assert_equal(map[? "moo"], 3); - var j = ++map[? "moo"]; - assert_equal(j, 4); - assert_equal(map[? "moo"], 4); - - ds_map_destroy(map); - } - - script prefix_decrement_map() { - test_it("--map"); - var map = ds_map_create(); - map[? "moo"] = 2; - --map[? "moo"]; - assert_equal(map[? "moo"], 1); - var j = --map[? "moo"]; - assert_equal(j, 0); - assert_equal(map[? "moo"], 0); - - ds_map_destroy(map); - }*/ - script prefix_increment_local_var() { test_it("++local_var"); var i = 2; diff --git a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs index efee74c..ca2cac9 100644 --- a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -828,18 +828,24 @@ private void ScriptStart(string scriptName, MethodBuilder method, Type[] args) { emit = new ILEmitter(method, args); _table.Enter(scriptName); + DeclareLocals(true); + } + + private void DeclareLocals(bool declareLocalLambda) + { foreach(var local in _table.Symbols) { - if (local is VariableLeaf leaf && leaf.IsCaptured) - { - if (_closure == null) - GetClosure(true); - var field = _closure.Type.DefineField(local.Name, typeof(TsObject), FieldAttributes.Public); - _closure.Fields.Add(local.Name, field); - } - else + if(local is VariableLeaf leaf) { - _locals.Add(local, emit.DeclareLocal(typeof(TsObject), local.Name)); + if (leaf.IsCaptured) + { + if (_closure == null) + GetClosure(declareLocalLambda); + var field = _closure.Type.DefineField(local.Name, typeof(TsObject), FieldAttributes.Public); + _closure.Fields.Add(local.Name, field); + } + else + _locals.Add(local, emit.DeclareLocal(typeof(TsObject), local.Name)); } } } @@ -1371,7 +1377,12 @@ public void Visit(AssignNode assign) _logger.Error($"Cannot assign to the value {symbol.Name}", variable.Position); if (leaf.IsCaptured) - emit.LdLocal(_closure.Self); + { + if (_closures > 0) + emit.LdArg(0); + else + emit.LdLocal(_closure.Self); + } assign.Right.Accept(this); ConvertTopToObject(); @@ -2379,10 +2390,17 @@ public void Visit(LambdaNode lambda) MethodAttributes.Assembly | MethodAttributes.HideBySig, typeof(TsObject), ScriptArgs); + _table.Enter(lambda.Scope); + if (_closures == 0 && owner.Self is null && _table.Symbols.Any()) + { + owner.Self = emit.DeclareLocal(owner.Type, "__0closure"); + emit.New(owner.Constructor, 0) + .StLocal(owner.Self); + } var temp = emit; emit = new ILEmitter(closure, ScriptArgs); - _table.Enter(lambda.Scope); + DeclareLocals(false); ++_closures; _argOffset = 1; @@ -2398,15 +2416,20 @@ public void Visit(LambdaNode lambda) _table.Exit(); emit = temp; - if (owner.Self == null) - emit.New(owner.Constructor, 0); + if (_closures == 0) + { + if (owner.Self == null) + emit.New(owner.Constructor, 0); + else + emit.LdLocal(owner.Self); + } else - emit.LdLocal(owner.Self); + emit.LdArg(0); emit.LdFtn(closure) .New(typeof(TsScript).GetConstructor(new[] { typeof(object), typeof(IntPtr) })) .LdStr("lambda") - .LdArg(0) + .LdArg(0 + _argOffset) .New(typeof(TsDelegate).GetConstructor(new[] { typeof(TsScript), typeof(string), typeof(ITsInstance) })); } From 178a919f99b53d6a6d7d0c40a6967f5ed847c3e3 Mon Sep 17 00:00:00 2001 From: mystborn Date: Fri, 18 May 2018 14:51:21 -0700 Subject: [PATCH 31/54] Allow Return With No Expression --- Samples/TestSuite/Tests/return.tfs | 36 +++++++++++++++++++ Samples/TestSuite/Tests/tests.tfs | 2 ++ .../Backend/Compiler/MsilWeakCodeGen.cs | 13 ++++--- TaffyScript.Compiler/Front End/Parser.cs | 3 +- .../Syntax/Concrete/Return.cs | 1 + 5 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 Samples/TestSuite/Tests/return.tfs diff --git a/Samples/TestSuite/Tests/return.tfs b/Samples/TestSuite/Tests/return.tfs new file mode 100644 index 0000000..ebd7c16 --- /dev/null +++ b/Samples/TestSuite/Tests/return.tfs @@ -0,0 +1,36 @@ +using UnitTest; + +namespace LanguageTests { + script run_return_tests() { + var tests = new obj_unit_test("Return Tests", + return_something_works, + return_nothing_works); + tests.run_tests(); + } + + script return_something_works() { + test_it("script { return val }"); + var result = return_something(); + assert_equal(result, 2); + } + + script return_nothing_works() { + test_it("script { return }"); + var result = return_nothing_semicolon(); + assert(is_undefined(result)); + result = return_nothing_end_brace(); + assert(is_undefined(result)); + } + + script return_something() { + return 2; + } + + script return_nothing_semicolon() { + return; + } + + script return_nothing_end_brace() { + return + } +} \ No newline at end of file diff --git a/Samples/TestSuite/Tests/tests.tfs b/Samples/TestSuite/Tests/tests.tfs index 4bf7424..ceff185 100644 --- a/Samples/TestSuite/Tests/tests.tfs +++ b/Samples/TestSuite/Tests/tests.tfs @@ -30,5 +30,7 @@ namespace LanguageTests { show_debug_message(""); run_lambda_tests(); show_debug_message(""); + run_return_tests(); + show_debug_message(""); } } \ No newline at end of file diff --git a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs index ca2cac9..7e59c19 100644 --- a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -3499,12 +3499,17 @@ public void Visit(RepeatNode repeat) public void Visit(ReturnNode returnNode) { // Todo: Allow return by itself. - returnNode.ReturnValue.Accept(this); + if (returnNode.HasReturnValue) + { + returnNode.ReturnValue.Accept(this); - if (!emit.TryGetTop(out var returnType)) - _logger.Error("Tried to return without a return value. If this is expected, use exit instead", returnNode.Position); + if (!emit.TryGetTop(out var returnType)) + _logger.Error("Invalid return value", returnNode.ReturnValue.Position); - ConvertTopToObject(); + ConvertTopToObject(); + } + else + emit.Call(TsTypes.Empty); if (_inInstanceScript) { diff --git a/TaffyScript.Compiler/Front End/Parser.cs b/TaffyScript.Compiler/Front End/Parser.cs index 2db56b1..2935b9b 100644 --- a/TaffyScript.Compiler/Front End/Parser.cs +++ b/TaffyScript.Compiler/Front End/Parser.cs @@ -541,7 +541,8 @@ private ISyntaxElement SimpleStatement() case TokenType.Return: Confirm(TokenType.Return); var temp = _factory.CreateNode(SyntaxType.Return, next.Position); - temp.AddChild(Expression()); + if(!(Try(TokenType.OpenBrace) || Try(TokenType.CloseBrace) || Try(TokenType.SemiColon))) + temp.AddChild(Expression()); result = temp; break; case TokenType.Repeat: diff --git a/TaffyScript.Compiler/Syntax/Concrete/Return.cs b/TaffyScript.Compiler/Syntax/Concrete/Return.cs index 92a913a..1adfa14 100644 --- a/TaffyScript.Compiler/Syntax/Concrete/Return.cs +++ b/TaffyScript.Compiler/Syntax/Concrete/Return.cs @@ -2,6 +2,7 @@ { public class ReturnNode : SyntaxNode { + public bool HasReturnValue => Children.Count > 0; public ISyntaxElement ReturnValue => Children[0]; public override SyntaxType Type => SyntaxType.Return; From e3fa8e85e108f93ebc56490a3c70c3111efd1b00 Mon Sep 17 00:00:00 2001 From: mystborn Date: Fri, 18 May 2018 14:54:44 -0700 Subject: [PATCH 32/54] Deprecate Exit --- .../Backend/Compiler/MsilWeakCodeGen.cs | 18 +----------------- .../Front End/LexicalAnalysis/TokenType.cs | 1 - .../Front End/LexicalAnalysis/Tokenizer.cs | 1 - TaffyScript.Compiler/Front End/Parser.cs | 3 --- .../Syntax/Concrete/ExitToken.cs | 16 ---------------- .../Syntax/ISyntaxElementVisitor.cs | 1 - .../Syntax/SyntaxElementFactory.cs | 2 -- TaffyScript.Compiler/Syntax/SyntaxType.cs | 1 - .../TaffyScript.Compiler.csproj | 1 - 9 files changed, 1 insertion(+), 43 deletions(-) delete mode 100644 TaffyScript.Compiler/Syntax/Concrete/ExitToken.cs diff --git a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs index 7e59c19..0e06401 100644 --- a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -2020,22 +2020,6 @@ private void TestEquality(string op, Type left, Type right, TokenPosition pos) _logger.Error($"Cannot {op} types {left} and {right}", pos); } - public void Visit(ExitToken exitToken) - { - if(_inInstanceScript) - { - emit.Call(typeof(TsInstance).GetMethod("get_EventType")) - .Call(typeof(Stack).GetMethod("Pop")) - .Pop() - .Call(TsTypes.Empty) - .Ret(); - return; - } - if (_inGlobalScript && !emit.TryGetTop(out _)) - emit.Call(TsTypes.Empty); - emit.Ret(); - } - public void Visit(ForNode forNode) { var forStart = emit.DefineLabel(); @@ -2802,7 +2786,7 @@ public void Visit(ObjectNode objectNode) script.Body.Accept(this); BlockNode body = (BlockNode)script.Body; var last = body.Children.Count == 0 ? null : body.Children[body.Children.Count - 1]; - if(body.Children.Count == 0 || (last.Type != SyntaxType.Exit && last.Type != SyntaxType.Return)) + if(body.Children.Count == 0 || last.Type != SyntaxType.Return) { emit.Call(eventType) .Call(pop) diff --git a/TaffyScript.Compiler/Front End/LexicalAnalysis/TokenType.cs b/TaffyScript.Compiler/Front End/LexicalAnalysis/TokenType.cs index 3fe9139..34cb42d 100644 --- a/TaffyScript.Compiler/Front End/LexicalAnalysis/TokenType.cs +++ b/TaffyScript.Compiler/Front End/LexicalAnalysis/TokenType.cs @@ -34,7 +34,6 @@ public enum TokenType Enum, Equal, Event, - Exit, For, GreaterThan, GreaterThanOrEqual, diff --git a/TaffyScript.Compiler/Front End/LexicalAnalysis/Tokenizer.cs b/TaffyScript.Compiler/Front End/LexicalAnalysis/Tokenizer.cs index ce34573..3cccf8f 100644 --- a/TaffyScript.Compiler/Front End/LexicalAnalysis/Tokenizer.cs +++ b/TaffyScript.Compiler/Front End/LexicalAnalysis/Tokenizer.cs @@ -76,7 +76,6 @@ static Tokenizer() { "else", TokenType.Else }, { "for", TokenType.For }, { "return", TokenType.Return }, - { "exit", TokenType.Exit }, { "switch", TokenType.Switch }, { "case", TokenType.Case }, { "default", TokenType.Default }, diff --git a/TaffyScript.Compiler/Front End/Parser.cs b/TaffyScript.Compiler/Front End/Parser.cs index 2935b9b..ad1e5a9 100644 --- a/TaffyScript.Compiler/Front End/Parser.cs +++ b/TaffyScript.Compiler/Front End/Parser.cs @@ -535,9 +535,6 @@ private ISyntaxElement SimpleStatement() case TokenType.Continue: result = _factory.CreateToken(SyntaxType.Continue, Confirm(TokenType.Continue).Value, next.Position); break; - case TokenType.Exit: - result = _factory.CreateToken(SyntaxType.Exit, Confirm(TokenType.Exit).Value, next.Position); - break; case TokenType.Return: Confirm(TokenType.Return); var temp = _factory.CreateNode(SyntaxType.Return, next.Position); diff --git a/TaffyScript.Compiler/Syntax/Concrete/ExitToken.cs b/TaffyScript.Compiler/Syntax/Concrete/ExitToken.cs deleted file mode 100644 index ef268e0..0000000 --- a/TaffyScript.Compiler/Syntax/Concrete/ExitToken.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace TaffyScript.Compiler.Syntax -{ - public class ExitToken : SyntaxToken - { - public override SyntaxType Type => SyntaxType.Exit; - - public ExitToken(string value, TokenPosition position) : base(value, position) - { - } - - public override void Accept(ISyntaxElementVisitor visitor) - { - visitor.Visit(this); - } - } -} \ No newline at end of file diff --git a/TaffyScript.Compiler/Syntax/ISyntaxElementVisitor.cs b/TaffyScript.Compiler/Syntax/ISyntaxElementVisitor.cs index 5e02a32..32e6d48 100644 --- a/TaffyScript.Compiler/Syntax/ISyntaxElementVisitor.cs +++ b/TaffyScript.Compiler/Syntax/ISyntaxElementVisitor.cs @@ -11,7 +11,6 @@ public interface ISyntaxElementVisitor void Visit(RootNode root); void Visit(AssignNode assign); void Visit(ReadOnlyToken readOnlyToken); - void Visit(ExitToken exitToken); void Visit(NewNode newNode); void Visit(NamespaceNode namespaceNode); void Visit(ImportObjectNode importObjectNode); diff --git a/TaffyScript.Compiler/Syntax/SyntaxElementFactory.cs b/TaffyScript.Compiler/Syntax/SyntaxElementFactory.cs index 29f9e2c..73b8898 100644 --- a/TaffyScript.Compiler/Syntax/SyntaxElementFactory.cs +++ b/TaffyScript.Compiler/Syntax/SyntaxElementFactory.cs @@ -140,8 +140,6 @@ public ISyntaxToken CreateToken(SyntaxType type, string value, TokenPosition pos return new BreakToken(value, position); case SyntaxType.Continue: return new ContinueToken(value, position); - case SyntaxType.Exit: - return new ExitToken(value, position); case SyntaxType.ReadOnlyValue: return new ReadOnlyToken(value, position); default: diff --git a/TaffyScript.Compiler/Syntax/SyntaxType.cs b/TaffyScript.Compiler/Syntax/SyntaxType.cs index 865a642..dca701f 100644 --- a/TaffyScript.Compiler/Syntax/SyntaxType.cs +++ b/TaffyScript.Compiler/Syntax/SyntaxType.cs @@ -55,7 +55,6 @@ public enum SyntaxType End, Break, Continue, - Exit, ReadOnlyValue } } diff --git a/TaffyScript.Compiler/TaffyScript.Compiler.csproj b/TaffyScript.Compiler/TaffyScript.Compiler.csproj index fe46db0..1eebb71 100644 --- a/TaffyScript.Compiler/TaffyScript.Compiler.csproj +++ b/TaffyScript.Compiler/TaffyScript.Compiler.csproj @@ -114,7 +114,6 @@ - From 2a9db7abb48ed4566753ab7007b68ae3b5a30e9f Mon Sep 17 00:00:00 2001 From: mystborn Date: Fri, 18 May 2018 15:24:15 -0700 Subject: [PATCH 33/54] Make Event Obsolete --- Samples/TestSuite/Tests/postfix.tfs | 12 ++++++------ Samples/TestSuite/Tests/prefix.tfs | 12 ++++++------ Samples/TestSuite/Tests/script_composition.tfs | 8 ++++---- Samples/TestSuite/Tests/with.tfs | 4 ++-- TaffyScript.Compiler/Front End/Parser.cs | 4 +++- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/Samples/TestSuite/Tests/postfix.tfs b/Samples/TestSuite/Tests/postfix.tfs index 37e7a89..493310d 100644 --- a/Samples/TestSuite/Tests/postfix.tfs +++ b/Samples/TestSuite/Tests/postfix.tfs @@ -149,15 +149,15 @@ namespace LanguageTests { } object obj_postfix { - event create() { + script create() { reset(); } - event reset() { + script reset() { val = 10; } - event postfix_object_var_increment() { + script postfix_object_var_increment() { test_it("object.val++"); reset(); val++; @@ -167,7 +167,7 @@ namespace LanguageTests { assert_equal(val, 12); } - event postfix_object_var_decrement() { + script postfix_object_var_decrement() { test_it("object.val--"); reset(); val--; @@ -177,7 +177,7 @@ namespace LanguageTests { assert_equal(val, 8); } - event postfix_self_var_increment() { + script postfix_self_var_increment() { test_it("self.val++"); reset(); self.val++; @@ -187,7 +187,7 @@ namespace LanguageTests { assert_equal(val, 12); } - event postfix_self_var_decrement() { + script postfix_self_var_decrement() { test_it("self.val--"); reset(); self.val--; diff --git a/Samples/TestSuite/Tests/prefix.tfs b/Samples/TestSuite/Tests/prefix.tfs index 49520f5..8b85cd2 100644 --- a/Samples/TestSuite/Tests/prefix.tfs +++ b/Samples/TestSuite/Tests/prefix.tfs @@ -187,15 +187,15 @@ namespace LanguageTests { } object obj_prefix { - event create() { + script create() { reset(); } - event reset() { + script reset() { val = 2; } - event prefix_increment_object_var() { + script prefix_increment_object_var() { test_it("++obj_var") reset(); ++val; @@ -205,7 +205,7 @@ namespace LanguageTests { assert_equal(val, 4); } - event prefix_decrement_object_var() { + script prefix_decrement_object_var() { test_it("--obj_var"); reset(); --val; @@ -215,7 +215,7 @@ namespace LanguageTests { assert_equal(val, 0); } - event prefix_increment_self_var() { + script prefix_increment_self_var() { test_it("++self_var"); reset(); ++self.val; @@ -225,7 +225,7 @@ namespace LanguageTests { assert_equal(val, 4); } - event prefix_decrement_self_var() { + script prefix_decrement_self_var() { test_it("--self_var"); reset(); --self.val; diff --git a/Samples/TestSuite/Tests/script_composition.tfs b/Samples/TestSuite/Tests/script_composition.tfs index a0b1481..622d20b 100644 --- a/Samples/TestSuite/Tests/script_composition.tfs +++ b/Samples/TestSuite/Tests/script_composition.tfs @@ -23,21 +23,21 @@ namespace LanguageTests { } object obj_comp2 : obj_comp1 { - event ev_comp1() { + script ev_comp1() { } - event ev_comp2 { + script ev_comp2 { } - event moo() { + script moo() { return "moo"; } } object obj_comp3 : obj_comp2 { - event moo() { + script moo() { return "moo" + event_inherited(); } } diff --git a/Samples/TestSuite/Tests/with.tfs b/Samples/TestSuite/Tests/with.tfs index 94ac7bb..7ea3d0c 100644 --- a/Samples/TestSuite/Tests/with.tfs +++ b/Samples/TestSuite/Tests/with.tfs @@ -68,11 +68,11 @@ namespace LanguageTests { } object obj_with { - event create(num) { + script create(num) { self.num = num; } - event get_value() { + script get_value() { return 4; } } diff --git a/TaffyScript.Compiler/Front End/Parser.cs b/TaffyScript.Compiler/Front End/Parser.cs index ad1e5a9..f9403ac 100644 --- a/TaffyScript.Compiler/Front End/Parser.cs +++ b/TaffyScript.Compiler/Front End/Parser.cs @@ -400,7 +400,9 @@ private ISyntaxElement ImportScript(TokenPosition pos) private ISyntaxElement Script(SymbolScope scope) { - if (!(Validate(TokenType.Script) || Validate(TokenType.Event))) + if (Try(TokenType.Event, out var eventToken)) + _logger.Warning("event is an obsolete keyword. It will be deprecated on the next major release. Consider switching to script", eventToken.Position); + else if (!Validate(TokenType.Script)) { _logger.Error($"Expected a script, got {_stream.Peek().Type}", _stream.Read().Position); return null; From b3f9780406f1654c4cff1c1ddfdac97ff9078d8f Mon Sep 17 00:00:00 2001 From: mystborn Date: Fri, 18 May 2018 19:10:22 -0700 Subject: [PATCH 34/54] Adjusted Base-Type Generation to Avoid Name Conflicts --- .../Backend/Compiler/MsilWeakCodeGen.cs | 22 ++++++++++------- .../DataStructureDisposedException.cs | 24 ------------------- TaffyScript/TaffyScript.csproj | 1 - TaffyScript/TsObject.cs | 9 +++---- 4 files changed, 18 insertions(+), 38 deletions(-) delete mode 100644 TaffyScript/BaseClassLib/DataStructureDisposedException.cs diff --git a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs index 0e06401..9eccb27 100644 --- a/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs +++ b/TaffyScript.Compiler/Backend/Compiler/MsilWeakCodeGen.cs @@ -53,6 +53,7 @@ internal partial class MsilWeakCodeGen : ISyntaxElementVisitor private readonly DotNetAssemblyLoader _assemblyLoader; private readonly DotNetTypeParser _typeParser; private string _entryPoint; + private string _projectName; private SymbolTable _table; private IErrorLogger _logger; @@ -122,11 +123,6 @@ internal partial class MsilWeakCodeGen : ISyntaxElementVisitor /// private Stack