Beispiel #1
0
 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);
     }
 }
Beispiel #2
0
        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);
        }