public override HassiumObject Invoke(VirtualMachine vm, SourceLocation location, params HassiumObject[] args) { if (BoundAttributes.ContainsKey("new")) { return(BoundAttributes["new"].Invoke(vm, location, args).AddType(TypeDefinition)); } else if (BoundAttributes.ContainsKey(INVOKE)) { return(BoundAttributes[INVOKE].Invoke(vm, location, args).AddType(TypeDefinition)); } else { foreach (var inherit in Inherits) { var inheritClazz = vm.ExecuteMethod(inherit); if (inheritClazz is HassiumTypeDefinition) { foreach (var attrib in inheritClazz.BoundAttributes) { BoundAttributes.Add(attrib.Key, (attrib.Value.Clone() as HassiumObject).SetSelfReference(this)); } } else { foreach (var attrib in HassiumMethod.CloneDictionary(vm.ExecuteMethod(inherit).GetAttributes())) { if (!BoundAttributes.ContainsKey(attrib.Key)) { attrib.Value.Parent = this; BoundAttributes.Add(attrib.Key, attrib.Value); } } } } if (BoundAttributes.ContainsKey("new")) { return(Invoke(vm, location, args).AddType(TypeDefinition)); } vm.RaiseException(HassiumAttribNotFoundException.AttribNotFoundExceptionTypeDef._new(vm, null, location, this, new HassiumString(INVOKE))); return(Null); } }
public HassiumObject ExecuteMethod(HassiumMethod method) { //System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch int count = method.Instructions.Count; for (int pos = 0; pos < count; pos++) { try { //watch.Start(); if (ExceptionReturns.ContainsKey(method)) { pos = ExceptionReturns[method]; ExceptionReturns.Remove(method); } HassiumObject left, right, val, list; HassiumObject[] elements; string attrib; int arg; SourceLocation loc; inst = method.Instructions[pos]; //Console.WriteLine(inst.InstructionType + "\t" + inst.SourceLocation); switch (inst.InstructionType) { case InstructionType.BinaryOperation: right = Stack.Pop(); left = Stack.Pop(); interpretBinaryOperation(left, right, inst.Arg); break; case InstructionType.BuildClosure: Stack.Push(new HassiumClosure(Stack.Pop() as HassiumMethod, StackFrame.Frames.Peek())); break; case InstructionType.BuildDictionary: arg = inst.Arg; var initials = new Dictionary <HassiumObject, HassiumObject>(); for (int i = 0; i < arg; i++) { initials.Add(Stack.Pop(), Stack.Pop()); } Stack.Push(new HassiumDictionary(initials)); break; case InstructionType.BuildList: elements = new HassiumObject[inst.Arg]; for (int i = elements.Length - 1; i >= 0; i--) { elements[i] = Stack.Pop(); } Stack.Push(new HassiumList(elements)); break; case InstructionType.BuildThread: Stack.Push(new HassiumThread(this, inst.SourceLocation, inst.Object as HassiumMethod, StackFrame.Frames.Peek())); break; case InstructionType.BuildTuple: arg = inst.Arg; HassiumObject[] tupleElements = new HassiumObject[arg]; for (int i = arg - 1; i >= 0; i--) { tupleElements[i] = Stack.Pop(); } Stack.Push(new HassiumTuple(tupleElements)); break; case InstructionType.Call: val = Stack.Pop(); elements = new HassiumObject[inst.Arg]; for (int i = elements.Length - 1; i >= 0; i--) { elements[i] = Stack.Pop(); } Stack.Push(val.Invoke(this, inst.SourceLocation, elements)); break; case InstructionType.Duplicate: Stack.Push(Stack.Peek()); break; case InstructionType.EnforcedAssignment: loc = inst.SourceLocation; val = Stack.Pop(); HassiumObject type = inst.Object.Invoke(this, inst.SourceLocation); if (type is HassiumTrait) { if (!(type as HassiumTrait).Is(this, loc, val).Bool) { RaiseException(HassiumConversionFailedException.ConversionFailedExceptionTypeDef._new(this, null, loc, val, type)); } } else { type = type is HassiumTypeDefinition ? type : type.Type(); if (!val.Types.Contains(type as HassiumTypeDefinition)) { RaiseException(HassiumConversionFailedException.ConversionFailedExceptionTypeDef._new(this, null, loc, val, type)); } } arg = inst.Arg; if (StackFrame.Contains(arg)) { StackFrame.Modify(arg, val); } else { StackFrame.Add(arg, val); } Stack.Push(val); break; case InstructionType.EnterWith: val = StackFrame.GetVariable(inst.SourceLocation, this, inst.Arg); val.Enter(this, val, CurrentSourceLocation); break; case InstructionType.ExitWith: val = StackFrame.GetVariable(inst.SourceLocation, this, inst.Arg); val.Exit(this, val, CurrentSourceLocation); break; case InstructionType.Iter: val = Stack.Pop(); Stack.Push(val.Iter(this, val, inst.SourceLocation)); break; case InstructionType.IterableFull: val = Stack.Pop(); Stack.Push(val.IterableFull(this, val, inst.SourceLocation)); break; case InstructionType.IterableNext: val = Stack.Pop(); Stack.Push(val.IterableNext(this, val, inst.SourceLocation)); break; case InstructionType.Jump: pos = method.Labels[inst.Arg]; break; case InstructionType.JumpIfFalse: val = Stack.Pop(); if (!(val as HassiumBool).Bool) { pos = method.Labels[inst.Arg]; } break; case InstructionType.JumpIfTrue: val = Stack.Pop(); if ((val as HassiumBool).Bool) { pos = method.Labels[inst.Arg]; } break; case InstructionType.LoadAttribute: loc = inst.SourceLocation; val = Stack.Pop(); try { var attribute = val.GetAttribute(this, inst.Constant); if (attribute.IsPrivate) { RaiseException(HassiumPrivateAttribException.PrivateAttribExceptionTypeDef._new(this, null, loc, new HassiumString(inst.Constant), val)); return(HassiumObject.Null); } if (attribute is HassiumProperty) { Stack.Push((attribute as HassiumProperty).Get.Invoke(this, inst.SourceLocation)); } else { Stack.Push(attribute); } } catch (KeyNotFoundException) { RaiseException(HassiumAttribNotFoundException.AttribNotFoundExceptionTypeDef._new(this, null, loc, val, new HassiumString(inst.Constant))); } break; case InstructionType.LoadGlobal: loc = inst.SourceLocation; attrib = inst.Constant; if (Globals.ContainsKey(attrib)) { Stack.Push(Globals[attrib]); break; } if (method.Parent != null) { if (method.Parent.ContainsAttribute(attrib)) { Stack.Push(method.Parent.GetAttribute(this, attrib)); break; } } if (method.Module != null) { if (method.Module.ContainsAttribute(attrib)) { Stack.Push(method.Module.GetAttribute(this, attrib)); break; } } RaiseException(HassiumAttribNotFoundException.AttribNotFoundExceptionTypeDef._new(this, null, loc, CurrentModule, new HassiumString(attrib))); break; case InstructionType.LoadGlobalVariable: try { Stack.Push(CurrentModule.Globals[inst.Arg]); } catch (KeyNotFoundException) { RaiseException(HassiumAttribNotFoundException.AttribNotFoundExceptionTypeDef._new(this, null, inst.SourceLocation, CurrentModule, new HassiumString(inst.Arg.ToString()))); } break; case InstructionType.LoadIterableElement: list = Stack.Pop(); Stack.Push(list.Index(this, list, inst.SourceLocation, Stack.Pop())); break; case InstructionType.LoadLocal: /* if (GlobalFrame.ContainsVariable(arg)) * { * if (StackFrame.Contains(arg)) * Stack.Push(StackFrame.GetVariable(CurrentSourceLocation, this, arg)); * else * Stack.Push(GlobalFrame.GetVariable(arg)); * } * else*/ Stack.Push(StackFrame.GetVariable(inst.SourceLocation, this, inst.Arg)); break; case InstructionType.Pop: lastValuePopped = Stack.Pop(); break; case InstructionType.PopHandler: //Handlers.Pop(); break; case InstructionType.Push: Stack.Push(new HassiumInt(inst.Arg)); break; case InstructionType.PushConstant: Stack.Push(new HassiumString(inst.Constant)); break; case InstructionType.PushHandler: var handler = inst.Object as HassiumExceptionHandler; handler.Frame = StackFrame.Frames.Peek(); Handlers.Push(handler); break; case InstructionType.PushObject: Stack.Push(inst.Object); break; case InstructionType.Raise: RaiseException(Stack.Pop()); break; case InstructionType.Return: return(Stack.Pop()); case InstructionType.SelfReference: Stack.Push(method.Parent); break; case InstructionType.SetInitialAttribute: val = Stack.Pop(); attrib = val.ToString(this, val, inst.SourceLocation).String; val = Stack.Pop(); var obj = Stack.Peek(); if (obj.ContainsAttribute(attrib)) { obj.RemoveAttribute(attrib); } obj.AddAttribute(attrib, val); break; case InstructionType.StartThread: val = Stack.Pop(); HassiumThread.ThreadTypeDef.start(this, val, inst.SourceLocation); break; case InstructionType.StoreAttribute: val = Stack.Pop(); attrib = inst.Constant; if (val.IsPrivate) { RaiseException(HassiumAttribNotFoundException.AttribNotFoundExceptionTypeDef._new(this, null, inst.SourceLocation, new HassiumString(inst.Constant), Stack.Pop())); return(HassiumObject.Null); } if (val.ContainsAttribute(attrib)) { if (val.GetAttribute(this, attrib) is HassiumProperty) { if (((HassiumProperty)val.GetAttribute(this, attrib)).Set == null) { RaiseException(HassiumKeyNotFoundException.KeyNotFoundExceptionTypeDef._new(this, null, inst.SourceLocation, val, new HassiumString(string.Format("{0} { set; }", attrib)))); return(null); } ((HassiumProperty)val.GetAttribute(this, attrib)).Set.Invoke(this, inst.SourceLocation, Stack.Pop()); break; } else { val.RemoveAttribute(attrib); } } val.AddAttribute(attrib, Stack.Pop().SetSelfReference(val)); break; case InstructionType.StoreGlobal: val = Stack.Pop(); attrib = inst.Constant; if (Globals.ContainsKey(attrib)) { Globals.Remove(attrib); } Globals.Add(attrib, val); break; case InstructionType.StoreGlobalVariable: CurrentModule.Globals[inst.Arg] = Stack.Pop(); break; case InstructionType.StoreIterableElement: val = Stack.Pop(); Stack.Push(val.StoreIndex(this, val, inst.SourceLocation, Stack.Pop(), Stack.Pop())); break; case InstructionType.StoreLocal: arg = inst.Arg; val = Stack.Pop(); if (StackFrame.Contains(arg)) { StackFrame.Modify(arg, val); } else { StackFrame.Add(arg, val); } break; case InstructionType.Swap: loc = inst.SourceLocation; val = Stack.Pop(); arg = inst.Arg; int index = (int)val.ToInt(this, val, loc).Int; val = StackFrame.GetVariable(loc, this, index); StackFrame.Modify(index, StackFrame.GetVariable(loc, this, arg)); StackFrame.Modify(arg, val); Stack.Push(val); break; case InstructionType.UnaryOperation: interpretUnaryOperation(Stack.Pop(), inst.Arg); break; } //watch.Reset(); } catch (Exception ex) { if (ex is UnhandledException) { throw ex; } RaiseException(new HassiumString(ex.ToString())); } } return(lastValuePopped); }