예제 #1
0
    public override AstNode ShallowClone()
    {
        var res = new AstObject(Source, Start, End);

        res.Properties.AddRange(Properties.AsReadOnlySpan());
        return(res);
    }
예제 #2
0
        public static AstNode ToAst(object o)
        {
            if (o is AstNode node)
            {
                return(node);
            }
            if (o is string str)
            {
                return(new AstString(str));
            }
            if (o is double num)
            {
                if (double.IsNaN(num))
                {
                    return(AstNaN.Instance);
                }
                if (double.IsPositiveInfinity(num))
                {
                    return(AstInfinity.Instance);
                }
                if (double.IsNegativeInfinity(num))
                {
                    return(AstInfinity.NegativeInstance);
                }
                return(new AstNumber(num));
            }

            if (o is int i)
            {
                return(new AstNumber(i));
            }

            if (o is uint u)
            {
                return(new AstNumber(u));
            }

            if (o is bool b)
            {
                return(b ? AstTrue.Instance : (AstNode)AstFalse.Instance);
            }
            if (o is Dictionary <object, object> dict)
            {
                var res = new AstObject();
                foreach (var pair in dict)
                {
                    res.Properties.Add(new AstObjectKeyVal(ToAst(pair.Key), ToAst(pair.Value)));
                }

                return(res);
            }

            throw new NotImplementedException();
        }
예제 #3
0
        public static string Print(AstObject ao)
        {
            switch (ao)
            {
            case AstAtom aa:
                return(PrintAtom(aa));

            case AstList al:
                return(PrintList(al));

            default:
                throw new Exception("Dafuq?");
            }
        }
예제 #4
0
 private static string Print(AstObject ao)
 {
     return(Printer.Print(ao));
 }
예제 #5
0
 private static AstObject Eval(AstObject ao, Environment env)
 {
     return(Evaluator.Eval(ao, env));
 }
예제 #6
0
        public static AstObject Eval(AstObject ao, Environment env)
        {
            if (ao is AstSymbol a)
            {
                if (env.ContainsKey(a))
                {
                    return(env[a]);
                }
                throw new EvaluationException($"Symbol {a.Represent()} not found");
            }

            if (ao is AstNumber an)
            {
                return(an);
            }
            if (ao is AstBoolean ab)
            {
                return(ab);
            }
            if (ao is AstList al) // TODO: Empty list
            {
                if (al.Objects[0].Equals(new AstSymbol("define")))
                {
                    if (al.Objects.Count == 3 && al.Objects[1] is AstSymbol symbol)
                    {
                        env[symbol] =
                            Eval(al.Objects[2],
                                 env); // TODO: Eager, right or wrong? Lazy did implicit quote - Need later eval for that
                        return(symbol);
                    }
                }

                if (al.Objects[0].Equals(new AstSymbol("if")))
                {
                    if (al.Objects.Count >= 3 && al.Objects.Count <= 4)
                    {
                        var cond = Eval(al.Objects[1], env);
                        if (new AstBoolean(false) != cond)
                        {
                            return(Eval(al.Objects[2], env));
                        }

                        if (al.Objects.Count == 4 && new AstBoolean(false) == cond)
                        {
                            return(Eval(al.Objects[3], env));
                        }

                        return(cond);
                    }
                }

                if (al.Objects[0].Equals(new AstSymbol("lambda")))
                {
                    if (al.Objects.Count == 3 && al.Objects[1] is AstList list)
                    {
                        AstObject Func(List <AstObject> x)
                        {
                            var environment = new Environment(env);

                            for (var index = 0; index < list.Objects.Count; index++)
                            {
                                var argName = list.Objects[index];
                                if (argName is AstSymbol @as)
                                {
                                    if (x.Count > index)
                                    {
                                        environment[@as] = x[index];
                                    }
                                    else
                                    {
                                        throw new EvaluationException("Currying not yet supported");
                                    }
//                                        return
//                                            Eval(new AstList(new AstSymbol("lambda"),
//                                                    new AstList(list.Objects.Take(index + 1).ToList()),
//                                                    al.Objects[2]),
//                                                environment);
                                }
                                else
                                {
                                    throw new EvaluationException(
                                              "Encountered non-symbol in parameter definition list: " + argName.GetType());
                                }
                            }

                            return(Eval(al.Objects[2], environment));
                        }

                        return(new AstFunc(Func));
                    }
                }

                var f    = (AstFunc)Eval(al.Objects[0], env);
                var args = al.Objects.Skip(1).Select(o => Eval(o, env));
                try
                {
                    return(f.F.Invoke(args.ToList()));
                }
                catch (InvalidCastException e)
                {
                    throw new EvaluationException(e.Message);
                }
            }

            Debug.Assert(false, "Encountered unknown AstObject");
            throw new EvaluationException($"Encountered unknown AstObject: {ao}");
        }