From 73cecd5cbf2aae183e9069fe5d218acf40f1889c Mon Sep 17 00:00:00 2001 From: Isaac Date: Fri, 24 Jan 2020 12:29:21 +1300 Subject: [PATCH 1/8] Simplified kernancompiler module and added extra features --- GraceLanguage/Execution/Interpreter.cs | 20 ++- GraceLanguage/Parsing/ParseNodes.cs | 11 +- .../modules/platform/kernancompiler.cs | 146 +++++++----------- 3 files changed, 72 insertions(+), 105 deletions(-) diff --git a/GraceLanguage/Execution/Interpreter.cs b/GraceLanguage/Execution/Interpreter.cs index 3e3bf36..8ac2938 100644 --- a/GraceLanguage/Execution/Interpreter.cs +++ b/GraceLanguage/Execution/Interpreter.cs @@ -366,9 +366,11 @@ public GraceObject LoadModule(string path) continue; } filePath = Path.Combine(p, path + ".grace"); - mod = tryLoadModuleFile(filePath, path); - if (mod != null) + + String mod_contents = TryReadModuleFile(filePath, path); + if (mod_contents != null) { + mod = LoadModuleString(filePath, mod_contents); modules[path] = mod; return mod; } @@ -402,12 +404,14 @@ public GraceObject LoadModule(string path) return null; } - /// Load a module file if it exists - private GraceObject tryLoadModuleFile(string filePath, + /// Read a module file if it exists + /// Filesystem path to the module + /// Module name to treat this code as belonging to. + public String TryReadModuleFile(string filePath, string importPath) { return (File.Exists(filePath)) - ? loadModuleFile(filePath, importPath) + ? readModuleFile(filePath, importPath) : null; } @@ -429,13 +433,13 @@ private GraceObject tryLoadResource(string filePath, string importPath) : null; } - /// Load a module file - private GraceObject loadModuleFile(string filePath, string importPath) + /// Read a module file + private String readModuleFile(string filePath, string importPath) { Interpreter.Debug("========== LOAD " + filePath + " =========="); using (StreamReader reader = File.OpenText(filePath)) { - return LoadModuleString(importPath, reader.ReadToEnd()); + return reader.ReadToEnd(); } } diff --git a/GraceLanguage/Parsing/ParseNodes.cs b/GraceLanguage/Parsing/ParseNodes.cs index e47c847..405bc6c 100644 --- a/GraceLanguage/Parsing/ParseNodes.cs +++ b/GraceLanguage/Parsing/ParseNodes.cs @@ -1953,15 +1953,15 @@ public override T Visit(ParseNodeVisitor visitor) /// public static class ParseNodeMeta { - private static Dictionary parseNodes; + private static DictionaryDataObject parseNodes; /// /// Get dictionary of parse node names to patterns. /// - public static Dictionary GetPatternDict() + public static GraceObject GetPatternDict() { if (parseNodes == null) - parseNodes = new Dictionary { + parseNodes = new DictionaryDataObject(new Dictionary { { "Object", new NativeTypePattern() }, { "MethodDeclaration", new NativeTypePattern() }, @@ -2021,7 +2021,7 @@ public static Dictionary GetPatternDict() new NativeTypePattern() }, { "Comment", new NativeTypePattern() }, - }; + }); return parseNodes; } @@ -2033,8 +2033,7 @@ private static GraceObject getPrettyPrinter(EvaluationContext ctx) string path = Path.Combine(dir, "pretty_printer.grace"); GraceObject ret; LocalScope surrounding = new LocalScope(); - surrounding.AddLocalDef("parseNodes", - new DictionaryDataObject(GetPatternDict())); + surrounding.AddLocalDef("parseNodes", GetPatternDict()); ctx.Extend(surrounding); using (StreamReader reader = File.OpenText(path)) { diff --git a/GraceLanguage/modules/platform/kernancompiler.cs b/GraceLanguage/modules/platform/kernancompiler.cs index c69ff57..7c1b20b 100644 --- a/GraceLanguage/modules/platform/kernancompiler.cs +++ b/GraceLanguage/modules/platform/kernancompiler.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using System.Linq; using System.IO; using Grace.Parsing; using Grace.Execution; @@ -12,7 +14,6 @@ namespace KernanCompiler [ModuleEntryPoint] public class ExposedCompiler : GraceObject { - private ParseNodePatternDictObject parseNodes; public static GraceObject Instantiate( EvaluationContext ctx) @@ -22,41 +23,72 @@ public static GraceObject Instantiate( public ExposedCompiler() : base("platform/kernancompiler") { - AddMethod("parse(_)", new DelegateMethod1( - new NativeMethod1(mParse))); - AddMethod("parseFile(_)", new DelegateMethod1( - new NativeMethod1(mParseFile))); - AddMethod("translateFile(_)", new DelegateMethod1( - new NativeMethod1(mTranslateFile))); - AddMethod("parseNodes", new DelegateMethod0( - new NativeMethod0(mParseNodes))); + AddMethod("parse(_)", new DelegateMethod1(code => mParse(GraceString.Create("source code"), code))); + AddMethod("parse(_, _)", + new DelegateMethodReq((ctx, req) => { + MethodHelper.CheckArity(ctx, req, 2); + return mParse(req[0].Arguments[0], req[0].Arguments[1]); })); + AddMethod("parseFile(_)", new DelegateMethod1(mParseFile)); + AddMethod("readGraceModule(_)", new DelegateMethod1Ctx(mReadGraceModule)); + AddMethod("translateFile(_)", new DelegateMethod1(mTranslateFile)); + AddMethod("parseNodes", new DelegateMethod0(() => ParseNodeMeta.GetPatternDict())); AddMethod("args", new DelegateMethod0( - new NativeMethod0(mArguments))); + () => GraceVariadicList.Of(UnusedArguments.UnusedArgs.Select(GraceString.Create)))); } - private GraceObject mParse(GraceObject code) + private GraceObject mParse(GraceObject gmodulename, GraceObject gcode) { - GraceString gs = code.FindNativeParent(); - string s = gs.Value; - var p = new Parser(s); - return new GraceObjectProxy(p.Parse()); + String modulename = gmodulename.FindNativeParent().Value; + String code = gcode.FindNativeParent().Value; + return new GraceObjectProxy(new Parser(modulename, code)); } - private GraceObject mParseFile(GraceObject code) + private GraceObject mParseFile(GraceObject gpath) { - GraceString gs = code.FindNativeParent(); - string path = gs.Value; + String path = gpath.FindNativeParent().Value; using (StreamReader reader = File.OpenText(path)) { - var p= new Parser(reader.ReadToEnd()); - return new GraceObjectProxy(p.Parse()); + return new GraceObjectProxy(new Parser(path, reader.ReadToEnd()).Parse()); } } - private GraceObject mTranslateFile(GraceObject code) + private GraceObject mReadGraceModule(EvaluationContext ctx, GraceObject gpath) { - GraceString gs = code.FindNativeParent(); - string path = gs.Value; + var itp = (Interpreter)ctx; + String path = gpath.FindNativeParent().Value; + + var name = Path.GetFileName(path); + var bases = itp.GetModulePaths(); + foreach (var p in bases) + { + string filePath; + + filePath = Path.Combine(p, path + ".grace"); + + String mod_contents = itp.TryReadModuleFile(filePath, path); + if (mod_contents != null) + { + return GraceString.Create(mod_contents.Replace(Environment.NewLine, "\u2028")); + } + } + if (itp.FailedImportHook != null) + { + // Optionally, the host program can try to satisfy a module + // and indicate that we should retry the import. + if (itp.FailedImportHook(path, itp)) + { + return mReadGraceModule(itp, gpath); + } + } + ErrorReporting.RaiseError(itp, "R2005", + new Dictionary { { "path", path } }, + "LookupError: Could not find module ${path}"); + return null; + } + + private GraceObject mTranslateFile(GraceObject gpath) + { + String path = gpath.FindNativeParent().Value; using (StreamReader reader = File.OpenText(path)) { var p = new Parser(reader.ReadToEnd()); @@ -66,73 +98,5 @@ private GraceObject mTranslateFile(GraceObject code) return eModule; } } - - private GraceObject mArguments() - { - IList unusedArguments = UnusedArguments.UnusedArgs; - IList graceUnusedArguments = new List(); - - foreach (var a in unusedArguments) - graceUnusedArguments.Add(GraceString.Create(a)); - - return GraceVariadicList.Of(graceUnusedArguments); - } - - - private GraceObject mParseNodes() - { - if (parseNodes == null) - parseNodes = new ParseNodePatternDictObject(); - return parseNodes; - } - } - - class NativeTypePattern : GraceObject { - public NativeTypePattern() - { - AddMethod("match(_)", new DelegateMethod1Ctx( - new NativeMethod1Ctx(mMatch))); - AddMethod("|", Matching.OrMethod); - AddMethod("&", Matching.AndMethod); - } - - /// Native method for Grace match - /// Current interpreter - /// Target of the match - private GraceObject mMatch(EvaluationContext ctx, GraceObject target) - { - var gop = target as GraceObjectProxy; - if (gop == null) - return Matching.FailedMatch(ctx, target); - if (gop.Object is T) - return Matching.SuccessfulMatch(ctx, target); - return Matching.FailedMatch(ctx, target); - } - } - - class ParseNodePatternDictObject : GraceObject, - IEnumerable> - { - private Dictionary data = - ParseNodeMeta.GetPatternDict(); - - public override GraceObject Request(EvaluationContext ctx, - MethodRequest req) - { - if (data.ContainsKey(req.Name)) - return data[req.Name]; - return base.Request(ctx, req); - } - - public IEnumerator> GetEnumerator() - { - return data.GetEnumerator(); - } - - System.Collections.IEnumerator - System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } } } From efabce9ef05dbdbdf1c3ae5dd15008e5e2654042 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 27 Jan 2020 16:11:16 +1300 Subject: [PATCH 2/8] Fixed bug when anding patterns --- GraceLanguage/Runtime/Matching.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GraceLanguage/Runtime/Matching.cs b/GraceLanguage/Runtime/Matching.cs index 0a98afe..0f28e99 100644 --- a/GraceLanguage/Runtime/Matching.cs +++ b/GraceLanguage/Runtime/Matching.cs @@ -103,7 +103,7 @@ public static GraceObject AndCombinator(EvaluationContext ctx, GraceObject self, GraceObject other) { var patReq = new MethodRequest(); - patReq.AddPart(new RequestPart("_OrPattern", + patReq.AddPart(new RequestPart("_AndPattern", RequestPart.EmptyList, new List { self, other })); GraceObject patRec = ctx.FindReceiver(patReq); From f5493933b983c94368a71b486b24fc6af3d3b3a4 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 27 Jan 2020 16:42:14 +1300 Subject: [PATCH 3/8] Objects now provide an identity-based hash method --- GraceLanguage/Runtime/GraceObject.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/GraceLanguage/Runtime/GraceObject.cs b/GraceLanguage/Runtime/GraceObject.cs index e54851a..691419b 100644 --- a/GraceLanguage/Runtime/GraceObject.cs +++ b/GraceLanguage/Runtime/GraceObject.cs @@ -163,6 +163,7 @@ private void initialise(bool defaults) AddMethod("asString", null); AddMethod("==(_)", null); AddMethod("!=(_)", null); + AddMethod("hash", null); } } @@ -218,6 +219,15 @@ private static GraceObject mNotEquals(EvaluationContext ctx, return GraceBoolean.Create(!object.ReferenceEquals(self, other)); } + /// Native method supporting Grace hash + /// Current interpreter + /// Receiver + private static GraceObject mHash(EvaluationContext ctx, + GraceObject self) + { + return GraceNumber.Create(RuntimeHelpers.GetHashCode(self)); + } + /// Remove a method from this object /// Method name to remove public virtual void RemoveMethod(string m) @@ -289,6 +299,9 @@ protected virtual Method getLazyMethod(string name) case "!=(_)": m = new DelegateMethodReceiver1Ctx(mNotEquals); return m; + case "hash": + m = new DelegateMethodReceiver0Ctx(mHash); + return m; } return null; } From 01aa25619d42b66a2306f029df6285413f564c89 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 27 Jan 2020 16:42:54 +1300 Subject: [PATCH 4/8] Added support for BooleanExtension, SequenceExtension, and TypeExtension --- GraceLanguage/Execution/Interpreter.cs | 28 ++++++ GraceLanguage/Runtime/GraceBoolean.cs | 125 ++++++++++++++----------- GraceLanguage/Runtime/GraceType.cs | 44 +++++++-- GraceLanguage/Runtime/Iterables.cs | 18 ++++ 4 files changed, 153 insertions(+), 62 deletions(-) diff --git a/GraceLanguage/Execution/Interpreter.cs b/GraceLanguage/Execution/Interpreter.cs index 8ac2938..aeaafde 100644 --- a/GraceLanguage/Execution/Interpreter.cs +++ b/GraceLanguage/Execution/Interpreter.cs @@ -257,6 +257,34 @@ public void LoadExtensionsFromObject(GraceObject ext) ext.Request(this, req); GraceString.ExtendWith(req.InheritedMethods); } + req = MethodRequest.Nullary("BooleanExtension"); + req.IsInherits = true; + if (ext.RespondsTo(req)) + { + var uo = new UserObject(); + req.InheritingObject = uo; + ext.Request(this, req); + GraceBoolean.ExtendWith(req.InheritedMethods); + } + req = MethodRequest.Nullary("SequenceExtension"); + req.IsInherits = true; + if (ext.RespondsTo(req)) + { + var uo = new UserObject(); + req.InheritingObject = uo; + ext.Request(this, req); + Iterables.ExtendWith(req.InheritedMethods); + } + req = MethodRequest.Nullary("TypeExtension"); + req.IsInherits = true; + if (ext.RespondsTo(req)) + { + var uo = new UserObject(); + req.InheritingObject = uo; + ext.Request(this, req); + GraceType.ExtendWith(req.InheritedMethods); + } + } /// diff --git a/GraceLanguage/Runtime/GraceBoolean.cs b/GraceLanguage/Runtime/GraceBoolean.cs index 11191ae..701795f 100644 --- a/GraceLanguage/Runtime/GraceBoolean.cs +++ b/GraceLanguage/Runtime/GraceBoolean.cs @@ -11,6 +11,8 @@ namespace Grace.Runtime /// A Grace boolean object public class GraceBoolean : GraceObject { + private static Dictionary sharedMethods; + /// The true singleton public static GraceBoolean True = new GraceBoolean(true); @@ -24,81 +26,92 @@ public bool Boolean set; } private GraceBoolean(bool val) + : base(createSharedMethods()) { Boolean = val; - AddMethod("prefix!", - new DelegateMethod0(new NativeMethod0(this.Negate))); - AddMethod("not", - new DelegateMethod0(new NativeMethod0(this.Negate))); - AddMethod("hash", new DelegateMethod0(mHash)); - AddMethod("&&(_)", - new DelegateMethod1Ctx(this.AndAnd)); - AddMethod("||(_)", - new DelegateMethod1Ctx(this.OrOr)); - AddMethod("ifTrue(_)", - new DelegateMethod1Ctx( - new NativeMethod1Ctx(this.IfTrue))); - AddMethod("ifFalse(_)", - new DelegateMethod1Ctx( - new NativeMethod1Ctx(this.IfFalse))); - AddMethod("ifTrue(_) ifFalse(_)", - new DelegateMethodReq( - new NativeMethodReq(this.IfTrueIfFalse))); - AddMethod("andAlso(_)", - new DelegateMethod1Ctx( - new NativeMethod1Ctx(this.AndAlso))); - AddMethod("orElse(_)", - new DelegateMethod1Ctx( - new NativeMethod1Ctx(this.OrElse))); - AddMethod("match(_)", new DelegateMethod1Ctx( - new NativeMethod1Ctx(this.Match))); - AddMethod("asString", - new DelegateMethod0(new NativeMethod0(this.AsString))); + } + + private static Dictionary createSharedMethods() + { + if (sharedMethods != null) + return sharedMethods; + sharedMethods = new Dictionary + { + { "prefix!", new DelegateMethodTyped0(Negate) }, + { "not", new DelegateMethodTyped0(Negate) }, + { "hash", new DelegateMethodTyped0(mHash) }, + { "&&(_)", new DelegateMethodTyped1Ctx(AndAnd) }, + { "||(_)", new DelegateMethodTyped1Ctx(OrOr) }, + { "ifTrue(_)", new DelegateMethodTyped1Ctx(IfTrue) }, + { "ifFalse(_)", new DelegateMethodTyped1Ctx(IfFalse) }, + { "ifTrue(_) ifFalse(_)", new DelegateMethodTyped(IfTrueIfFalse) }, + { "andAlso(_)", new DelegateMethodTyped1Ctx(AndAlso) }, + { "orElse(_)", new DelegateMethodTyped1Ctx(OrElse) }, + { "match(_)", new DelegateMethodTyped1Ctx(Match) }, + { "asString", new DelegateMethodTyped0(AsString) }, + }; + return sharedMethods; + } + + /// + /// Apply an extension trait to all future instances of this type. + /// + /// + /// Dictionary of methods to add. + /// + public static void ExtendWith(IDictionary meths) + { + if (sharedMethods == null) + createSharedMethods(); + foreach (var m in meths) + sharedMethods[m.Key] = m.Value; } /// Native method for Grace ! - public GraceObject Negate() + public static GraceObject Negate(GraceBoolean self) { - if (Boolean) + if (self.Boolean) return GraceBoolean.False; return GraceBoolean.True; } - private GraceObject mHash() + private static GraceObject mHash(GraceBoolean self) { - return GraceNumber.Create(Boolean.GetHashCode()); + return GraceNumber.Create(self.Boolean.GetHashCode()); } /// Native method for Grace match /// Current interpreter + /// Receiver of the method /// Target of the match - public GraceObject Match(EvaluationContext ctx, GraceObject target) + public static GraceObject Match(EvaluationContext ctx, GraceBoolean self, GraceObject target) { var b = target as GraceBoolean; - if (b != null && b.Boolean == Boolean) + if (b != null && b.Boolean == self.Boolean) return Matching.SuccessfulMatch(ctx, target); return Matching.FailedMatch(ctx, target); } /// Native method for Grace asString - public GraceObject AsString() + public static GraceObject AsString(GraceBoolean self) { - if (Boolean) + if (self.Boolean) return GraceString.Create("true"); return GraceString.Create("false"); } /// Native method for Grace && /// Current interpreter + /// Receiver of the method /// Argument to the method - public GraceObject AndAnd(EvaluationContext ctx, GraceObject other) + public static GraceObject AndAnd(EvaluationContext ctx, GraceBoolean self, GraceObject other) { GraceBoolean oth = other as GraceBoolean; if (oth != null) - return GraceBoolean.Create(this.Boolean && oth.Boolean); + return GraceBoolean.Create(self.Boolean && oth.Boolean); GraceObjectProxy op = other as GraceObjectProxy; if (op != null) - return GraceBoolean.Create(this.Boolean && (dynamic)op.Object); + return GraceBoolean.Create(self.Boolean && (dynamic)op.Object); ErrorReporting.RaiseError(ctx, "R2001", new Dictionary() { { "method", "&&" }, @@ -113,15 +126,16 @@ public GraceObject AndAnd(EvaluationContext ctx, GraceObject other) /// Native method for Grace || /// Current interpreter + /// Receiver of the method /// Argument to the method - public GraceObject OrOr(EvaluationContext ctx, GraceObject other) + public static GraceObject OrOr(EvaluationContext ctx, GraceBoolean self, GraceObject other) { GraceBoolean oth = other as GraceBoolean; if (oth != null) - return GraceBoolean.Create(this.Boolean || oth.Boolean); + return GraceBoolean.Create(self.Boolean || oth.Boolean); GraceObjectProxy op = other as GraceObjectProxy; if (op != null) - return GraceBoolean.Create(this.Boolean || (dynamic)op.Object); + return GraceBoolean.Create(self.Boolean || (dynamic)op.Object); ErrorReporting.RaiseError(ctx, "R2001", new Dictionary() { { "method", "||" }, @@ -136,8 +150,9 @@ public GraceObject OrOr(EvaluationContext ctx, GraceObject other) /// Native method for Grace ifTrue /// Current interpreter + /// Receiver of the method /// Block to apply if true - public GraceObject IfTrue(EvaluationContext ctx, GraceObject other) + public static GraceObject IfTrue(EvaluationContext ctx, GraceBoolean self, GraceObject other) { var oth = other as GraceBlock; if (oth == null) @@ -150,7 +165,7 @@ public GraceObject IfTrue(EvaluationContext ctx, GraceObject other) }, "ArgumentTypeError: ifTrue requires a block argument" ); - if (Boolean) + if (self.Boolean) { var req = MethodRequest.Nullary("apply"); other.Request(ctx, req); @@ -160,8 +175,9 @@ public GraceObject IfTrue(EvaluationContext ctx, GraceObject other) /// Native method for Grace ifFalse /// Current interpreter + /// Receiver of the method /// Block to apply if false - public GraceObject IfFalse(EvaluationContext ctx, GraceObject other) + public static GraceObject IfFalse(EvaluationContext ctx, GraceBoolean self, GraceObject other) { var oth = other as GraceBlock; if (oth == null) @@ -174,7 +190,7 @@ public GraceObject IfFalse(EvaluationContext ctx, GraceObject other) }, "ArgumentTypeError: ifFalse requires a block argument" ); - if (!Boolean) + if (!self.Boolean) { var req = MethodRequest.Nullary("apply"); other.Request(ctx, req); @@ -184,10 +200,11 @@ public GraceObject IfFalse(EvaluationContext ctx, GraceObject other) /// Native method for Grace ifTrue ifFalse /// Current interpreter + /// Receiver of the method /// Method request that gave rise to this method /// execution - public GraceObject IfTrueIfFalse(EvaluationContext ctx, - MethodRequest req) + public static GraceObject IfTrueIfFalse(EvaluationContext ctx, + MethodRequest req, GraceBoolean self) { MethodHelper.CheckArity(ctx, req, 1, 1); var trueBlock = req[0].Arguments[0]; @@ -213,7 +230,7 @@ public GraceObject IfTrueIfFalse(EvaluationContext ctx, "ArgumentTypeError: ifTrue ifFalse requires two block arguments" ); var apply = MethodRequest.Nullary("apply"); - if (Boolean) + if (self.Boolean) { return trueBlock.Request(ctx, apply); } @@ -222,8 +239,9 @@ public GraceObject IfTrueIfFalse(EvaluationContext ctx, /// Native method for Grace andAlso /// Current interpreter + /// Receiver of the method /// Block to apply if true - public GraceObject AndAlso(EvaluationContext ctx, GraceObject other) + public static GraceObject AndAlso(EvaluationContext ctx, GraceBoolean self, GraceObject other) { var oth = other as GraceBlock; if (oth == null) @@ -236,7 +254,7 @@ public GraceObject AndAlso(EvaluationContext ctx, GraceObject other) }, "ArgumentTypeError: andAlso requires a block argument" ); - if (Boolean) + if (self.Boolean) { var req = MethodRequest.Nullary("apply"); return other.Request(ctx, req); @@ -246,8 +264,9 @@ public GraceObject AndAlso(EvaluationContext ctx, GraceObject other) /// Native method for Grace orElse /// Current interpreter + /// Receiver of the method /// Block to apply if false - public GraceObject OrElse(EvaluationContext ctx, GraceObject other) + public static GraceObject OrElse(EvaluationContext ctx, GraceBoolean self, GraceObject other) { var oth = other as GraceBlock; if (oth == null) @@ -260,7 +279,7 @@ public GraceObject OrElse(EvaluationContext ctx, GraceObject other) }, "ArgumentTypeError: orElse requires a block argument" ); - if (!Boolean) + if (!self.Boolean) { var req = MethodRequest.Nullary("apply"); return other.Request(ctx, req); diff --git a/GraceLanguage/Runtime/GraceType.cs b/GraceLanguage/Runtime/GraceType.cs index 23afbfb..07ad29c 100644 --- a/GraceLanguage/Runtime/GraceType.cs +++ b/GraceLanguage/Runtime/GraceType.cs @@ -6,6 +6,8 @@ namespace Grace.Runtime /// A Grace type literal public class GraceType : GraceObject { + private static Dictionary sharedMethods; + private readonly string name; private List methods = new List(); private List requests; @@ -13,12 +15,36 @@ public class GraceType : GraceObject /// Name of this type for debugging /// and reporting purposes public GraceType(string name) + : base(createSharedMethods()) { this.name = name; - AddMethod("match(_)", new DelegateMethod1Ctx( - new NativeMethod1Ctx(this.Match))); - AddMethod("|(_)", Matching.OrMethod); - AddMethod("&(_)", Matching.AndMethod); + } + + private static Dictionary createSharedMethods() + { + if (sharedMethods != null) + return sharedMethods; + sharedMethods = new Dictionary + { + { "match(_)", new DelegateMethodTyped1Ctx(Match) }, + { "|(_)", Matching.OrMethod }, + { "&(_)", Matching.AndMethod }, + }; + return sharedMethods; + } + + /// + /// Apply an extension trait to all future instances of this type. + /// + /// + /// Dictionary of methods to add. + /// + public static void ExtendWith(IDictionary meths) + { + if (sharedMethods == null) + createSharedMethods(); + foreach (var m in meths) + sharedMethods[m.Key] = m.Value; } /// Add a method type entry to this type @@ -32,12 +58,12 @@ public void Add(SignatureNode n) /// for types /// At present, this matching uses only the method /// names in both the object and the type. - public GraceObject Match(EvaluationContext ctx, GraceObject target) + public static GraceObject Match(EvaluationContext ctx, GraceType self, GraceObject target) { - if (requests == null) + if (self.requests == null) { var l = new List(); - foreach (var m in methods) + foreach (var m in self.methods) { var req = new MethodRequest(); foreach (var p in m) @@ -47,9 +73,9 @@ public GraceObject Match(EvaluationContext ctx, GraceObject target) } l.Add(req); } - requests = l; + self.requests = l; } - foreach (var req in requests) + foreach (var req in self.requests) { if (!target.RespondsTo(req)) return Matching.FailedMatch(ctx, target); diff --git a/GraceLanguage/Runtime/Iterables.cs b/GraceLanguage/Runtime/Iterables.cs index e1cdb75..09d0c1d 100644 --- a/GraceLanguage/Runtime/Iterables.cs +++ b/GraceLanguage/Runtime/Iterables.cs @@ -11,6 +11,22 @@ namespace Grace.Runtime /// Encapsulates behaviour relating to iterables public static class Iterables { + internal static Dictionary sharedMethods; + + /// + /// Apply an extension trait to all future instances of this type. + /// + /// + /// Dictionary of methods to add. + /// + public static void ExtendWith(IDictionary meths) + { + if (sharedMethods == null) + sharedMethods = new Dictionary { }; + foreach (var m in meths) + sharedMethods[m.Key] = m.Value; + } + /// /// Execute a block of native code for each element /// of an iterable. @@ -56,6 +72,7 @@ public Concatenated(GraceObject l, GraceObject r) new DelegateMethod1Ctx( new NativeMethod1Ctx(this.Do))); AddMethod("++(_)", Iterables.ConcatMethod); + AddMethods(sharedMethods); TagName = "ConcatenatedIterables"; } @@ -112,6 +129,7 @@ public GraceVariadicList() AddMethod("with(_) do(_)", new DelegateMethodReq( new NativeMethodReq(this.WithDo))); + AddMethods(Iterables.sharedMethods); TagName = "Lineup"; } From f32948fbc5569bf586ad9778365af3dcb578f8a8 Mon Sep 17 00:00:00 2001 From: Isaac Oscar Gariano Date: Wed, 29 Jan 2020 10:02:17 +1300 Subject: [PATCH 5/8] Fixed unitilised variable --- GraceLanguage/Runtime/Iterables.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/GraceLanguage/Runtime/Iterables.cs b/GraceLanguage/Runtime/Iterables.cs index 09d0c1d..676f300 100644 --- a/GraceLanguage/Runtime/Iterables.cs +++ b/GraceLanguage/Runtime/Iterables.cs @@ -11,7 +11,7 @@ namespace Grace.Runtime /// Encapsulates behaviour relating to iterables public static class Iterables { - internal static Dictionary sharedMethods; + internal static Dictionary sharedMethods = new Dictionary { }; /// /// Apply an extension trait to all future instances of this type. @@ -21,8 +21,6 @@ public static class Iterables /// public static void ExtendWith(IDictionary meths) { - if (sharedMethods == null) - sharedMethods = new Dictionary { }; foreach (var m in meths) sharedMethods[m.Key] = m.Value; } From 9111d0d0bea2a8e7884270d60ac42a5c8e438979 Mon Sep 17 00:00:00 2001 From: Isaac Oscar Gariano Date: Wed, 29 Jan 2020 19:13:51 +1300 Subject: [PATCH 6/8] TypeExtension now applies to native types as well --- GraceLanguage/Runtime/GraceType.cs | 33 +++++++------------ GraceLanguage/Runtime/Matching.cs | 1 + .../modules/platform/kernancompiler.cs | 2 +- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/GraceLanguage/Runtime/GraceType.cs b/GraceLanguage/Runtime/GraceType.cs index 07ad29c..295e666 100644 --- a/GraceLanguage/Runtime/GraceType.cs +++ b/GraceLanguage/Runtime/GraceType.cs @@ -6,7 +6,7 @@ namespace Grace.Runtime /// A Grace type literal public class GraceType : GraceObject { - private static Dictionary sharedMethods; + internal static Dictionary sharedMethods = new Dictionary { }; private readonly string name; private List methods = new List(); @@ -15,22 +15,13 @@ public class GraceType : GraceObject /// Name of this type for debugging /// and reporting purposes public GraceType(string name) - : base(createSharedMethods()) { this.name = name; - } - - private static Dictionary createSharedMethods() - { - if (sharedMethods != null) - return sharedMethods; - sharedMethods = new Dictionary - { - { "match(_)", new DelegateMethodTyped1Ctx(Match) }, - { "|(_)", Matching.OrMethod }, - { "&(_)", Matching.AndMethod }, - }; - return sharedMethods; + AddMethod("match(_)", new DelegateMethod1Ctx( + new NativeMethod1Ctx(this.Match))); + AddMethod("|(_)", Matching.OrMethod); + AddMethod("&(_)", Matching.AndMethod); + AddMethods(GraceType.sharedMethods); } /// @@ -41,8 +32,6 @@ private static Dictionary createSharedMethods() /// public static void ExtendWith(IDictionary meths) { - if (sharedMethods == null) - createSharedMethods(); foreach (var m in meths) sharedMethods[m.Key] = m.Value; } @@ -58,12 +47,12 @@ public void Add(SignatureNode n) /// for types /// At present, this matching uses only the method /// names in both the object and the type. - public static GraceObject Match(EvaluationContext ctx, GraceType self, GraceObject target) + public GraceObject Match(EvaluationContext ctx, GraceObject target) { - if (self.requests == null) + if (requests == null) { var l = new List(); - foreach (var m in self.methods) + foreach (var m in methods) { var req = new MethodRequest(); foreach (var p in m) @@ -73,9 +62,9 @@ public static GraceObject Match(EvaluationContext ctx, GraceType self, GraceObje } l.Add(req); } - self.requests = l; + requests = l; } - foreach (var req in self.requests) + foreach (var req in requests) { if (!target.RespondsTo(req)) return Matching.FailedMatch(ctx, target); diff --git a/GraceLanguage/Runtime/Matching.cs b/GraceLanguage/Runtime/Matching.cs index 0f28e99..1e24737 100644 --- a/GraceLanguage/Runtime/Matching.cs +++ b/GraceLanguage/Runtime/Matching.cs @@ -127,6 +127,7 @@ public NativeTypePattern() AddMethod("match(_)", new DelegateMethod1Ctx(mMatch)); AddMethod("|(_)", Matching.OrMethod); AddMethod("&(_)", Matching.AndMethod); + AddMethods(GraceType.sharedMethods); } /// Native method for Grace match diff --git a/GraceLanguage/modules/platform/kernancompiler.cs b/GraceLanguage/modules/platform/kernancompiler.cs index 7c1b20b..39e0eff 100644 --- a/GraceLanguage/modules/platform/kernancompiler.cs +++ b/GraceLanguage/modules/platform/kernancompiler.cs @@ -24,7 +24,7 @@ public static GraceObject Instantiate( public ExposedCompiler() : base("platform/kernancompiler") { AddMethod("parse(_)", new DelegateMethod1(code => mParse(GraceString.Create("source code"), code))); - AddMethod("parse(_, _)", + AddMethod("parse(_,_)", new DelegateMethodReq((ctx, req) => { MethodHelper.CheckArity(ctx, req, 2); return mParse(req[0].Arguments[0], req[0].Arguments[1]); })); From e61635a8a506a4016ed5eb8ee42128cde14da1ca Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 3 Feb 2020 12:08:14 +1300 Subject: [PATCH 7/8] Allow catching of parse failures --- GraceLanguage/Runtime/GraceObjectProxy.cs | 7 ++++++- .../modules/platform/kernancompiler.cs | 20 +++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/GraceLanguage/Runtime/GraceObjectProxy.cs b/GraceLanguage/Runtime/GraceObjectProxy.cs index d24bd9d..b61b3e4 100644 --- a/GraceLanguage/Runtime/GraceObjectProxy.cs +++ b/GraceLanguage/Runtime/GraceObjectProxy.cs @@ -114,7 +114,12 @@ public override GraceObject Request(EvaluationContext ctx, MethodRequest req) }, "LookupError: Native proxy failed to find method «${method}»" ); - return GraceObjectProxy.Create(meth.Invoke(obj, args)); + try { + return GraceObjectProxy.Create(meth.Invoke(obj, args)); + } catch (TargetInvocationException ex) { + System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); + throw null; // Unreachable + } } private static object viewAsNative(Object obj) diff --git a/GraceLanguage/modules/platform/kernancompiler.cs b/GraceLanguage/modules/platform/kernancompiler.cs index 39e0eff..08c5029 100644 --- a/GraceLanguage/modules/platform/kernancompiler.cs +++ b/GraceLanguage/modules/platform/kernancompiler.cs @@ -23,11 +23,10 @@ public static GraceObject Instantiate( public ExposedCompiler() : base("platform/kernancompiler") { - AddMethod("parse(_)", new DelegateMethod1(code => mParse(GraceString.Create("source code"), code))); - AddMethod("parse(_,_)", - new DelegateMethodReq((ctx, req) => { + AddMethod("parse(_)", new DelegateMethod1Ctx((ctx, code) => mParse(ctx, GraceString.Create("source code"), code))); + AddMethod("parse(_,_)", new DelegateMethodReq((ctx, req) => { MethodHelper.CheckArity(ctx, req, 2); - return mParse(req[0].Arguments[0], req[0].Arguments[1]); })); + return mParse(ctx, req[0].Arguments[0], req[0].Arguments[1]); })); AddMethod("parseFile(_)", new DelegateMethod1(mParseFile)); AddMethod("readGraceModule(_)", new DelegateMethod1Ctx(mReadGraceModule)); AddMethod("translateFile(_)", new DelegateMethod1(mTranslateFile)); @@ -36,11 +35,20 @@ public ExposedCompiler() : base("platform/kernancompiler") () => GraceVariadicList.Of(UnusedArguments.UnusedArgs.Select(GraceString.Create)))); } - private GraceObject mParse(GraceObject gmodulename, GraceObject gcode) + private GraceObject mParse(EvaluationContext ctx, GraceObject gmodulename, GraceObject gcode) { String modulename = gmodulename.FindNativeParent().Value; String code = gcode.FindNativeParent().Value; - return new GraceObjectProxy(new Parser(modulename, code)); + try { + bool sup = ErrorReporting.SuppressAllErrors; + ErrorReporting.SuppressAllErrors = true; // Don't print error messages, as we will forward them to grace + var res = new GraceObjectProxy(new Parser(modulename, code).Parse()); + ErrorReporting.SuppressAllErrors = sup; // Restore old value + return res; + } catch (StaticErrorException exc) { + GraceExceptionPacket.Throw("StaticError", $"{exc.Code}: {exc.Message}; at line {exc.Line}", ctx.GetStackTrace()); + throw null; // unreachable! + } } private GraceObject mParseFile(GraceObject gpath) From 123bf4bde3224508ad6ba9bb9aef0c2750a0ab42 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 9 Mar 2020 12:27:37 +1300 Subject: [PATCH 8/8] Increase stack size --- GraceLanguage/Execution/Interpreter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GraceLanguage/Execution/Interpreter.cs b/GraceLanguage/Execution/Interpreter.cs index aeaafde..cc0aa76 100644 --- a/GraceLanguage/Execution/Interpreter.cs +++ b/GraceLanguage/Execution/Interpreter.cs @@ -702,7 +702,7 @@ public static GraceObject BaseTryCatchFinally(EvaluationContext ctx, /// public int NestRequest(string module, int line, string name) { - if (callStackMethod.Count > 511) { + if (callStackMethod.Count > 1023) { ErrorReporting.RaiseError(this, "R2024", new Dictionary(), "RecursionError: maximum call stack size exceeded."