Esempio n. 1
0
        public static object Eval(Evaluator v, InvocationExpr e)
        {
            if (e.Count != 1)
            {
                throw new Exception("`eval` requires 1 parameter");
            }

            var quoteExpr = e[0] as QuoteExpr;

            if (quoteExpr == null)
            {
                throw new Exception("`eval` parameter must be a quoted s-expression");
            }

            return(v.Eval(((QuoteExpr)quoteExpr).SExpr));
        }
Esempio n. 2
0
        public static object If(Evaluator v, InvocationExpr e)
        {
            if (e.Count != 3)
            {
                throw new Exception("`if` requires 3 parameters: condition, then, else");
            }

            var testExpr  = e[0];
            var trueExpr  = e[1];
            var falseExpr = e[2];

            // Eval the test s-expression:
            var test = v.Eval(testExpr);

            if (test == null)
            {
                // Null is logically false:
                return(v.Eval(falseExpr));
            }
            else
            {
                // Check if the test value is a boolean or not:
                if (test is bool)
                {
                    // Test the boolean value:
                    if ((bool)test)
                    {
                        return(v.Eval(trueExpr));
                    }
                    else
                    {
                        return(v.Eval(falseExpr));
                    }
                }
                else if (!test.GetType().IsValueType)
                {
                    // Non-null reference is logically true:
                    return(v.Eval(trueExpr));
                }
                else
                {
                    throw new Exception("`if` condition parameter must be a boolean or reference type");
                }
            }
        }
Esempio n. 3
0
        public static object Ne(Evaluator v, InvocationExpr e)
        {
            if (e.Count != 2)
            {
                throw new Exception("`ne` requires 2 parameters");
            }

            var a = v.Eval(e[0]);
            var b = v.Eval(e[1]);

            if (a == null && b == null)
            {
                return(false);
            }
            else if (a == null || b == null)
            {
                return(true);
            }
            else
            {
                return(!a.Equals(b));
            }
        }
Esempio n. 4
0
        public object Invoke(InvocationExpr e)
        {
            if (e.Identifier.Kind == SExprKind.ScopedIdentifier)
            {
                // Check the function name:
                var name = ((ScopedIdentifierExpr)e.Identifier).Name.Text;
                // TODO(jsd): Support CLR property/method invocation for objects!

                // Find the function in the `externs` dictionary:
                ExternFunction func;
                if (!externs.TryGetValue(name, out func))
                {
                    throw new Exception("Undefined function '{0}'".F(name));
                }

                // Execute it:
                return(func(this, e));
            }
            else if (e.Identifier.Kind == SExprKind.StaticMemberIdentifier)
            {
                // Find the type by namespace/class:
                var ident = (StaticMemberIdentifierExpr)e.Identifier;

                var typeName   = String.Join(".", ident.TypeName.Select(ns => ns.Text));
                var memberName = ident.Name.Text;

                var type = Type.GetType(typeName, false);
                if (type == null)
                {
                    throw new Exception("Could not find type by name '{0}'".F(typeName));
                }

                // Member can be either a method or property:

                // Find a method:
                var mt = type.GetMethod(memberName);
                if (mt != null)
                {
                    object[] parms;

                    if (e.Count > 0)
                    {
                        parms = Eval(e.Parameters);
                    }
                    else
                    {
                        parms = null;
                    }

                    // TODO(jsd): handle invocation exception:
                    return(mt.Invoke(null, parms));
                }

                // Find a property:
                var pr = type.GetProperty(memberName);
                if (pr != null)
                {
                    // TODO(jsd): Turn this into a property reference expression so we can (set x) it.
                    if (e.Count > 0)
                    {
                        var parms = Eval(e.Parameters);

                        return(pr.GetValue(null, parms));
                    }
                    else
                    {
                        return(pr.GetValue(null));
                    }
                }

                throw new Exception("Could not find method or property with name '{0}' on instance of type '{1}'".F(memberName, type.FullName));
            }
            else if (e.Identifier.Kind == SExprKind.InstanceMemberIdentifier)
            {
                // Find the type by namespace/class:
                var ident = (InstanceMemberIdentifierExpr)e.Identifier;

                var memberName = ident.Name.Text;

                var instance = Eval(e[0]);
                if (instance == null)
                {
                    throw new Exception("Cannot call method or property '{0}' on a null object instance".F(memberName));
                }

                var type = instance.GetType();

                // Member can be either a method or property:

                // Evaluate parameter expressions:
                var      parmExprs = e.Parameters.Skip(1).ToArray();
                object[] parms;
                Type[]   parmTypes;
                if (parmExprs.Length > 0)
                {
                    parms     = Eval(parmExprs);
                    parmTypes = parms.Select(p => p == null ? (Type)null : p.GetType()).ToArray();
                }
                else
                {
                    parms     = null;
                    parmTypes = Type.EmptyTypes;
                }

                // Find a method:
                var mt = type.GetMethod(memberName, parmTypes);
                if (mt != null)
                {
                    // TODO(jsd): handle invocation exception:
                    return(mt.Invoke(instance, parms));
                }

                // Find a property:
                var pr = type.GetProperty(memberName);
                if (pr != null)
                {
                    // TODO(jsd): Turn this into a property reference expression so we can (set x) it.
                    return(pr.GetValue(instance, parms));
                }

                throw new Exception("Could not find method or property with name '{0}' on instance of type '{1}'".F(memberName, type.FullName));
            }

            throw new Exception("Unknown or unsupported member identifier kind '{0}'".F(e.Identifier.Kind));
        }