Пример #1
0
        private static void initMethodTable()
        {
            {
                Unit Clone(VM vm)
                {
                    TableUnit this_table = vm.GetTable(0);
                    Dictionary <Unit, Unit> table_copy = new Dictionary <Unit, Unit>();

                    foreach (KeyValuePair <Unit, Unit> entry in this_table.Map)
                    {
                        table_copy.Add(entry.Key, entry.Value);
                    }

                    TableUnit copy = new TableUnit(table_copy);

                    copy.ExtensionTable = this_table.ExtensionTable;

                    return(new Unit(copy));
                }

                methodTable.Set("clone", new IntrinsicUnit("table_clone", Clone, 1));

                //////////////////////////////////////////////////////
                Unit Count(VM vm)
                {
                    TableUnit this_table = vm.GetTable(0);
                    int       count      = this_table.Count;

                    return(new Unit(count));
                }

                methodTable.Set("count", new IntrinsicUnit("table_count", Count, 1));

                //////////////////////////////////////////////////////
                Unit Clear(VM vm)
                {
                    TableUnit this_table = vm.GetTable(0);

                    this_table.Map.Clear();
                    return(new Unit(UnitType.Null));
                }

                methodTable.Set("clear", new IntrinsicUnit("table_clear", Clear, 1));

                //////////////////////////////////////////////////////
                Unit ToString(VM vm)
                {
                    TableUnit this_table = vm.GetTable(0);
                    string    value      = "";
                    bool      first      = true;

                    foreach (KeyValuePair <Unit, Unit> entry in this_table.Map)
                    {
                        if (first)
                        {
                            value +=
                                System.Text.RegularExpressions.Regex.Unescape(entry.Key.ToString())
                                + " : " + System.Text.RegularExpressions.Regex.Unescape(entry.Value.ToString());
                            first = false;
                        }
                        else
                        {
                            value +=
                                ", "
                                + System.Text.RegularExpressions.Regex.Unescape(entry.Key.ToString())
                                + " : " + System.Text.RegularExpressions.Regex.Unescape(entry.Value.ToString());
                        }
                    }
                    return(new Unit(value));
                }

                methodTable.Set("to_string", new IntrinsicUnit("table_to_string", ToString, 1));

                //////////////////////////////////////////////////////
                Unit MakeIterator(VM vm)
                {
                    TableUnit this_table = vm.GetTable(0);

                    System.Collections.IDictionaryEnumerator enumerator = this_table.Map.GetEnumerator();

                    TableUnit iterator = new TableUnit(null);

                    iterator.Set("key", new Unit(UnitType.Null));
                    iterator.Set("value", new Unit(UnitType.Null));

                    Unit next(VM vm)
                    {
                        if (enumerator.MoveNext())
                        {
                            iterator.Set("key", (Unit)(enumerator.Key));
                            iterator.Set("value", (Unit)(enumerator.Value));
                            return(new Unit(true));
                        }
                        return(new Unit(false));
                    };

                    iterator.Set("next", new IntrinsicUnit("table_iterator_next", next, 0));
                    return(new Unit(iterator));
                }

                methodTable.Set("iterator", new IntrinsicUnit("table_iterator", MakeIterator, 1));

                //////////////////////////////////////////////////////
                Unit MakeNumericIterator(VM vm)
                {
                    TableUnit this_table = vm.GetTable(0);

                    System.Collections.IDictionaryEnumerator enumerator = this_table.Map.GetEnumerator();

                    TableUnit iterator = new TableUnit(null);

                    iterator.Set("key", new Unit(UnitType.Null));
                    iterator.Set("value", new Unit(UnitType.Null));

                    Unit next(VM vm)
                    {
                        while (true)
                        {
                            if (enumerator.MoveNext())
                            {
                                if (Unit.IsNumeric((Unit)enumerator.Key))
                                {
                                    iterator.Set("key", (Unit)(enumerator.Key));
                                    iterator.Set("value", (Unit)(enumerator.Value));
                                    return(new Unit(true));
                                }
                            }
                            else
                            {
                                return(new Unit(false));
                            }
                        }
                    };

                    iterator.Set("next", new IntrinsicUnit("table_iterator_next", next, 0));
                    return(new Unit(iterator));
                }

                methodTable.Set("numeric_iterator", new IntrinsicUnit("table_numeric_iterator", MakeNumericIterator, 1));

                //////////////////////////////////////////////////////
                Unit Indexes(VM vm)
                {
                    TableUnit this_table = vm.GetTable(0);
                    ListUnit  indexes    = new ListUnit(null);

                    foreach (Unit v in this_table.Map.Keys)
                    {
                        indexes.Elements.Add(v);
                    }

                    return(new Unit(indexes));
                }

                methodTable.Set("indexes", new IntrinsicUnit("table_indexes", Indexes, 1));

                //////////////////////////////////////////////////////
                Unit NumericIndexes(VM vm)
                {
                    TableUnit this_table = vm.GetTable(0);
                    ListUnit  indexes    = new ListUnit(null);

                    foreach (Unit v in this_table.Map.Keys)
                    {
                        if (Unit.IsNumeric(v))
                        {
                            indexes.Elements.Add(v);
                        }
                    }

                    return(new Unit(indexes));
                }

                methodTable.Set("numeric_indexes", new IntrinsicUnit("table_numeric_indexes", NumericIndexes, 1));

                //////////////////////////////////////////////////////
                Unit SetExtensionTable(VM vm)
                {
                    Unit      this_unit       = vm.GetUnit(0);
                    TableUnit extension_table = vm.GetTable(1);

                    if (extension_table.GetExtensionTable() != null)
                    {
                        throw new Exception("Extension Table has an Extention Table!");
                    }
                    if (this_unit.heapUnitValue.GetExtensionTable() != null)
                    {
                        throw new Exception("Table already has an Extention Table!");
                    }

                    this_unit.heapUnitValue.SetExtensionTable(extension_table);

                    return(new Unit(UnitType.Null));
                }

                methodTable.Set("set_extension_table", new IntrinsicUnit("table_set_extension_table", SetExtensionTable, 2));

                //////////////////////////////////////////////////////
                Unit UnsetExtensionTable(VM vm)
                {
                    Unit this_unit = vm.GetUnit(0);

                    this_unit.heapUnitValue.UnsetExtensionTable();

                    return(new Unit(UnitType.Null));
                }

                methodTable.Set("unset_extension_table", new IntrinsicUnit("table_unset_extension_table", UnsetExtensionTable, 1));

                //////////////////////////////////////////////////////
                Unit GetExtensionTable(VM vm)
                {
                    Unit      this_unit       = vm.GetUnit(0);
                    TableUnit extension_table = this_unit.heapUnitValue.GetExtensionTable();

                    if (extension_table == null)
                    {
                        return(new Unit(UnitType.Null));
                    }

                    return(new Unit(extension_table));
                }

                methodTable.Set("get_extension_table", new IntrinsicUnit("table_get_extension_table", GetExtensionTable, 1));

                //////////////////////////////////////////////////////
                Unit Merge(VM vm)
                {
                    TableUnit this_table    = vm.GetTable(0);
                    TableUnit merging_table = vm.GetTable(1);

                    foreach (KeyValuePair <Unit, Unit> u in merging_table.Map)
                    {
                        if (!this_table.Map.ContainsKey(u.Key))
                        {
                            this_table.Map.Add(u.Key, u.Value);
                        }
                    }
                    return(new Unit(UnitType.Null));
                }

                methodTable.Set("merge", new IntrinsicUnit("merge", Merge, 2));
            }
        }
Пример #2
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)));
                }
            }
        }
Пример #3
0
 public override void SetExtensionTable(TableUnit p_ExtensionTable)
 {
     ExtensionTable = p_ExtensionTable;
 }
Пример #4
0
 public WrapperUnit(object p_content, TableUnit p_ExtentionTable = null)
 {
     content        = p_content;
     ExtensionTable = p_ExtentionTable;
 }
Пример #5
0
 public virtual void SetExtensionTable(TableUnit p_ExtensionTable)
 {
     throw new Exception("Trying to set a Extension Table of a " + Type);
 }
Пример #6
0
 public override void SetExtensionTable(TableUnit p_ExtensionTable)
 {
     methodTable.ExtensionTable = p_ExtensionTable;
 }
Пример #7
0
        private static void initMethodTable()
        {
            {
                //////////////////////////////////////////////////////
                Unit Clone(VM vm)
                {
                    ListUnit    this_list         = vm.GetList(0);
                    List <Unit> new_list_elements = new List <Unit>();

                    foreach (Unit v in this_list.Elements)
                    {
                        new_list_elements.Add(v);
                    }
                    ListUnit new_list = new ListUnit(new_list_elements);

                    new_list.MethodTable = this_list.MethodTable;

                    return(new Unit(new_list));
                }

                methodTable.Set("clone", new IntrinsicUnit("list_clone", Clone, 1));

                //////////////////////////////////////////////////////
                Unit Count(VM vm)
                {
                    ListUnit this_list = vm.GetList(0);
                    int      count     = this_list.Count;

                    return(new Unit(count));
                }

                methodTable.Set("count", new IntrinsicUnit("list_count", Count, 1));

                //////////////////////////////////////////////////////
                Unit Clear(VM vm)
                {
                    ListUnit this_list = vm.GetList(0);

                    this_list.Elements.Clear();
                    return(new Unit(UnitType.Null));
                }

                methodTable.Set("clear", new IntrinsicUnit("list_clear", Clear, 1));

                //////////////////////////////////////////////////////
                Unit ToString(VM vm)
                {
                    ListUnit this_list = vm.GetList(0);
                    bool     first     = true;
                    string   value     = "";

                    foreach (Unit v in this_list.Elements)
                    {
                        if (first)
                        {
                            value += System.Text.RegularExpressions.Regex.Unescape(v.ToString());
                            first  = false;
                        }
                        else
                        {
                            value += ", " + System.Text.RegularExpressions.Regex.Unescape(v.ToString());
                        }
                    }
                    return(new Unit(value));
                }

                methodTable.Set("to_string", new IntrinsicUnit("list_to_string", ToString, 1));

                //////////////////////////////////////////////////////
                Unit MakeIndexesIterator(VM vm)
                {
                    ListUnit this_list = vm.GetList(0);
                    int      i         = -1;

                    TableUnit iterator = new TableUnit(null);

                    Unit next(VM vm)
                    {
                        if (i < (this_list.Count - 1))
                        {
                            i++;
                            iterator.Set("key", i);
                            iterator.Set("value", this_list.Elements[i]);
                            return(new Unit(true));
                        }
                        return(new Unit(false));
                    };
                    iterator.Set("next", new IntrinsicUnit("list_index_iterator_next", next, 0));
                    return(new Unit(iterator));
                }

                methodTable.Set("index_iterator", new IntrinsicUnit("list_index_iterator", MakeIndexesIterator, 1));

                //////////////////////////////////////////////////////
                Unit MakeIterator(VM vm)
                {
                    ListUnit this_list = vm.GetList(0);
                    int      i         = -1;
                    Unit     value     = new Unit(UnitType.Null);

                    TableUnit iterator = new TableUnit(null);

                    Unit next(VM vm)
                    {
                        if (i < (this_list.Count - 1))
                        {
                            i++;
                            iterator.Set("value", this_list.Elements[i]);
                            return(new Unit(true));
                        }
                        return(new Unit(false));
                    };
                    iterator.Set("next", new IntrinsicUnit("list_iterator_next", next, 0));
                    return(new Unit(iterator));
                }

                methodTable.Set("iterator", new IntrinsicUnit("list_iterator", MakeIterator, 1));

                //////////////////////////////////////////////////////
                Unit Init(VM vm)
                {
                    ListUnit this_list = vm.GetList(0);
                    Integer  new_end   = vm.GetInteger(1);
                    int      size      = this_list.Count;

                    for (int i = size; i < new_end; i++)
                    {
                        this_list.Elements.Add(new Unit(UnitType.Null));
                    }

                    return(new Unit(UnitType.Null));
                }

                methodTable.Set("init", new IntrinsicUnit("list_init", Init, 2));

                //////////////////////////////////////////////////////
                Unit Push(VM vm)
                {
                    ListUnit this_list = vm.GetList(0);
                    Unit     value     = vm.GetUnit(1);

                    this_list.Elements.Add(value);

                    return(new Unit(UnitType.Null));
                }

                methodTable.Set("push", new IntrinsicUnit("list_push", Push, 2));

                //////////////////////////////////////////////////////
                Unit Pop(VM vm)
                {
                    ListUnit this_list = vm.GetList(0);
                    Float    value     = this_list.Elements[^ 1].floatValue;