public void Set(Symbol ident, dynamic value) { if (Variables.ContainsKey(ident.Name)) { Variables[ident.Name] = value; return; } if (Parent == null) { throw new Exception($"Undefined \"{ident.Name}\""); } Parent.Set(ident, value); }
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; } } } }