Exemple #1
0
        public VM(Chunk p_chunk)
        {
            IP         = 0;
            parallelVM = false;

            main = p_chunk.MainFunctionUnit("main");

            instructions = new InstructionStack(callStackSize, main, out instructionsCache);

            stack = new Stack(callStackSize);

            variables          = new Memory <Unit>();
            upValues           = new Memory <UpValueUnit>();
            registeredUpValues = new UpValueEnv(variables);

            data       = p_chunk.GetData;
            Prelude    = p_chunk.Prelude;
            globals    = new Memory <Unit>();
            Intrinsics = p_chunk.Prelude.intrinsics;
            foreach (IntrinsicUnit v in Intrinsics)
            {
                // lock(globals) // not needed because this vm initialization does not run in parallel
                globals.Add(new Unit(v));
            }
            foreach (KeyValuePair <string, TableUnit> entry in p_chunk.Prelude.tables)
            {
                // lock(globals) // not needed because this vm initialization does not run in parallel
                globals.Add(new Unit(entry.Value));
            }
            LoadedModules = new Dictionary <string, int>();
            modules       = new List <ModuleUnit>();

            vmPool = new Stack <VM>();
        }
Exemple #2
0
        public FunctionUnit MainFunctionUnit(string p_name)
        {
            FunctionUnit this_function_unit = new FunctionUnit(p_name, ModuleName);

            this_function_unit.Set(0, Body, ChunkPosition, 0);
            return(this_function_unit);
        }
Exemple #3
0
        public override bool Equals(object p_other)
        {
            Type other_type = p_other.GetType();

            if (other_type == typeof(Unit))
            {
                if (((Unit)p_other).Type == UnitType.Function)
                {
                    FunctionUnit other_val_func = (FunctionUnit)((Unit)(p_other)).heapUnitValue;
                    if (other_val_func.Name == this.Name && other_val_func.Module == this.Module)
                    {
                        return(true);
                    }
                }
            }
            if (other_type == typeof(FunctionUnit))
            {
                FunctionUnit other_val_func = p_other as FunctionUnit;
                if (other_val_func.Name == this.Name && other_val_func.Module == this.Module)
                {
                    return(true);
                }
            }
            return(false);
        }
Exemple #4
0
        private VM(
            FunctionUnit p_main,
            List <Unit> p_data,
            Memory <Unit> p_globals,
            Library p_Prelude,
            Dictionary <string, int> p_LoadedModules,
            List <ModuleUnit> p_modules,
            Stack <VM> p_vmPool,
            bool p_parallelVM)
        {
            main          = p_main;
            data          = p_data;
            globals       = p_globals;
            Prelude       = p_Prelude;
            LoadedModules = p_LoadedModules;
            modules       = p_modules;
            vmPool        = p_vmPool;

            IP         = 0;
            parallelVM = p_parallelVM;

            instructions       = new InstructionStack(callStackSize, main, out instructionsCache);
            stack              = new Stack(callStackSize);
            variables          = new Memory <Unit>();
            upValues           = new Memory <UpValueUnit>();
            registeredUpValues = new UpValueEnv(variables);
        }
Exemple #5
0
        public void PushFunction(FunctionUnit p_function, int p_env, out List <Instruction> p_instructionsCache)
        {
            currentInstructionsIndex++;

            funCallEnv[currentInstructionsIndex] = p_env;
            functions[currentInstructionsIndex]  = p_function;

            p_instructionsCache = ExecutingInstructions;
        }
Exemple #6
0
        public Unit CallFunction(Unit p_callable, List <Unit> p_args = null)
        {
            UnitType this_type = p_callable.Type;

            if (p_args != null)
            {
                for (int i = p_args.Count - 1; i >= 0; i--)
                {
                    stack.Push(p_args[i]);
                }
            }

            Operand before_call_IP = IP;

            if (this_type == UnitType.Function)
            {
                instructions.PushRET((Operand)(main.Body.Count - 1));
                FunctionUnit this_func = (FunctionUnit)(p_callable.heapUnitValue);
                instructions.PushFunction(this_func, Env, out instructionsCache);

                IP = 0;
            }
            else if (this_type == UnitType.Closure)
            {
                instructions.PushRET((Operand)(main.Body.Count - 1));
                ClosureUnit this_closure = (ClosureUnit)(p_callable.heapUnitValue);

                upValues.PushEnv();


                foreach (UpValueUnit u in this_closure.UpValues)
                {
                    upValues.Add(u);
                }
                instructions.PushFunction(this_closure.Function, Env, out instructionsCache);

                IP = 0;
            }
            else if (this_type == UnitType.Intrinsic)
            {
                IntrinsicUnit this_intrinsic   = (IntrinsicUnit)(p_callable.heapUnitValue);
                Unit          intrinsic_result = this_intrinsic.Function(this);
                stack.top -= this_intrinsic.Arity;
                return(intrinsic_result);
            }

            VMResult result = Run();

            IP = before_call_IP;
            if (result.status == VMResultType.OK)
            {
                return(result.value);
            }
            return(new Unit(UnitType.Null));
        }
Exemple #7
0
        public InstructionStack(int p_callStackSize, FunctionUnit p_main, out List <Instruction> p_instructionsCache)
        {
            functions     = new FunctionUnit[p_callStackSize];
            returnAddress = new Operand[2 * p_callStackSize];
            funCallEnv    = new int[p_callStackSize];

            returnAddressTop         = 0;
            currentInstructionsIndex = 0;

            PushRET((Operand)(p_main.Body.Count - 1));
            functions[currentInstructionsIndex] = p_main;

            p_instructionsCache = ExecutingInstructions;
        }
Exemple #8
0
        private VMResult Run()
        {
            Instruction instruction;

            while (true)
            {
                instruction = instructionsCache[IP];

                switch (instruction.opCode)
                {
                case OpCode.POP:
                    IP++;
                    stack.Pop();
                    break;

                case OpCode.DUP:
                    IP++;
                    stack.Push(stack.Peek());
                    break;

                case OpCode.LOAD_DATA:
                    IP++;
                    stack.Push(data[instruction.opA]);
                    break;

                case OpCode.LOAD_VARIABLE:
                    IP++;
                    stack.Push(variables.GetAt(instruction.opA, CalculateEnvShift(instruction.opB)));
                    break;

                case OpCode.LOAD_GLOBAL:
                    IP++;
                    if (parallelVM == true)
                    {
                        lock (globals.Get(instruction.opA).heapUnitValue)    // needed because global may be loaded from parallel functions
                            stack.Push(globals.Get(instruction.opA));
                    }
                    else
                    {
                        stack.Push(globals.Get(instruction.opA));
                    }
                    break;

                case OpCode.LOAD_IMPORTED_GLOBAL:
                    IP++;
                    stack.Push(modules[instruction.opB].GetGlobal(instruction.opA));
                    break;

                case OpCode.LOAD_IMPORTED_DATA:
                    IP++;
                    stack.Push(modules[instruction.opB].GetData(instruction.opA));
                    break;

                case OpCode.LOAD_UPVALUE:
                    IP++;
                    if (parallelVM == true)
                    {
                        lock (upValues.GetAt(instruction.opA))    // needed because upvalue may be loaded from parallel functions
                            stack.Push(upValues.GetAt(instruction.opA).UpValue);
                    }
                    else
                    {
                        stack.Push(upValues.GetAt(instruction.opA).UpValue);
                    }
                    break;

                case OpCode.LOAD_NIL:
                    IP++;
                    stack.Push(new Unit(UnitType.Null));
                    break;

                case OpCode.LOAD_TRUE:
                    IP++;
                    stack.Push(new Unit(true));
                    break;

                case OpCode.LOAD_FALSE:
                    IP++;
                    stack.Push(new Unit(false));
                    break;

                case OpCode.LOAD_INTRINSIC:
                    IP++;
                    stack.Push(new Unit(Intrinsics[instruction.opA]));
                    break;

                case OpCode.DECLARE_VARIABLE:
                    IP++;
                    variables.Add(stack.Pop());
                    break;

                case OpCode.DECLARE_GLOBAL:
                    IP++;
                    // lock(globals) // not needed because global declaration can not happen inside parallel functions
                    globals.Add(stack.Pop());
                    break;

                case OpCode.DECLARE_FUNCTION:
                {
                    IP++;
                    Operand env = instruction.opA;
                    Operand is_function_expression = instruction.opB;
                    Operand new_fun_address        = instruction.opC;
                    Unit    this_callable          = data[new_fun_address];
                    if (this_callable.Type == UnitType.Function)
                    {
                        if (is_function_expression == 0)
                        {
                            if (env == 0)        // Global
                            {
                                // lock(globals) // not needed because global declaration can not happen inside parallel functions
                                globals.Add(this_callable);
                            }
                            else
                            {
                                variables.Add(this_callable);
                            }
                        }
                        else
                        {
                            stack.Push(this_callable);
                        }
                    }
                    else
                    {
                        ClosureUnit this_closure = (ClosureUnit)(this_callable.heapUnitValue);

                        // new upvalues
                        List <UpValueUnit> new_upValues = new List <UpValueUnit>();
                        foreach (UpValueUnit u in this_closure.UpValues)
                        {
                            // here we convert env from shift based to absolute based
                            UpValueUnit new_upvalue = registeredUpValues.Get(u.Address, CalculateEnvShiftUpVal(u.Env));
                            new_upValues.Add(new_upvalue);
                        }
                        ClosureUnit new_closure = new ClosureUnit(this_closure.Function, new_upValues);

                        Unit new_closure_unit = new Unit(new_closure);
                        if (is_function_expression == 0)
                        {
                            if (env == 0)        // yes they exist!
                            {
                                // lock(globals) // not needed because global declaration can not happen inside parallel functions
                                globals.Add(new_closure_unit);
                            }
                            else
                            {
                                variables.Add(new_closure_unit);
                            }
                        }
                        else
                        {
                            stack.Push(new_closure_unit);
                        }
                    }
                    break;
                }

                case OpCode.ASSIGN_VARIABLE:
                {
                    IP++;

                    Unit old_value = variables.GetAt(instruction.opA, CalculateEnvShift(instruction.opB));
                    Unit result;
                    switch (instruction.opC)
                    {
                    case ASSIGN:
                        variables.SetAt(stack.Peek(), instruction.opA, CalculateEnvShift(instruction.opB));
                        break;

                    case ADDITION_ASSIGN:
                        result = old_value + stack.Peek();
                        variables.SetAt(result, instruction.opA, CalculateEnvShift(instruction.opB));
                        break;

                    case SUBTRACTION_ASSIGN:
                        result = old_value - stack.Peek();
                        variables.SetAt(result, instruction.opA, CalculateEnvShift(instruction.opB));
                        break;

                    case MULTIPLICATION_ASSIGN:
                        result = old_value * stack.Peek();
                        variables.SetAt(result, instruction.opA, CalculateEnvShift(instruction.opB));
                        break;

                    case DIVISION_ASSIGN:
                        result = old_value / stack.Peek();
                        variables.SetAt(result, instruction.opA, CalculateEnvShift(instruction.opB));
                        break;

                    default:
                        throw new Exception("Unknown operator");
                    }
                    break;
                }

                case OpCode.ASSIGN_GLOBAL:
                {
                    IP++;
                    Operand address   = instruction.opA;
                    Operand op        = instruction.opB;
                    Unit    new_value = stack.Peek();
                    if (parallelVM == true)
                    {
                        switch (op)
                        {
                        case ASSIGN:
                            lock (globals.Get(address).heapUnitValue)
                                globals.Set(new_value, address);
                            break;

                        case ADDITION_ASSIGN:
                            lock (globals.Get(address).heapUnitValue){
                                Unit result = globals.Get(address) + new_value;
                                globals.Set(result, address);
                            }
                            break;

                        case SUBTRACTION_ASSIGN:
                            lock (globals.Get(address).heapUnitValue){
                                Unit result = globals.Get(address) - new_value;
                                globals.Set(result, address);
                            }
                            break;

                        case MULTIPLICATION_ASSIGN:
                            lock (globals.Get(address).heapUnitValue){
                                Unit result = globals.Get(address) * new_value;
                                globals.Set(result, address);
                            }
                            break;

                        case DIVISION_ASSIGN:
                            lock (globals.Get(address).heapUnitValue){
                                Unit result = globals.Get(address) / new_value;
                                globals.Set(result, address);
                            }
                            break;

                        default:
                            throw new Exception("Unknown operator");
                        }
                    }
                    else
                    {
                        Unit result;
                        switch (op)
                        {
                        case ASSIGN:
                            globals.Set(new_value, address);
                            break;

                        case ADDITION_ASSIGN:
                            result = globals.Get(address) + new_value;
                            globals.Set(result, address);
                            break;

                        case SUBTRACTION_ASSIGN:
                            result = globals.Get(address) - new_value;
                            globals.Set(result, address);
                            break;

                        case MULTIPLICATION_ASSIGN:
                            result = globals.Get(address) * new_value;
                            globals.Set(result, address);
                            break;

                        case DIVISION_ASSIGN:
                            result = globals.Get(address) / new_value;
                            globals.Set(result, address);
                            break;

                        default:
                            throw new Exception("Unknown operator");
                        }
                    }
                    break;
                }

                case OpCode.ASSIGN_IMPORTED_GLOBAL:
                    IP++;
                    modules[instruction.opB].SetOpGlobal(stack.Peek(), instruction.opC, instruction.opA);
                    break;

                case OpCode.ASSIGN_UPVALUE:
                    IP++;
                    if (parallelVM == true)
                    {
                        UpValueUnit this_upValue;
                        this_upValue = upValues.GetAt(instruction.opA);
                        switch (instruction.opB)
                        {
                        case ASSIGN:
                            lock (this_upValue)
                                this_upValue.UpValue = stack.Peek();
                            break;

                        case ADDITION_ASSIGN:
                            lock (this_upValue)
                                this_upValue.UpValue = upValues.GetAt(instruction.opA).UpValue + stack.Peek();
                            break;

                        case SUBTRACTION_ASSIGN:
                            lock (this_upValue)
                                this_upValue.UpValue = upValues.GetAt(instruction.opA).UpValue - stack.Peek();
                            break;

                        case MULTIPLICATION_ASSIGN:
                            lock (this_upValue)
                                this_upValue.UpValue = upValues.GetAt(instruction.opA).UpValue *stack.Peek();
                            break;

                        case DIVISION_ASSIGN:
                            lock (this_upValue)
                                this_upValue.UpValue = upValues.GetAt(instruction.opA).UpValue / stack.Peek();
                            break;

                        default:
                            throw new Exception("Unknown operator");
                        }
                    }
                    else
                    {
                        UpValueUnit this_upValue = upValues.GetAt(instruction.opA);
                        switch (instruction.opB)
                        {
                        case ASSIGN:
                            this_upValue.UpValue = stack.Peek();
                            break;

                        case ADDITION_ASSIGN:
                            this_upValue.UpValue = this_upValue.UpValue + stack.Peek();
                            break;

                        case SUBTRACTION_ASSIGN:
                            this_upValue.UpValue = this_upValue.UpValue - stack.Peek();
                            break;

                        case MULTIPLICATION_ASSIGN:
                            this_upValue.UpValue = this_upValue.UpValue * stack.Peek();
                            break;

                        case DIVISION_ASSIGN:
                            this_upValue.UpValue = this_upValue.UpValue / stack.Peek();
                            break;

                        default:
                            throw new Exception("Unknown operator");
                        }
                    }
                    break;

                case OpCode.GET:
                {
                    IP++;
                    Operand indexes_counter = instruction.opA;

                    Unit[] indexes = new Unit[indexes_counter];
                    for (int i = indexes_counter - 1; i >= 0; i--)
                    {
                        indexes[i] = stack.Pop();
                    }

                    Unit value = stack.Pop();
                    foreach (Unit v in indexes)
                    {
                        value = (value.heapUnitValue).Get(v);
                    }
                    stack.Push(value);
                    break;
                }

                case OpCode.SET:
                {
                    IP++;
                    Operand indexes_counter = instruction.opA;
                    Operand op = instruction.opB;

                    Unit[] indexes = new Unit[indexes_counter];
                    for (int i = indexes_counter - 1; i >= 0; i--)
                    {
                        indexes[i] = stack.Pop();
                    }

                    Unit this_table = stack.Pop();

                    for (int i = 0; i < indexes_counter - 1; i++)
                    {
                        Unit v = indexes[i];
                        this_table = (this_table.heapUnitValue).Get(v);
                    }
                    Unit     new_value  = stack.Peek();
                    Unit     index      = indexes[indexes_counter - 1];
                    UnitType index_type = indexes[indexes_counter - 1].Type;
                    if (op == ASSIGN)
                    {
                        ((this_table.heapUnitValue)).Set(index, new_value);
                    }
                    else if (parallelVM == true)
                    {
                        Unit old_value;
                        Unit result;
                        switch (op)
                        {
                        case ADDITION_ASSIGN:
                            lock (this_table.heapUnitValue){
                                old_value = ((TableUnit)(this_table.heapUnitValue)).Get(index);
                                result    = old_value + new_value;
                                (this_table.heapUnitValue).Set(index, result);
                            }
                            break;

                        case SUBTRACTION_ASSIGN:
                            lock (this_table.heapUnitValue){
                                old_value = ((TableUnit)(this_table.heapUnitValue)).Get(index);
                                result    = old_value - new_value;
                                (this_table.heapUnitValue).Set(index, result);
                            }
                            break;

                        case MULTIPLICATION_ASSIGN:
                            lock (this_table.heapUnitValue){
                                old_value = ((TableUnit)(this_table.heapUnitValue)).Get(index);
                                result    = old_value * new_value;
                                (this_table.heapUnitValue).Set(index, result);
                            }
                            break;

                        case DIVISION_ASSIGN:
                            lock (this_table.heapUnitValue){
                                old_value = ((TableUnit)(this_table.heapUnitValue)).Get(index);
                                result    = old_value / new_value;
                                (this_table.heapUnitValue).Set(index, result);
                            }
                            break;

                        default:
                            throw new Exception("Unknown operator");
                        }
                    }
                    else
                    {
                        Unit old_value = (this_table.heapUnitValue).Get(index);
                        Unit result;
                        switch (op)
                        {
                        case ADDITION_ASSIGN:
                            result = old_value + new_value;
                            break;

                        case SUBTRACTION_ASSIGN:
                            result = old_value - new_value;
                            break;

                        case MULTIPLICATION_ASSIGN:
                            result = old_value * new_value;
                            break;

                        case DIVISION_ASSIGN:
                            result = old_value / new_value;
                            break;

                        default:
                            throw new Exception("Unknown operator");
                        }
                        (this_table.heapUnitValue).Set(index, result);
                    }
                    break;
                }

                case OpCode.JUMP:
                    IP += instruction.opA;
                    break;

                case OpCode.JUMP_IF_NOT_TRUE:
                    if (stack.Pop().ToBool() == false)
                    {
                        IP += instruction.opA;
                    }
                    else
                    {
                        IP++;
                    }
                    break;

                case OpCode.JUMP_BACK:
                    IP -= instruction.opA;
                    break;

                case OpCode.OPEN_ENV:
                    IP++;
                    EnvPush();
                    break;

                case OpCode.CLOSE_ENV:
                    IP++;
                    EnvPop();
                    break;

                case OpCode.RETURN:
                    IP = instructions.PopRET();
                    break;

                case OpCode.RETURN_SET:
                    instructions.PushRET((Operand)(instruction.opA + IP));
                    IP++;
                    break;

                case OpCode.ADD:
                {
                    IP++;
                    Unit opB = stack.Pop();
                    stack.Push(stack.Pop() + opB);

                    break;
                }

                case OpCode.APPEND:
                {
                    IP++;
                    Unit   opB    = stack.Pop();
                    string result = stack.Pop().ToString() + opB.ToString();
                    stack.Push(new Unit(result));
                    break;
                }

                case OpCode.SUBTRACT:
                {
                    IP++;
                    Unit opB = stack.Pop();
                    stack.Push(stack.Pop() - opB);
                    break;
                }

                case OpCode.MULTIPLY:
                    IP++;
                    stack.Push(stack.Pop() * stack.Pop());
                    break;

                case OpCode.DIVIDE:
                {
                    IP++;
                    Unit opB = stack.Pop();
                    stack.Push(stack.Pop() / opB);
                    break;
                }

                case OpCode.NEGATE:
                    IP++;
                    stack.Push(-stack.Pop());
                    break;

                case OpCode.INCREMENT:
                    IP++;
                    stack.Push(stack.Pop() + 1);
                    break;

                case OpCode.DECREMENT:
                    IP++;
                    stack.Push(stack.Pop() - 1);
                    break;

                case OpCode.EQUALS:
                    IP++;
                    stack.Push(new Unit(stack.Pop().Equals(stack.Pop())));
                    break;

                case OpCode.NOT_EQUALS:
                    IP++;
                    stack.Push(new Unit(!stack.Pop().Equals(stack.Pop())));
                    break;

                case OpCode.GREATER_EQUALS:
                    IP++;
                    // the values are popped out of order from stack, so the logic is inverted!
                    stack.Push(new Unit(stack.Pop().floatValue <= stack.Pop().floatValue));
                    break;

                case OpCode.LESS_EQUALS:
                    IP++;
                    // the values are popped out of order from stack, so the logic is inverted!
                    stack.Push(new Unit(stack.Pop().floatValue >= stack.Pop().floatValue));
                    break;

                case OpCode.GREATER:
                    IP++;
                    // the values are popped out of order from stack, so the logic is inverted!
                    stack.Push(new Unit(stack.Pop().floatValue < stack.Pop().floatValue));
                    break;

                case OpCode.LESS:
                    IP++;
                    // the values are popped out of order from stack, so the logic is inverted!
                    stack.Push(new Unit(stack.Pop().floatValue > stack.Pop().floatValue));
                    break;

                case OpCode.NOT:
                    IP++;
                    stack.Push(new Unit(!stack.Pop().ToBool()));
                    break;

                case OpCode.AND:
                {
                    IP++;
                    Unit opB = stack.Pop();
                    stack.Push(new Unit(stack.Pop().ToBool() && opB.ToBool()));
                    break;
                }

                case OpCode.OR:
                {
                    IP++;
                    Unit opB = stack.Pop();
                    stack.Push(new Unit(stack.Pop().ToBool() || opB.ToBool()));
                    break;
                }

                case OpCode.XOR:
                {
                    IP++;
                    Unit opB = stack.Pop();
                    stack.Push(new Unit(stack.Pop().ToBool() ^ opB.ToBool()));
                    break;
                }

                case OpCode.NAND:
                {
                    IP++;
                    Unit opB = stack.Pop();
                    stack.Push(new Unit(!(stack.Pop().ToBool() && opB.ToBool())));
                    break;
                }

                case OpCode.NOR:
                {
                    IP++;
                    Unit opB = stack.Pop();
                    stack.Push(new Unit(!(stack.Pop().ToBool() || opB.ToBool())));
                    break;
                }

                case OpCode.XNOR:
                {
                    IP++;
                    Unit opB = stack.Pop();
                    stack.Push(new Unit(!(stack.Pop().ToBool() ^ opB.ToBool())));
                    break;
                }

                case OpCode.CLOSE_CLOSURE:
                    upValues.PopEnv();
                    EnvSet(instructions.TargetEnv);
                    IP = instructions.PopFunction(out instructionsCache);

                    break;

                case OpCode.CLOSE_FUNCTION:
                    EnvSet(instructions.TargetEnv);
                    IP = instructions.PopFunction(out instructionsCache);

                    break;

                case OpCode.NEW_TABLE:
                {
                    IP++;

                    TableUnit new_table = new TableUnit(null);

                    int n_table = instruction.opA;
                    for (int i = 0; i < n_table; i++)
                    {
                        Unit val = stack.Pop();
                        Unit key = stack.Pop();
                        new_table.Map.Add(key, val);
                    }

                    stack.Push(new Unit(new_table));
                    break;
                }

                case OpCode.NEW_LIST:
                {
                    IP++;

                    ListUnit new_list = new ListUnit(null);

                    int n_table = instruction.opA;
                    for (int i = 0; i < n_table; i++)
                    {
                        Unit val = stack.Pop();
                        new_list.Elements.Add(val);
                    }

                    stack.Push(new Unit(new_list));
                    break;
                }

                case OpCode.CALL:
                {
                    IP++;

                    Unit     this_callable = stack.Pop();
                    UnitType this_type     = this_callable.Type;

                    if (this_type == UnitType.Function)
                    {
                        FunctionUnit this_func = (FunctionUnit)this_callable.heapUnitValue;

                        instructions.PushRET(IP);
                        instructions.PushFunction(this_func, Env, out instructionsCache);

                        IP = 0;
                    }
                    else if (this_type == UnitType.Closure)
                    {
                        ClosureUnit this_closure = (ClosureUnit)this_callable.heapUnitValue;

                        upValues.PushEnv();

                        foreach (UpValueUnit u in this_closure.UpValues)
                        {
                            upValues.Add(u);
                        }

                        instructions.PushRET(IP);
                        instructions.PushFunction(this_closure.Function, Env, out instructionsCache);

                        IP = 0;
                    }
                    else if (this_type == UnitType.Intrinsic)
                    {
                        IntrinsicUnit this_intrinsic = (IntrinsicUnit)this_callable.heapUnitValue;
                        Unit          result         = this_intrinsic.Function(this);
                        stack.top -= this_intrinsic.Arity;
                        stack.Push(result);
                    }
                    else
                    {
                        Error("Trying to call a " + this_callable.Type);
                        return(new VMResult(VMResultType.OK, new Unit(UnitType.Null)));
                    }
                    break;
                }

                case OpCode.PUSH_STASH:
                    IP++;
                    stack.PushStash();
                    break;

                case OpCode.POP_STASH:
                    IP++;
                    stack.PopStash();
                    break;

                case OpCode.EXIT:
                    if (stack.top > 0)
                    {
                        return(new VMResult(VMResultType.OK, stack.Pop()));
                    }
                    return(new VMResult(VMResultType.OK, new Unit(UnitType.Null)));

                default:
                    Error("Unkown OpCode: " + instruction.opCode);
                    return(new VMResult(VMResultType.ERROR, new Unit(UnitType.Null)));
                }
            }
        }
Exemple #9
0
 public ClosureUnit(FunctionUnit p_Function, List <UpValueUnit> p_UpValues)
 {
     Function = p_Function;
     UpValues = p_UpValues;
 }
Exemple #10
0
        private void CompileFunction(string p_name, FunctionExpressionNode p_node, bool p_isGlobal)
        {
            FunctionUnit new_function = new FunctionUnit(p_name, moduleName);
            Operand      this_address = (Operand)AddData(new_function);

            if (p_node.Type != NodeType.FUNCTION_DECLARATION)
            {
                Add(OpCode.DECLARE_FUNCTION, 0, 1, this_address, p_node.PositionData);
            }
            else
            {
                if (p_isGlobal)
                {
                    Add(OpCode.DECLARE_FUNCTION, 0, 0, this_address, p_node.PositionData);// zero for gloabal
                }
                else
                {
                    Add(OpCode.DECLARE_FUNCTION, 1, 0, this_address, p_node.PositionData);// one for current env
                }
            }

            // body
            int function_start = instructionCounter;

            // env
            env.Add(new List <string>());
            Add(OpCode.OPEN_ENV, p_node.PositionData);
            //Add funStartEnv
            funStartEnv.Push(env.Count - 1);

            int exit_instruction_address = instructionCounter;

            Add(OpCode.RETURN_SET, 0, p_node.PositionData);

            Operand arity = 0;

            if (p_node.Parameters != null)
            {
                foreach (string p in p_node.Parameters)
                {
                    SetVar(p);// it is always local
                    Add(OpCode.DECLARE_VARIABLE, p_node.PositionData);
                    arity++;
                }
            }

            upvalueStack.Push(new List <Variable>());
            foreach (Node n in p_node.Body)
            {
                ChunkIt(n);
            }

            bool is_closure = false;

            if (upvalueStack.Peek().Count != 0)
            {
                is_closure = true;
                List <Variable>    this_variables = upvalueStack.Pop();
                List <UpValueUnit> new_upvalues   = new List <UpValueUnit>();
                foreach (Variable v in this_variables)
                {
                    new_upvalues.Add(new UpValueUnit((Operand)v.address, (Operand)v.envIndex));
                }
                ClosureUnit new_closure = new ClosureUnit(new_function, new_upvalues);
                chunk.SwapDataLiteral(this_address, new Unit(new_closure));
            }
            else
            {
                upvalueStack.Pop();
            }

            // fix the exit address
            chunk.FixInstruction(exit_instruction_address, null, (Operand)(instructionCounter - exit_instruction_address), null, null);

            if (is_closure == true)
            {
                Add(OpCode.CLOSE_CLOSURE, p_node.PositionData);
            }
            else
            {
                Add(OpCode.CLOSE_FUNCTION, p_node.PositionData);
            }

            new_function.Set(
                arity,
                chunk.Slice(function_start, instructionCounter),
                chunk.ChunkPosition.Slice(function_start, instructionCounter),
                (Operand)function_start);
            instructionCounter = function_start;

            //Console.WriteLine("Removed env");
            env.RemoveAt(env.Count - 1);

            //pop fun start env
            funStartEnv.Pop();
        }
Exemple #11
0
 private int AddData(FunctionUnit p_function)
 {
     dataLiterals.Add(p_function);
     chunk.AddData(new Unit(p_function));
     return(dataLiterals.Count - 1);
 }