private void EvalInstruction() { if (instruction.Location != null) { currentLocation = instruction.Location; } switch (instruction.OperationCode) { case Opcode.Pop: { Pop(); break; } case Opcode.Dup: { IodineObject val = Pop(); Push(val); Push(val); break; } case Opcode.LoadConst: { Push(Top.Module.ConstantPool [instruction.Argument]); break; } case Opcode.LoadNull: { Push(IodineNull.Instance); break; } case Opcode.LoadSelf: { Push(Top.Self); break; } case Opcode.LoadTrue: { Push(IodineBool.True); break; } case Opcode.LoadException: { Push(lastException); break; } case Opcode.LoadFalse: { Push(IodineBool.False); break; } case Opcode.StoreLocal: { string name = ((IodineName)Top.Module.ConstantPool [instruction.Argument]).Value; Top.StoreLocal(name, Pop()); break; } case Opcode.LoadLocal: { string name = ((IodineName)Top.Module.ConstantPool [instruction.Argument]).Value; Push(Top.LoadLocal(name)); break; } case Opcode.StoreGlobal: { string name = ((IodineName)Top.Module.ConstantPool [instruction.Argument]).Value; Top.Module.SetAttribute(this, name, Pop()); break; } case Opcode.LoadGlobal: { string name = ((IodineName)Top.Module.ConstantPool [instruction.Argument]).Value; if (name == "_") { Push(Top.Module); } else if (Top.Module.Attributes.ContainsKey(name)) { Push(Top.Module.GetAttribute(this, name)); } else { RaiseException(new IodineAttributeNotFoundException(name)); } break; } case Opcode.StoreAttribute: { IodineObject target = Pop(); IodineObject value = Pop(); string attribute = ((IodineName)Top.Module.ConstantPool [instruction.Argument]).Value; if (target.Attributes.ContainsKey(attribute) && target.Attributes [attribute] is IIodineProperty) { IIodineProperty property = (IIodineProperty)target.Attributes [attribute]; property.Set(this, value); break; } target.SetAttribute(this, attribute, value); break; } case Opcode.LoadAttribute: { IodineObject target = Pop(); string attribute = ((IodineName)Top.Module.ConstantPool [instruction.Argument]).Value; if (target.Attributes.ContainsKey(attribute) && target.Attributes [attribute] is IIodineProperty) { IIodineProperty property = (IIodineProperty)target.Attributes [attribute]; Push(property.Get(this)); break; } Push(target.GetAttribute(this, attribute)); break; } case Opcode.LoadAttributeOrNull: { IodineObject target = Pop(); string attribute = ((IodineName)Top.Module.ConstantPool [instruction.Argument]).Value; if (target.Attributes.ContainsKey(attribute)) { Push(target.GetAttribute(this, attribute)); } else { Push(IodineNull.Instance); } break; } case Opcode.StoreIndex: { IodineObject index = Pop(); IodineObject target = Pop(); IodineObject value = Pop(); target.SetIndex(this, index, value); break; } case Opcode.LoadIndex: { IodineObject index = Pop(); IodineObject target = Pop(); Push(target.GetIndex(this, index)); break; } case Opcode.CastLocal: { IodineTypeDefinition type = Pop() as IodineTypeDefinition; string name = ((IodineName)Top.Module.ConstantPool [instruction.Argument]).Value; IodineObject o = Top.LoadLocal(name); if (type == null) { RaiseException(new IodineTypeException("TypeDef")); break; } if (o.InstanceOf(type)) { Push(o); } else { RaiseException(new IodineTypeException(type.Name)); } break; } case Opcode.BinOp: { IodineObject op2 = Pop(); IodineObject op1 = Pop(); Push(op1.PerformBinaryOperation(this, (BinaryOperation)instruction.Argument, op2 )); break; } case Opcode.UnaryOp: { Push(Pop().PerformUnaryOperation(this, (UnaryOperation)instruction.Argument)); break; } case Opcode.Invoke: { IodineObject target = Pop(); IodineObject[] arguments = new IodineObject[instruction.Argument]; for (int i = 1; i <= instruction.Argument; i++) { arguments [instruction.Argument - i] = Pop(); } Push(target.Invoke(this, arguments)); break; } case Opcode.InvokeVar: { IodineObject target = Pop(); List <IodineObject> arguments = new List <IodineObject> (); IodineTuple tuple = Pop() as IodineTuple; if (tuple == null) { RaiseException(new IodineTypeException("Tuple")); break; } for (int i = 0; i < instruction.Argument; i++) { arguments.Add(Pop()); } arguments.AddRange(tuple.Objects); Push(target.Invoke(this, arguments.ToArray())); break; } case Opcode.InvokeSuper: { IodineTypeDefinition target = Pop() as IodineTypeDefinition; IodineObject[] arguments = new IodineObject[instruction.Argument]; for (int i = 1; i <= instruction.Argument; i++) { arguments [instruction.Argument - i] = Pop(); } target.Inherit(this, Top.Self, arguments); break; } case Opcode.Return: { Top.InstructionPointer = int.MaxValue; break; } case Opcode.Yield: { Top.Yielded = true; break; } case Opcode.JumpIfTrue: { if (Pop().IsTrue()) { Top.InstructionPointer = instruction.Argument; } break; } case Opcode.JumpIfFalse: { if (!Pop().IsTrue()) { Top.InstructionPointer = instruction.Argument; } break; } case Opcode.Jump: { Top.InstructionPointer = instruction.Argument; break; } case Opcode.BuildClass: { IodineName name = Pop() as IodineName; IodineString doc = Pop() as IodineString; IodineMethod constructor = Pop() as IodineMethod; //CodeObject initializer = Pop as CodeObject; IodineTypeDefinition baseClass = Pop() as IodineTypeDefinition; IodineTuple interfaces = Pop() as IodineTuple; IodineClass clazz = new IodineClass(name.ToString(), new CodeObject(), constructor); if (baseClass != null) { clazz.BaseClass = baseClass; baseClass.BindAttributes(clazz); } for (int i = 0; i < instruction.Argument; i++) { IodineObject val = Pop(); IodineObject key = Pop(); clazz.Attributes [val.ToString()] = key; } foreach (IodineObject obj in interfaces.Objects) { IodineContract contract = obj as IodineContract; if (!contract.InstanceOf(clazz)) { //RaiseException (new IodineTypeException (contract.Name)); break; } } clazz.SetAttribute("__doc__", doc); Push(clazz); break; } case Opcode.BuildMixin: { IodineName name = Pop() as IodineName; IodineMixin mixin = new IodineMixin(name.ToString()); for (int i = 0; i < instruction.Argument; i++) { IodineObject val = Pop(); IodineObject key = Pop(); mixin.Attributes [val.ToString()] = key; } Push(mixin); break; } case Opcode.BuildEnum: { IodineName name = Pop() as IodineName; IodineEnum ienum = new IodineEnum(name.ToString()); for (int i = 0; i < instruction.Argument; i++) { IodineInteger val = Pop() as IodineInteger; IodineName key = Pop() as IodineName; ienum.AddItem(key.ToString(), (int)val.Value); } Push(ienum); break; } case Opcode.BuildContract: { IodineName name = Pop() as IodineName; IodineContract contract = new IodineContract(name.ToString()); for (int i = 0; i < instruction.Argument; i++) { IodineMethod val = Pop() as IodineMethod; contract.AddMethod(val); } Push(contract); break; } case Opcode.BuildTrait: { IodineName name = Pop() as IodineName; IodineTrait trait = new IodineTrait(name.ToString()); for (int i = 0; i < instruction.Argument; i++) { IodineMethod val = Pop() as IodineMethod; trait.AddMethod(val); } Push(trait); break; } case Opcode.BuildHash: { IodineDictionary hash = new IodineDictionary(); for (int i = 0; i < instruction.Argument; i++) { IodineObject val = Pop(); IodineObject key = Pop(); hash.Set(key, val); } Push(hash); break; } case Opcode.BuildList: { IodineObject[] items = new IodineObject[instruction.Argument]; for (int i = 1; i <= instruction.Argument; i++) { items [instruction.Argument - i] = Pop(); } Push(new IodineList(items)); break; } case Opcode.BuildTuple: { IodineObject[] items = new IodineObject[instruction.Argument]; for (int i = 1; i <= instruction.Argument; i++) { items [instruction.Argument - i] = Pop(); } Push(new IodineTuple(items)); break; } case Opcode.BuildClosure: { IodineObject obj = Pop(); IodineMethod method = obj as IodineMethod; Push(new IodineClosure(Top, method)); break; } case Opcode.BuildGenExpr: { CodeObject method = Pop() as CodeObject; Push(new IodineGeneratorExpr(Top, method)); break; } case Opcode.Slice: { IodineObject target = Pop(); IodineInteger[] arguments = new IodineInteger[3]; for (int i = 0; i < 3; i++) { IodineObject obj = Pop(); arguments [i] = obj as IodineInteger; if (obj != IodineNull.Instance && arguments [i] == null) { RaiseException(new IodineTypeException("Int")); break; } } IodineSlice slice = new IodineSlice(arguments [0], arguments [1], arguments [2]); Push(target.Slice(this, slice)); break; } case Opcode.MatchPattern: { IodineObject collection = Pop().GetIterator(this); IodineObject[] items = new IodineObject[instruction.Argument]; for (int i = 1; i <= instruction.Argument; i++) { items [instruction.Argument - i] = Pop(); } int index = 0; collection.IterReset(this); while (collection.IterMoveNext(this) && index < items.Length) { IodineObject o = collection.IterGetCurrent(this); if (items [index] is IodineTypeDefinition) { if (!o.InstanceOf(items [index] as IodineTypeDefinition)) { Push(IodineBool.False); break; } } else { if (!o.Equals(items [index])) { Push(IodineBool.False); break; } } index++; } Push(IodineBool.Create(index == items.Length)); break; } case Opcode.Unwrap: { IodineObject container = Pop(); IodineObject value = container.Unwrap(this); if (instruction.Argument > 0) { IodineInteger len = value.Len(this) as IodineInteger; if (len == null || len.Value != instruction.Argument) { Push(IodineBool.False); break; } } Push(value); Push(IodineBool.True); break; } case Opcode.Unpack: { IodineTuple tuple = Pop() as IodineTuple; if (tuple == null) { RaiseException(new IodineTypeException("Tuple")); break; } if (tuple.Objects.Length != instruction.Argument) { RaiseException(new IodineUnpackException(instruction.Argument)); break; } for (int i = tuple.Objects.Length - 1; i >= 0; i--) { Push(tuple.Objects [i]); } break; } case Opcode.GetIter: { Push(Pop().GetIterator(this)); break; } case Opcode.IterGetNext: { Push(Pop().IterGetCurrent(this)); break; } case Opcode.IterMoveNext: { Push(IodineBool.Create(Pop().IterMoveNext(this))); break; } case Opcode.IterReset: { Pop().IterReset(this); break; } case Opcode.PushExceptionHandler: { Top.ExceptionHandlers.Push(new IodineExceptionHandler(frameCount, instruction.Argument)); break; } case Opcode.PopExceptionHandler: { Top.ExceptionHandlers.Pop(); break; } case Opcode.InstanceOf: { IodineObject o = Pop(); IodineTypeDefinition type = Pop() as IodineTypeDefinition; if (type == null) { RaiseException(new IodineTypeException("TypeDef")); break; } Push(IodineBool.Create(o.InstanceOf(type))); break; } case Opcode.DynamicCast: { IodineObject o = Pop(); IodineTypeDefinition type = Pop() as IodineTypeDefinition; if (type == null) { RaiseException(new IodineTypeException("TypeDef")); break; } if (o.InstanceOf(type)) { Push(o); } else { Push(IodineNull.Instance); } break; } case Opcode.NullCoalesce: { IodineObject o1 = Pop(); IodineObject o2 = Pop(); if (o1 is IodineNull) { Push(o2); } else { Push(o1); } break; } case Opcode.BeginExcept: { bool rethrow = true; for (int i = 1; i <= instruction.Argument; i++) { IodineTypeDefinition type = Pop() as IodineTypeDefinition; if (type == null) { RaiseException(new IodineTypeException("TypeDef")); break; } if (lastException.InstanceOf(type)) { rethrow = false; break; } } if (rethrow) { RaiseException(lastException); } break; } case Opcode.Raise: { IodineObject e = Pop(); if (e.InstanceOf(IodineException.TypeDefinition)) { RaiseException(e); } else { RaiseException(new IodineTypeException("Exception")); } break; } case Opcode.SwitchLookup: { Dictionary <int, IodineObject> lookup = new Dictionary <int, IodineObject> (); int needle = Pop().GetHashCode(); for (int i = 0; i < instruction.Argument; i++) { IodineObject value = Pop(); IodineObject key = Pop(); lookup [key.GetHashCode()] = value; } if (lookup.ContainsKey(needle)) { lookup [needle].Invoke(this, new IodineObject[] { }); Push(IodineBool.True); } else { Push(IodineBool.False); } break; } case Opcode.BeginWith: { IodineObject obj = Pop(); obj.Enter(this); Top.DisposableObjects.Push(obj); break; } case Opcode.EndWith: { Top.DisposableObjects.Pop().Exit(this); break; } case Opcode.IncludeMixin: { IodineObject obj = Pop(); IodineObject type = Pop(); foreach (KeyValuePair <string, IodineObject> attr in obj.Attributes) { type.SetAttribute(attr.Key, attr.Value); } break; } case Opcode.ApplyMixin: { IodineObject type = Pop(); IodineMixin mixin = Top.Module.ConstantPool [instruction.Argument] as IodineMixin; foreach (KeyValuePair <string, IodineObject> attr in mixin.Attributes) { type.SetAttribute(attr.Key, attr.Value); } break; } case Opcode.BuildFunction: { MethodFlags flags = (MethodFlags)instruction.Argument; IodineString name = Pop() as IodineString; IodineString doc = Pop() as IodineString; CodeObject bytecode = Pop() as CodeObject; IodineTuple parameters = Pop() as IodineTuple; IodineObject[] defaultValues = new IodineObject[] { }; int defaultValuesStart = 0; if (flags.HasFlag(MethodFlags.HasDefaultParameters)) { IodineTuple defaultValuesTuple = Pop() as IodineTuple; IodineInteger startInt = Pop() as IodineInteger; defaultValues = defaultValuesTuple.Objects; defaultValuesStart = (int)startInt.Value; } IodineMethod method = new IodineMethod( Top.Module, name, bytecode, parameters, flags, defaultValues, defaultValuesStart ); method.SetAttribute("__doc__", doc); Push(method); break; } } }