Esempio n. 1
0
        /// <summary>Load a module file</summary>
        private GraceObject loadNativeModule(string path)
        {
            Interpreter.Debug("========== LOAD " + path + " ==========");
            var dll = Assembly.LoadFile(path);

            foreach (var t in dll.GetExportedTypes())
            {
                foreach (var a in t.GetCustomAttributes(false))
                {
                    if (a is ModuleEntryPoint)
                    {
                        var m = t.GetMethod("Instantiate");
                        return((GraceObject)m.Invoke(null, new Object[1] {
                            this
                        }));
                    }
                }
            }
            ErrorReporting.RaiseError(this, "R2005",
                                      new Dictionary <string, string> {
                { "path", path }
            },
                                      "LookupError: Could not find module ${path}");
            return(null);
        }
Esempio n. 2
0
        /// <inheritdoc/>
        public override GraceObject Respond(
            EvaluationContext ctx,
            GraceObject self,
            MethodRequest req
            )
        {
            checkAccessibility(ctx, req);
            var arg = req[1].Arguments[0];

            if (Type != null)
            {
                if (Matching.TryMatch(ctx, Type, arg, out GraceObject result))
                {
                    arg = result;
                }
                else
                {
                    ErrorReporting.RaiseError(ctx, "R2025",
                                              new Dictionary <string, string> {
                        { "field", req[0].Name },
                        { "required", GraceString.AsNativeString(ctx, Type) }
                    },
                                              "TypeError: ${field} can only hold ${required}.");
                }
            }

            var tmp = cell.Value;

            cell.Value = arg;
            return(tmp);
        }
Esempio n. 3
0
        private static GraceObject mAt(EvaluationContext ctx,
                                       MethodRequest req,
                                       StringCodepoints self)
        {
            MethodHelper.CheckArity(ctx, req, 1);
            var oth = req[0].Arguments[0].FindNativeParent <GraceNumber>();

            if (oth == null)
            {
                ErrorReporting.RaiseError(ctx, "R2001",
                                          new Dictionary <string, string> {
                    { "method", req.Name },
                    { "index", "1" },
                    { "part", req.Name },
                    { "required", "Number" },
                }, "ArgumentTypeError: Index must be a number");
            }
            int idx = oth.GetInt() - 1;

            if (idx >= self.codepoints.Length || idx < 0)
            {
                ErrorReporting.RaiseError(ctx, "R2013",
                                          new Dictionary <string, string> {
                    { "index", "" + (idx + 1) },
                    { "valid", self.codepoints.Length > 0 ?
                      "1 .. " + self.codepoints.Length
                                : "none (empty)" }
                }, "IndexError: Index out of range");
            }
            if (self.codepoints[idx] == null)
            {
                self.codepoints[idx] = CodepointObject.Create(self.utf32[idx]);
            }
            return(self.codepoints[idx]);
        }
Esempio n. 4
0
        /// <summary>Native method for Grace ||</summary>
        /// <param name="ctx">Current interpreter</param>
        /// <param name="other">Argument to the method</param>
        public GraceObject OrOr(EvaluationContext ctx, GraceObject other)
        {
            GraceBoolean oth = other as GraceBoolean;

            if (oth != null)
            {
                return(GraceBoolean.Create(this.Boolean || oth.Boolean));
            }
            GraceObjectProxy op = other as GraceObjectProxy;

            if (op != null)
            {
                return(GraceBoolean.Create(this.Boolean || (dynamic)op.Object));
            }
            ErrorReporting.RaiseError(ctx, "R2001",
                                      new Dictionary <string, string>()
            {
                { "method", "||" },
                { "index", "1" },
                { "part", "||" },
                { "required", "Boolean" }
            },
                                      "ArgumentTypeError: || requires a Boolean argument"
                                      );
            return(GraceBoolean.False);
        }
Esempio n. 5
0
        private static GraceObject mAt(
            EvaluationContext ctx,
            GraceString self,
            GraceObject other
            )
        {
            var oth = other.FindNativeParent <GraceNumber>();

            if (oth == null)
            {
                return(GraceString.Create("bad index"));
            }
            int idx = oth.GetInt() - 1;

            if (idx >= self.graphemeIndices.Length || idx < 0)
            {
                ErrorReporting.RaiseError(ctx, "R2013",
                                          new Dictionary <string, string> {
                    { "index", "" + (idx + 1) },
                    { "valid", self.graphemeIndices.Length > 0 ?
                      "1 .. " + self.graphemeIndices.Length
                                : "none (empty)" }
                }, "Index must be a number");
            }
            int start = self.graphemeIndices[idx];

            return(GraceString.Create(
                       StringInfo.GetNextTextElement(self.Value, start)));
        }
Esempio n. 6
0
 /// <summary>Confirm that this method can be accessed through
 /// the given request in this context</summary>
 /// <remarks>If this method is confidential and the request is
 /// not an interior one with privileged access, this method
 /// will raise a Grace exception reporting an accessibility
 /// violation.</remarks>
 /// <param name="ctx">Current interpreter</param>
 /// <param name="req">Request to check</param>
 protected virtual void checkAccessibility(EvaluationContext ctx,
                                           MethodRequest req)
 {
     if (Conflict)
     {
         ErrorReporting.RaiseError(ctx, "R2022",
                                   new Dictionary <string, string>()
         {
             { "method", req.Name }
         },
                                   "InheritanceError: Method ${method} is a conflict."
                                   );
     }
     if (Abstract)
     {
         ErrorReporting.RaiseError(ctx, "R2021",
                                   new Dictionary <string, string>()
         {
             { "method", req.Name }
         },
                                   "InheritanceError: Method ${method} is abstract."
                                   );
     }
     if (Confidential && !req.IsInterior)
     {
         ErrorReporting.RaiseError(ctx, "R2003",
                                   new Dictionary <string, string>()
         {
             { "method", req.Name }
         },
                                   "AccessibilityError: Method ${method} is confidential"
                                   );
     }
 }
Esempio n. 7
0
        private static GraceObject substringFromTo(
            EvaluationContext ctx,
            MethodRequest req,
            GraceString self
            )
        {
            MethodHelper.CheckArity(ctx, req, 1, 1);
            // Index of first grapheme to include.
            var start = req[0].Arguments[0];
            // Index of last grapheme to include.
            var end = req[1].Arguments[0];
            var st  = start.FindNativeParent <GraceNumber>();

            if (st == null)
            {
                ErrorReporting.RaiseError(ctx, "R2001",
                                          new Dictionary <string, string> {
                    { "method", req.Name },
                    { "index", "1" },
                    { "part", "substringFrom" }
                }, "Start must be a number");
            }
            var en = end.FindNativeParent <GraceNumber>();

            if (en == null)
            {
                ErrorReporting.RaiseError(ctx, "R2001",
                                          new Dictionary <string, string> {
                    { "method", req.Name },
                    { "index", "1" },
                    { "part", "to" }
                }, "End must be a number");
            }
            // Because, e.g., substringFrom(1) to(1) should return the
            // first grapheme, the start value must be adjusted for
            // base-one indexing, but the end value must not be.
            int stInd = st.GetInt() - 1;
            int enInd = en.GetInt();

            if (stInd < 0)
            {
                stInd = 0;
            }
            if (enInd < 0)
            {
                enInd = 0;
            }
            if (enInd >= self.graphemeIndices.Length)
            {
                enInd = self.graphemeIndices.Length;
            }
            int endIndex = enInd < self.graphemeIndices.Length
                ? self.graphemeIndices[enInd]
                : self.Value.Length;

            stInd = self.graphemeIndices[stInd];
            return(GraceString.Create(self.Value.Substring(stInd,
                                                           endIndex - stInd)));
        }
Esempio n. 8
0
 /// <summary>
 /// Raise an error if the user is trying to inherit from
 /// this method.
 /// </summary>
 /// <param name="ctx">Current interpreter</param>
 /// <param name="req">Method request to check</param>
 public static void CheckNoInherits(EvaluationContext ctx,
                                    MethodRequest req)
 {
     if (req.IsInherits)
     {
         ErrorReporting.RaiseError(ctx, "R2017",
                                   new Dictionary <string, string> {
             { "method", req.Name }
         },
                                   "InheritanceError: Invalid inheritance"
                                   );
     }
 }
Esempio n. 9
0
 /// <inheritdoc />
 public int NestRequest(string module, int line, string name)
 {
     if (callStackMethod.Count > 511)
     {
         ErrorReporting.RaiseError(this, "R2024",
                                   new Dictionary <string, string>(),
                                   "RecursionError: maximum call stack size exceeded."
                                   );
     }
     callStackMethod.Push(name);
     callStackModule.Push(module);
     callStackLine.Push(line);
     return(callStackMethod.Count - 1);
 }
Esempio n. 10
0
        /// <summary>
        /// Load a resource file
        /// </summary>
        /// <param name="filePath">Filesystem path to resource</param>
        /// <param name="importPath">Import path used to reach resource</param>
        private GraceObject loadResource(string filePath, string importPath)
        {
            var ext = Path.GetExtension(importPath);

            if (ext == ".txt")
            {
                return(GraceString.Create(File.OpenText(filePath).ReadToEnd()));
            }
            ErrorReporting.RaiseError(this, "R2010",
                                      new Dictionary <string, string> {
                { "path", importPath },
                { "extension", ext }
            },
                                      "LookupError: No resource handler for ${importPath}");
            return(null);
        }
Esempio n. 11
0
 private static void checkIndex(
     EvaluationContext ctx,
     int i,
     GraceObject[] data
     )
 {
     if (i < 0 || i >= data.Length)
     {
         ErrorReporting.RaiseError(ctx, "R2013",
                                   new Dictionary <string, string> {
             { "index", "" + i },
             { "valid", "0.." + (data.Length - 1) }
         },
                                   "IndexError: Invalid index " + i
                                   );
     }
 }
Esempio n. 12
0
 /// <summary>
 /// Attempt to match a pattern, raising R2025 TypeError on failure.
 /// </summary>
 /// <param name="ctx">Current interpreter</param>
 /// <param name="pattern">Pattern to match against</param>
 /// <param name="target">Object to examine</param>
 /// <param name="name">Name to report in error (e.g. field or parameter name)</param>
 /// <returns></returns>
 public static GraceObject TypeMatch(EvaluationContext ctx, GraceObject pattern, GraceObject target, string name)
 {
     if (Matching.TryMatch(ctx, pattern, target, out var result))
     {
         return(result);
     }
     else
     {
         ErrorReporting.RaiseError(ctx, "R2025",
                                   new Dictionary <string, string> {
             { "field", name },
             { "required", GraceString.AsNativeString(ctx, pattern) }
         },
                                   "TypeError: argument type mismatch");
         return(null);
     }
 }
Esempio n. 13
0
        /// <summary>Native method for Grace /</summary>
        /// <param name="ctx">Current interpreter</param>
        /// <param name="self">Receiver of the method</param>
        /// <param name="other">Argument to the method</param>
        private static GraceObject mDivide(
            EvaluationContext ctx,
            GraceNumber self,
            GraceObject other
            )
        {
            var oth = other.FindNativeParent <GraceNumber>();

            if (oth.Value == Rational.Zero)
            {
                ErrorReporting.RaiseError(ctx, "R2012",
                                          new Dictionary <string, string> {
                    { "dividend", self.Value.ToString() },
                },
                                          "ZeroDivisionError: Division by zero.");
            }
            return(GraceNumber.Create(self.Value / oth.Value));
        }
Esempio n. 14
0
        private GraceObject mDotDot(EvaluationContext ctx, GraceObject step)
        {
            var n = step.FindNativeParent <GraceNumber>();

            if (n == null)
            {
                ErrorReporting.RaiseError(ctx, "R2001",
                                          new Dictionary <string, string> {
                    { "method", ".." },
                    { "index", "1" },
                    { "part", ".." },
                    { "required", "Number" }
                },
                                          "ArgumentTypeError: .. requires a Number argument"
                                          );
            }
            return(new GraceRange(_low, _high, _step * n.Value));
        }
Esempio n. 15
0
        private static GraceObject mConcat(EvaluationContext ctx,
                                           MethodRequest req,
                                           StringCodepoints self)
        {
            MethodHelper.CheckArity(ctx, req, 1);
            var oth = req[0].Arguments[0].FindNativeParent <StringCodepoints>();

            if (oth == null)
            {
                ErrorReporting.RaiseError(ctx, "R2001",
                                          new Dictionary <string, string> {
                    { "method", req.Name },
                    { "index", "1" },
                    { "part", req.Name },
                    { "required", "codepoints" },
                }, "ArgumentTypeError: Needed codepoints object");
            }
            return(new StringCodepoints(self.utf32.Concat(oth.utf32)));
        }
Esempio n. 16
0
 /// <summary>Return a value from this method</summary>
 /// <param name="ctx">Current interpreter</param>
 /// <param name="val">Return value</param>
 /// <param name="ret">Return statement</param>
 /// <exception cref="ReturnException">Always thrown to indicate a
 /// return from a Grace method</exception>
 public void Return(EvaluationContext ctx, GraceObject val,
                    Node ret)
 {
     if (completed)
     {
         // Put the return statement into the call stack
         // so that its location is shown to the user, even
         // though it isn't actually a method request.
         ctx.NestRequest(ret.Location.Module,
                         ret.Location.line, "return");
         ErrorReporting.RaiseError(ctx, "R2009",
                                   new Dictionary <string, string> {
             { "method", Name }
         },
                                   "IllegalReturnError: Method «" + Name
                                   + "» already returned");
     }
     completed = true;
     throw new ReturnException(this, val);
 }
Esempio n. 17
0
        private GraceObject mAt(EvaluationContext ctx, GraceObject index)
        {
            var num = index.FindNativeParent <GraceNumber>();
            var i   = (int)num.Double;

            checkIndex(ctx, i, data);
            var ret = data[i];

            if (ret == null)
            {
                ErrorReporting.RaiseError(ctx, "R2008",
                                          new Dictionary <string, string> {
                    { "name", "index " + i },
                    { "receiver", ToString() }
                },
                                          "UninitialisedReadError: Cannot read from index " + i
                                          );
            }
            return(ret);
        }
Esempio n. 18
0
        /// <summary>
        /// Request a method of this object in a given
        /// context with a particular receiver identity
        /// </summary>
        /// <param name="ctx">Current interpreter</param>
        /// <param name="req">Request</param>
        /// <param name="receiver">Receiver identity</param>
        /// <returns>Return value of the resolved method</returns>
        public virtual GraceObject Request(EvaluationContext ctx,
                                           MethodRequest req,
                                           GraceObject receiver)
        {
            var m = FindMethod(req.Name);

            if (m == null)
            {
                ErrorReporting.RaiseError(ctx, "R2000",
                                          new Dictionary <string, string> {
                    { "method", req.Name },
                    { "receiver", ToString() }
                },
                                          "LookupError: Method «" + req.Name +
                                          "» not found.");
            }
            var ret = m.Respond(ctx, receiver, req);

            return(ret);
        }
Esempio n. 19
0
        /// <summary>Native method for Grace ifTrue ifFalse</summary>
        /// <param name="ctx">Current interpreter</param>
        /// <param name="req">Method request that gave rise to this method
        /// execution</param>
        public GraceObject IfTrueIfFalse(EvaluationContext ctx,
                                         MethodRequest req)
        {
            MethodHelper.CheckArity(ctx, req, 1, 1);
            var trueBlock  = req[0].Arguments[0];
            var falseBlock = req[1].Arguments[0];

            if (!(trueBlock is GraceBlock))
            {
                ErrorReporting.RaiseError(ctx, "R2001",
                                          new Dictionary <string, string>()
                {
                    { "method", req.Name },
                    { "index", "1" },
                    { "part", "ifTrue" },
                    { "required", "Block" }
                },
                                          "ArgumentTypeError: ifTrue ifFalse requires two block arguments"
                                          );
            }
            if (!(falseBlock is GraceBlock))
            {
                ErrorReporting.RaiseError(ctx, "R2001",
                                          new Dictionary <string, string>()
                {
                    { "method", req.Name },
                    { "index", "1" },
                    { "part", "ifFalse" },
                    { "required", "Block" }
                },
                                          "ArgumentTypeError: ifTrue ifFalse requires two block arguments"
                                          );
            }
            var apply = MethodRequest.Nullary("apply");

            if (Boolean)
            {
                return(trueBlock.Request(ctx, apply));
            }
            return(falseBlock.Request(ctx, apply));
        }
Esempio n. 20
0
        private static GraceObject mAt(EvaluationContext ctx,
                                       MethodRequest req,
                                       UTF32CodepointsView self)
        {
            MethodHelper.CheckArity(ctx, req, 1);
            var arg   = req[0].Arguments[0];
            var index = arg.FindNativeParent <GraceNumber>();
            var idx   = index.GetInt() - 1;

            if (idx < 0 || idx >= self.utf32.Count)
            {
                ErrorReporting.RaiseError(ctx, "R2013",
                                          new Dictionary <string, string> {
                    { "index", "" + (idx + 1) },
                    { "valid", self.utf32.Count > 0 ?
                      "1 .. " + self.utf32.Count
                                : "none (empty)" }
                }, "IndexError: Index out of range");
            }
            return(GraceNumber.Create(self.utf32[idx]));
        }
Esempio n. 21
0
        private static GraceObject mAt(EvaluationContext ctx,
                                       MethodRequest req,
                                       ByteString self)
        {
            MethodHelper.CheckArity(ctx, req, 1);
            var arg   = req[0].Arguments[0];
            var index = arg.FindNativeParent <GraceNumber>();
            var idx   = index.GetInt() - 1;

            if (idx < 0 || idx >= self.data.Length)
            {
                ErrorReporting.RaiseError(ctx, "R2013",
                                          new Dictionary <string, string> {
                    { "index", "" + (idx + 1) },
                    { "valid", self.data.Length > 0 ?
                      "1 .. " + self.data.Length
                                : "none (empty)" }
                }, "IndexError: Index out of range");
            }
            return(getByteObject(self.data[idx]));
        }
Esempio n. 22
0
        /// <summary>Native method for Grace ..</summary>
        /// <param name="ctx">Current interpreter</param>
        /// <param name="self">Receiver of the method</param>
        /// <param name="other">Argument to the method</param>
        private static GraceObject mDotDot(
            EvaluationContext ctx,
            GraceNumber self,
            GraceObject other
            )
        {
            var n = other.FindNativeParent <GraceNumber>();

            if (n == null)
            {
                ErrorReporting.RaiseError(ctx, "R2001",
                                          new Dictionary <string, string> {
                    { "method", ".." },
                    { "index", "1" },
                    { "part", ".." },
                    { "required", "Number" }
                },
                                          "ArgumentTypeError: .. requires a Number argument"
                                          );
            }
            return(new GraceRange(self.Value, n.Value, 1));
        }
Esempio n. 23
0
 /// <inheritdoc/>
 public override GraceObject Respond(
     EvaluationContext ctx,
     GraceObject self,
     MethodRequest req
     )
 {
     checkAccessibility(ctx, req);
     MethodHelper.CheckNoInherits(ctx, req);
     MethodNode.CheckArgCount(ctx, req.Name, req.Name,
                              0, false,
                              req[0].Arguments.Count);
     if (cell.Value == GraceObject.Uninitialised)
     {
         ErrorReporting.RaiseError(ctx, "R2008",
                                   new Dictionary <string, string> {
             { "name", req.Name },
             { "receiver", self.ToString() }
         },
                                   "UninitialisedReadError: Cannot read from " + req.Name
                                   );
     }
     return(cell.Value);
 }
Esempio n. 24
0
        private static GraceObject mConcat(EvaluationContext ctx,
                                           MethodRequest req,
                                           ByteString self)
        {
            MethodHelper.CheckArity(ctx, req, 1);
            var oth = req[0].Arguments[0].FindNativeParent <ByteString>();

            if (oth == null)
            {
                ErrorReporting.RaiseError(ctx, "R2001",
                                          new Dictionary <string, string> {
                    { "method", req.Name },
                    { "index", "1" },
                    { "part", req.Name },
                    { "required", "byte string" },
                }, "ArgumentTypeError: Needed byte string");
            }
            var d2 = new byte[self.data.Length + oth.data.Length];

            self.data.CopyTo(d2, 0);
            oth.data.CopyTo(d2, self.data.Length);
            return(new ByteString(d2));
        }
Esempio n. 25
0
        /// <inheritdoc/>
        /// <remarks>This method uses the indexer on the LocalScope
        /// object the method was requested on.</remarks>
        public override GraceObject Respond(EvaluationContext ctx, GraceObject self, MethodRequest req)
        {
            checkAccessibility(ctx, req);
            MethodHelper.CheckNoInherits(ctx, req);
            MethodNode.CheckArgCount(ctx, req.Name, req.Name,
                                     0, false,
                                     req[0].Arguments.Count);
            LocalScope s    = self as LocalScope;
            string     name = req.Name;

            if (s[name] == GraceObject.Uninitialised ||
                s[name] == null)
            {
                ErrorReporting.RaiseError(ctx, "R2008",
                                          new Dictionary <string, string> {
                    { "name", name },
                    { "receiver", ToString() }
                },
                                          "UninitialisedReadError: Cannot read from «" + name + "»"
                                          );
            }
            return(s[name]);
        }
Esempio n. 26
0
        /// <summary>Native method for Grace orElse</summary>
        /// <param name="ctx">Current interpreter</param>
        /// <param name="other">Block to apply if false</param>
        public GraceObject OrElse(EvaluationContext ctx, GraceObject other)
        {
            var oth = other as GraceBlock;

            if (oth == null)
            {
                ErrorReporting.RaiseError(ctx, "R2001",
                                          new Dictionary <string, string>()
                {
                    { "method", "orElse" },
                    { "index", "1" },
                    { "part", "ifFalse" },
                    { "required", "Block" }
                },
                                          "ArgumentTypeError: orElse requires a block argument"
                                          );
            }
            if (!Boolean)
            {
                var req = MethodRequest.Nullary("apply");
                return(other.Request(ctx, req));
            }
            return(True);
        }
Esempio n. 27
0
        /// <inheritdoc />
        /// <remarks>The import path will be resolved according to
        /// the directories given by
        /// <c cref="GetModulePaths">GetModulePaths</c>. If this import
        /// path has been loaded previously, the existing module object
        /// is returned.</remarks>
        public GraceObject LoadModule(string path)
        {
            if (modules.ContainsKey(path))
            {
                return(modules[path]);
            }
            importStack.Push(path);
            if (importedPaths.Contains(path))
            {
                var chain = String.Join(" -> ", importStack.Reverse());
                ErrorReporting.RaiseError(this, "R2011",
                                          new Dictionary <string, string> {
                    { "path", path },
                    { "chain", chain }
                },
                                          "CyclicImportError: Module ${path} imports itself.");
            }
            importedPaths.Add(path);
            var name       = Path.GetFileName(path);
            var isResource = name.Contains('.');
            var bases      = GetModulePaths();

            try
            {
                foreach (var p in bases)
                {
                    string      filePath;
                    GraceObject mod;
                    if (isResource)
                    {
                        filePath = Path.Combine(p, path);
                        mod      = tryLoadResource(filePath, path);
                        if (mod != null)
                        {
                            modules[path] = mod;
                            return(mod);
                        }
                        continue;
                    }
                    filePath = Path.Combine(p, path + ".grace");
                    mod      = tryLoadModuleFile(filePath, path);
                    if (mod != null)
                    {
                        modules[path] = mod;
                        return(mod);
                    }
                    filePath = Path.Combine(p, path + ".dll");
                    mod      = tryLoadNativeModule(filePath);
                    if (mod != null)
                    {
                        modules[path] = mod;
                        return(mod);
                    }
                }
                if (FailedImportHook != null)
                {
                    // Optionally, the host program can try to satisfy a module
                    // and indicate that we should retry the import.
                    if (FailedImportHook(path, this))
                    {
                        importedPaths.Remove(path);
                        importStack.Pop();
                        return(LoadModule(path));
                    }
                }
            }
            finally
            {
                importStack.Pop();
            }
            ErrorReporting.RaiseError(this, "R2005",
                                      new Dictionary <string, string> {
                { "path", path }
            },
                                      "LookupError: Could not find module ${path}");
            return(null);
        }
Esempio n. 28
0
        /// <inheritsdoc/>
        /// <remarks>Uses reflection to access the method, or the
        /// dynamic type to access operators.</remarks>
        public override GraceObject Request(EvaluationContext ctx, MethodRequest req)
        {
            string name = req.Name;

            switch (name)
            {
            case "isNull":
                if (obj == null)
                {
                    return(GraceBoolean.True);
                }
                return(GraceBoolean.False);

            case "+(_)":
                return(GraceObjectProxy.Create((dynamic)obj + (dynamic)viewAsNative(req[0].Arguments[0])));

            case "-(_)":
                return(GraceObjectProxy.Create((dynamic)obj - (dynamic)viewAsNative(req[0].Arguments[0])));

            case "*(_)":
                return(GraceObjectProxy.Create((dynamic)obj * (dynamic)viewAsNative(req[0].Arguments[0])));

            case "/(_)":
                return(GraceObjectProxy.Create((dynamic)obj / (dynamic)viewAsNative(req[0].Arguments[0])));

            case "<(_)":
                return(GraceObjectProxy.Create((dynamic)obj < (dynamic)viewAsNative(req[0].Arguments[0])));

            case "<=(_)":
                return(GraceObjectProxy.Create((dynamic)obj <= (dynamic)viewAsNative(req[0].Arguments[0])));

            case ">(_)":
                return(GraceObjectProxy.Create((dynamic)obj > (dynamic)viewAsNative(req[0].Arguments[0])));

            case ">=(_)":
                return(GraceObjectProxy.Create((dynamic)obj >= (dynamic)viewAsNative(req[0].Arguments[0])));

            case "==(_)":
                return(GraceObjectProxy.Create((dynamic)obj == (dynamic)viewAsNative(req[0].Arguments[0])));

            case "!=(_)":
                return(GraceObjectProxy.Create((dynamic)obj != (dynamic)viewAsNative(req[0].Arguments[0])));

            case "%(_)":
                return(GraceObjectProxy.Create((dynamic)obj % (dynamic)viewAsNative(req[0].Arguments[0])));

            case "^(_)":
                return(GraceObjectProxy.Create(Math.Pow((dynamic)obj, (dynamic)viewAsNative(req[0].Arguments[0]))));

            case "asString":
                if (obj == null)
                {
                    return(GraceString.Create("(null)"));
                }
                return(GraceString.Create(obj.ToString()));

            case "prefix!":
                return(GraceObjectProxy.Create(!(dynamic)obj));

            case "at(_)":
                if (Interpreter.JSIL)
                {
                    // Calling get_Item directly is iffy, but
                    // works on JSIL where accessing Item fails,
                    // and [] uses native (the wrong) [].
                    return(GraceObjectProxy.Create(
                               ((dynamic)obj)
                               .get_Item(
                                   (dynamic)viewAsNative(req[0].Arguments[0]))
                               ));
                }
                return(GraceObjectProxy.Create(
                           ((dynamic)obj)[
                               (dynamic)viewAsNative(req[0].Arguments[0])]));
            }
            object[] args = new object[req[0].Arguments.Count];
            for (int i = 0; i < req[0].Arguments.Count; i++)
            {
                args[i] = viewAsNative(req[0].Arguments[i]);
            }
            Type[] types = new Type[args.Length];
            for (int i = 0; i < types.Length; i++)
            {
                types[i] = args[i].GetType();
            }
            MethodInfo meth = type.GetMethod(name, types);

            if (meth == null)
            {
                ErrorReporting.RaiseError(ctx, "R2000",
                                          new Dictionary <string, string>()
                {
                    { "method", req.Name },
                    { "receiver", "Native Proxy" }
                },
                                          "LookupError: Native proxy failed to find method «${method}»"
                                          );
            }
            return(GraceObjectProxy.Create(meth.Invoke(obj, args)));
        }
Esempio n. 29
0
        /// <summary>Native version of the built-in Grace
        /// "try-*catch-?finally" method
        /// </summary>
        public static GraceObject BaseTryCatchFinally(EvaluationContext ctx,
                                                      MethodRequest req)
        {
            Interpreter.ScopeMemo memo = ctx.Memorise();
            GraceObject           tryBlock;
            GraceObject           finallyBlock;
            var catchBlocks = new List <GraceObject>();

            tryBlock     = req[0].Arguments[0];
            finallyBlock = req[0].Arguments[1];
            for (int i = 2; i < req[0].Arguments.Count; i++)
            {
                catchBlocks.Add(req[0].Arguments[i]);
            }
            var ret    = GraceObject.Done;
            var caught = true;

            try
            {
                ret = tryBlock.Request(ctx, MethodRequest.Nullary("apply"));
            }
            catch (GraceExceptionPacketException e)
            {
                ctx.RestoreExactly(memo);
                GraceObject   gep      = e.ExceptionPacket;
                MethodRequest matchReq = MethodRequest.Single("match",
                                                              gep);
                caught = false;
                foreach (var cb in catchBlocks)
                {
                    var mr = cb.Request(ctx, matchReq);
                    if (Matching.Succeeded(ctx, mr))
                    {
                        caught = true;
                        ret    = mr.Request(ctx,
                                            MethodRequest.Nullary("result"));
                        break;
                    }
                }
                if (!caught)
                {
                    throw;
                }
            }
            finally
            {
                ctx.RestoreExactly(memo);
                if (finallyBlock != null)
                {
                    if (caught)
                    {
                        finallyBlock.Request(ctx,
                                             MethodRequest.Nullary("apply"));
                    }
                    else
                    {
                        try {
                            finallyBlock.Request(ctx,
                                                 MethodRequest.Nullary("apply"));
                        }
                        catch (ReturnException)
                        {
                            ErrorReporting.RaiseError(ctx, "R2018",
                                                      new Dictionary <string, string>(),
                                                      "IllegalReturnError: From completed finally");
                        }
                    }
                }
            }
            return(ret);
        }