Ejemplo n.º 1
0
            public static TrueStack Clone(TrueStack original)
            {
                var arr = new object[original.Count];

                original.CopyTo(arr, 0);
                Array.Reverse(arr);
                return(new TrueStack(arr));
            }
Ejemplo n.º 2
0
        static object VM3(Operation operation, EnviromentFrame e)
        {
            object a   = null;
            var    x   = operation;
            var    rib = 0;

            var trueStack = new TrueStack(100);

            while (true)
            {
                switch (x.Cmd)
                {
                case Operation.Comand.Halt:
                    return(a);

                case Operation.Comand.Refer: {
                    a = e.Get(x.Var);
                    x = x.Branch1;
                    break;
                }

                case Operation.Comand.Constant: {
                    a = x.Value;
                    x = x.Branch1;
                    break;
                }

                case Operation.Comand.Close: {
                    a = new Closure(x.Branch2, e, x.Vars);
                    x = x.Branch1;
                    break;
                }

                case Operation.Comand.Test: {
                    x = GetSBool(a) == false ? x.Branch2 : x.Branch1;
                    break;
                }

                case Operation.Comand.Assign: {
                    e.Set(x.Var, a);
                    x = x.Branch1;
                    break;
                }

                case Operation.Comand.Extend: {
                    e.Define(x.Var, a);
                    x = x.Branch1;
                    break;
                }

                case Operation.Comand.Conti: {
                    var var = "v".O3Symbol();
                    a = new Closure(Operation.Nuate(TrueStack.Clone(trueStack), var), new EnviromentFrame(), new [] { var });
                    x = x.Branch1;
                    break;
                }

                case Operation.Comand.Nuate: {
                    trueStack = TrueStack.Clone(x.Value as TrueStack);
                    a         = e.Get(x.Var);
                    x         = Operation.Return();
                    break;
                }

                case Operation.Comand.Frame: {
                    trueStack.Push(rib);
                    trueStack.Push(e);
                    trueStack.Push(x.Branch2);

                    x = x.Branch1;

                    rib = 0;
                    break;
                }

                case Operation.Comand.Argument: {
                    trueStack.Push(a);
                    x = x.Branch1;
                    rib++;
                    break;
                }

                case Operation.Comand.Apply: {
                    if (a is MulticastDelegate)
                    {
                        var func       = a as MulticastDelegate;
                        var parameters = func.Method.GetParameters();

                        var argCnt = 0;
                        var cArg   = new List <object>();
                        foreach (var pi in parameters)
                        {
                            if (typeof(Params) == pi.ParameterType)
                            {
                                var par = new Params();
                                while (argCnt++ < rib)
                                {
                                    par.Add(trueStack.Pop());
                                }
                                cArg.Add(par);
                            }
                            else
                            {
                                if (argCnt++ < rib)
                                {
                                    cArg.Add(trueStack.Pop());
                                }
                            }
                        }

                        if (parameters.Length != cArg.Count)
                        {
                            throw new Exception($"Arity mismatch {func}, expected {parameters.Length}, given {cArg.Count} arguments");
                        }

                        a = func.DynamicInvoke(cArg.ToArray());
                        x = Operation.Return();
                        break;
                    }

                    if (a is Closure)
                    {
                        var func = a as Closure;
                        x = func.Body;
                        e = new EnviromentFrame(func.En);

                        if (rib != func.Argument.Length)
                        {
                            throw new Exception($"Arity mismatch, expected {func.Argument.Length}, given {rib} arguments");
                        }

                        foreach (var arg in func.Argument)
                        {
                            e.Define(arg, trueStack.Pop());
                        }

                        rib = 0;

                        break;
                    }

                    throw new Exception($"{a} is not a callable");
                }

                case Operation.Comand.Return: {
                    x   = trueStack.Pop() as Operation;
                    e   = trueStack.Pop() as EnviromentFrame;
                    rib = (int)trueStack.Pop();
                    break;
                }
                }
            }
        }