Пример #1
0
        private string Stringify(double token, DataType type, HashLookup <string> debugSymbols)
        {
            switch (type)
            {
            case DataType.Invalid: return("");

            case DataType.NoValue: return("");

            case DataType.VariableRef:
                var rref = NanTags.DecodeVariableRef(token);
                if (debugSymbols?.ContainsKey(rref) == true)
                {
                    return("'" + debugSymbols[rref] + "' (" + rref.ToString("X") + ")");
                }
                return(rref.ToString("X"));

            case DataType.Opcode:
                NanTags.DecodeLongOpCode(token, out var ccls, out var cact, out var refr);
                if (ccls == 'm')
                {
                    if (debugSymbols?.ContainsKey(refr) == true)
                    {
                        return(ccls + "" + cact + " '" + debugSymbols[refr] + "' (" + refr.ToString("X") + ")");
                    }
                }
                if (ccls == 'i')
                {
                    if (debugSymbols?.ContainsKey(refr) == true)
                    {
                        return("Incr " + ((sbyte)cact) + " '" + debugSymbols[refr] + "' (" + refr.ToString("X") + ")");
                    }
                }
                NanTags.DecodeOpCode(token, out _, out _, out var p1, out var p2);
                return(ccls + "" + cact + " (" + p1 + ", " + p2 + ")");

            case DataType.ValSmallString:
                return("[" + NanTags.DecodeShortStr(token) + "]");

            case DataType.PtrHashtable:
            case DataType.PtrGrid:
            case DataType.PtrSet:
            case DataType.PtrVector:
            case DataType.PtrString:
            case DataType.PtrStaticString:
                NanTags.DecodePointer(token, out var targ, out _);
                return(" -> " + targ);

            case DataType.ValInt32: return(NanTags.DecodeInt32(token).ToString());

            case DataType.ValUInt32: return(NanTags.DecodeUInt32(token).ToString());

            case DataType.Number:  return(token.ToString(CultureInfo.InvariantCulture));

            default:
                throw new ArgumentOutOfRangeException(nameof(type), type, null);
            }
        }
Пример #2
0
        public void opcodes_survive_a_round_trip()
        {
            double enc1 = NanTags.EncodeOpcode('c', 'j', 123, 0); // control, jump, 123, <unused>
            double enc2 = NanTags.EncodeOpcode('f', 'd', 3, 40);  // function, define, 3 params, 40 opcodes

            Assert.That(NanTags.TypeOf(enc1), Is.EqualTo(DataType.Opcode));
            Assert.That(NanTags.TypeOf(enc2), Is.EqualTo(DataType.Opcode));

            NanTags.DecodeOpCode(enc1, out var codeClass, out var codeAction, out var p1, out var p2);
            Assert.That(codeClass, Is.EqualTo('c'));
            Assert.That(codeAction, Is.EqualTo('j'));
            Assert.That(p1, Is.EqualTo(123));
            Assert.That(p2, Is.EqualTo(0));

            NanTags.DecodeOpCode(enc2, out codeClass, out codeAction, out p1, out p2);
            Assert.That(codeClass, Is.EqualTo('f'));
            Assert.That(codeAction, Is.EqualTo('d'));
            Assert.That(p1, Is.EqualTo(3));
            Assert.That(p2, Is.EqualTo(40));
        }
Пример #3
0
        /// <summary>
        /// Main loop.
        /// Good default for all the flags is `false`
        /// </summary>
        /// <param name="resetVars">If true, all scopes are DELETED before running</param>
        /// <param name="traceExecution">If true, console output of state is written</param>
        /// <param name="singleStep">If true, the interpreter will run a single step, then return. Internal `eval` statements will run to completion</param>
        public ExecutionResult Execute(bool resetVars, bool traceExecution, bool singleStep)
        {
            double evalResult;

            _runningVerbose = traceExecution;

            if (resetVars)
            {
                _memory.Variables.Clear();
            }

            while (_position < program.Count)
            {
                _stepsTaken++;
                //if (stepsTaken > 1000) throw new Exception("trap");

                // Prevent stackoverflow.
                // Ex: if(true 1 10 20)
                if ((_stepsTaken & 127) == 0 && _valueStack.Count > 100)
                {
                    var oldValues = _valueStack.ToArray();
                    _valueStack = new Stack <double>(oldValues.Skip(oldValues.Length - 100));
                }

                double word = program[_position];

                if (traceExecution)
                {
                    _output.WriteLine("          stack :" + string.Join(", ", _valueStack.ToArray().Select(t => _memory.DiagnosticString(t, DebugSymbols))));
                    _output.WriteLine("          #" + _stepsTaken + "; p=" + _position
                                      + "; w=" + _memory.DiagnosticString(word, DebugSymbols));
                }

                var type = NanTags.TypeOf(word);
                switch (type)
                {
                case DataType.Invalid:
                    throw new Exception("Unknown code point at " + _position);

                case DataType.Opcode:
                    // decode opcode and do stuff
                    NanTags.DecodeOpCode(word, out var codeClass, out var codeAction, out var p1, out var p2);
                    ProcessOpCode(codeClass, codeAction, p1, p2, ref _position, _valueStack, _returnStack, word);
                    break;

                default:
                    _valueStack.Push(word);     // these could be raw doubles, encoded real values, or references/pointers
                    break;
                }


                _position++;
                if (singleStep)
                {
                    return new ExecutionResult {
                               State = ExecutionState.Paused, Result = NanTags.EncodeNonValue(NonValueType.Not_a_Result)
                    }
                }
                ;
            }

            if (_valueStack.Count != 0)
            {
                evalResult = _valueStack.Pop();
            }
            else
            {
                evalResult = NanTags.EncodeNonValue(NonValueType.Void);
            }

            _valueStack.Clear();

            return(new ExecutionResult {
                State = ExecutionState.Complete, Result = evalResult
            });
        }