Example #1
0
        private int DisassembleConstant(string name, GearsChunk chunk, int offset, EGearsOpCode constantType, Action <string> writeLine)
        {
            int constantIndex = (chunk.ReadCode(ref offset) << 8) + chunk.ReadCode(ref offset);

            switch (constantType)
            {
            case OP_LOAD_CONSTANT: {
                GearsValue value = chunk.ReadConstantValue(constantIndex);
                writeLine($"{name} const[{constantIndex}] ({value})");
            }
            break;

            case OP_LOAD_STRING: {
                string value = chunk.Strings.ReadStringConstant(constantIndex);
                writeLine($"{name} string[{constantIndex}] ({value})");
            }
            break;

            case OP_LOAD_FUNCTION: {
                string value = chunk.ReadConstantValueAsBitStr(constantIndex);
                writeLine($"{name} bitstr[{constantIndex}] ({value})");
            }
            break;
            }
            return(offset);
        }
Example #2
0
        private int DisassembleTwoParams(string name, GearsChunk chunk, int offset, Action <string> writeLine)
        {
            int index = (chunk.ReadCode(ref offset) << 8) + chunk.ReadCode(ref offset);

            writeLine($"{name} ({index})");
            return(offset);
        }
Example #3
0
 public GearsObjFunction(GearsChunk chunk, int arity, int upvalueCount, int ip = 0)
 {
     Chunk    = chunk;
     Arity    = arity;
     IP       = ip;
     Upvalues = new GearsObjUpvalue[upvalueCount];
 }
Example #4
0
        /// <summary>
        /// Reset the VM. Heap, globals, and stack are cleared.
        /// Then the VM is run once, unless firstRun == false
        /// </summary>
        internal Gears Reset(GearsChunk chunk, bool firstRun)
        {
            Chunk = chunk;
            _SP   = 0;
            for (int i = 0; i < _Stack.Length; i++)
            {
                _Stack[i] = 0;
            }
            _FrameCount = 0;
            for (int i = 0; i < _Frames.Length; i++)
            {
                _Frames[i] = null;
            }
            for (int i = 0; i < _Heap.Length; i++)
            {
                _Heap[i] = null;
            }
            Globals.Reset();
            _GrayList.Clear();
            GearsObjFunction closure = new GearsObjFunction(Chunk, 0, 0, 0);

            PushFrame(new GearsCallFrame(closure));
            Push(GearsValue.CreateObjPtr(HeapAddObject(closure)));
            AddNativeFunctionToGlobals("clock", 0, NativeFnClock);
            AddNativeFunctionToGlobals("print", 1, NativeFnPrint);
            if (firstRun)
            {
                Run();
            }
            return(this);
        }
Example #5
0
 private static void DoFixups(GearsChunk chunk, int origin, Func <GearsValue, int> makeConstant, Func <string, int> makeConstant2, List <LoxCompiler> fns)
 {
     foreach (LoxCompiler fn in fns)
     {
         int codeBase = chunk.SizeCode;
         chunk.WriteCode(fn._Chunk._Code, fn._Chunk._Lines, fn._Chunk.SizeCode);
         chunk.WriteCodeAt(origin + fn._OriginAddress, (byte)(codeBase >> 8));
         chunk.WriteCodeAt(origin + fn._OriginAddress + 1, (byte)(codeBase & 0xff));
         foreach (LoxCompilerFixup fixup in fn._FixupConstants)
         {
             GearsValue value         = fn._Chunk.ReadConstantValue(fixup.Value);
             int        constantFixup = makeConstant(value); // as fixup
             chunk.WriteCodeAt(codeBase + fixup.Address, (byte)(constantFixup >> 8));
             chunk.WriteCodeAt(codeBase + fixup.Address + 1, (byte)(constantFixup & 0xff));
         }
         foreach (LoxCompilerFixup fixup in fn._FixupStrings)
         {
             string value         = fn._Chunk.Strings.ReadStringConstant(fixup.Value);
             int    constantFixup = makeConstant2(value); // as fixup
             chunk.WriteCodeAt(codeBase + fixup.Address, (byte)(constantFixup >> 8));
             chunk.WriteCodeAt(codeBase + fixup.Address + 1, (byte)(constantFixup & 0xff));
         }
         DoFixups(chunk, codeBase, makeConstant, makeConstant2, fn._FixupFns);
         chunk.Compress();
     }
 }
Example #6
0
        private int DisassembleInvoke(string name, GearsChunk chunk, int offset, Action <string> writeLine)
        {
            int    args      = chunk.ReadCode(ref offset);
            int    nameIndex = (chunk.ReadCode(ref offset) << 8) + chunk.ReadCode(ref offset);
            string value     = chunk.ReadConstantValueAsBitStr(nameIndex);

            writeLine($"{name} const[{nameIndex}] ({value})");
            return(offset);
        }
Example #7
0
    internal partial class Gears { // disassembly
        // === Disassembly ===========================================================================================
        // ===========================================================================================================

        public void Disassemble(GearsChunk chunk, Action <string> write, Action <string> writeLine)
        {
            writeLine($"=== chunk ===");
            int offset = 0;

            while (offset < chunk.SizeCode)
            {
                offset = Disassemble(chunk, offset, write, writeLine);
            }
        }
Example #8
0
        private int DisassembleFunction(string name, GearsChunk chunk, int offset, Action <string> writeLine)
        {
            int argCount     = chunk.ReadCode(ref offset);
            int fnAddress    = (chunk.ReadCode(ref offset) << 8) + chunk.ReadCode(ref offset);
            int upvalueCount = chunk.ReadCode(ref offset);

            writeLine($"{name} ({argCount} arguments, {upvalueCount} upvalues) @{fnAddress:D4}");
            for (int i = 0; i < upvalueCount; i++)
            {
                chunk.ReadCode(ref offset); // local?
                chunk.ReadCode(ref offset); // index
            }
            return(offset);
        }
Example #9
0
 private LoxCompiler(TokenList tokens, ELoxFunctionType type, string name, LoxCompiler enclosing, LoxCompilerClass enclosingClass)
     : base(tokens, name)
 {
     _FunctionType      = type;
     Arity              = 0;
     _Chunk             = new GearsChunk(name);
     _Rules             = new List <Rule>();
     _EnclosingCompiler = enclosing;
     _CurrentClass      = enclosingClass;
     // stack slot zero is used for 'this' reference in methods, and is empty for script/functions:
     if (type != ELoxFunctionType.TYPE_FUNCTION)
     {
         _LocalVarData[_LocalCount++] = new LoxCompilerLocal("this", 0);
     }
     else
     {
         _LocalVarData[_LocalCount++] = new LoxCompilerLocal(string.Empty, 0);
     }
 }
Example #10
0
        /// <summary>
        /// Attempts to compile the passed source, tokenizing first.
        /// If compilation is successful, compiler.Chunk will be set.
        /// If compilation fails, status will be the error message.
        /// </summary>
        public static bool TryCompileFromPath(string path, out GearsChunk chunk, out string status)
        {
            chunk = null;
            string source;

            if (!File.Exists(path))
            {
                status = $"LoxCompiler: File '{path}' does not exist.";
                return(false);
            }
            try {
                source = File.ReadAllText(path);
            }
            catch (Exception e) {
                status = $"LoxCompiler: Could not read '{path}': {e.Message}";
                return(false);
            }
            return(TryCompileFromSource(path, source, out chunk, out status));
        }
Example #11
0
 /// <summary>
 /// Attempts to compile the passed source, tokenizing first.
 /// If compilation is successful, compiler.Chunk will be set.
 /// If compilation fails, status will be the error message.
 /// </summary>
 public static bool TryCompileFromSource(string path, string source, out GearsChunk chunk, out string status)
 {
     try {
         TokenList   tokens   = new LoxTokenizer(path, source).ScanTokens();
         LoxCompiler compiler = new LoxCompiler(tokens, ELoxFunctionType.TYPE_SCRIPT, path, null, null);
         if (compiler.Compile())
         {
             chunk  = compiler._Chunk;
             status = null;
             return(true);
         }
         status = $"LoxCompiler: uncaught error while compiling {path}.";
         chunk  = null;
         return(false);
     }
     catch (CompilerException e) {
         chunk  = null;
         status = $"LoxCompiler at {e.TargetSite.DeclaringType.Name}.{e.TargetSite.Name} {path} {e}";
         return(false);
     }
 }
Example #12
0
        private int Disassemble(GearsChunk chunk, int offset, Action <string> write, Action <string> writeLine)
        {
            write($"{chunk._Lines[offset]:D4}  {offset:D4}  ");
            EGearsOpCode instruction = (EGearsOpCode)chunk.ReadCode(ref offset);

            switch (instruction)
            {
            case OP_LOAD_CONSTANT:
                return(DisassembleConstant("OP_LOAD_CONSTANT", chunk, offset, OP_LOAD_CONSTANT, writeLine));

            case OP_LOAD_STRING:
                return(DisassembleConstant("OP_LOAD_STRING", chunk, offset, OP_LOAD_STRING, writeLine));

            case OP_LOAD_FUNCTION:
                return(DisassembleFunction("OP_LOAD_FUNCTION", chunk, offset, writeLine));

            case OP_NIL:
                return(DisassembleSimple("OP_NIL", chunk, offset, writeLine));

            case OP_TRUE:
                return(DisassembleSimple("OP_TRUE", chunk, offset, writeLine));

            case OP_FALSE:
                return(DisassembleSimple("OP_FALSE", chunk, offset, writeLine));

            case OP_POP:
                return(DisassembleSimple("OP_POP", chunk, offset, writeLine));

            case OP_GET_LOCAL:
                return(DisassembleTwoParams("OP_GET_LOCAL", chunk, offset, writeLine));

            case OP_SET_LOCAL:
                return(DisassembleTwoParams("OP_SET_LOCAL", chunk, offset, writeLine));

            case OP_DEFINE_GLOBAL:
                return(DisassembleConstant("OP_DEF_GLOBAL", chunk, offset, OP_LOAD_FUNCTION, writeLine));

            case OP_GET_GLOBAL:
                return(DisassembleConstant("OP_GET_GLOBAL", chunk, offset, OP_LOAD_FUNCTION, writeLine));

            case OP_SET_GLOBAL:
                return(DisassembleConstant("OP_SET_GLOBAL", chunk, offset, OP_LOAD_FUNCTION, writeLine));

            case OP_GET_UPVALUE:
                return(DisassembleTwoParams("OP_GET_UPVALUE", chunk, offset, writeLine));

            case OP_SET_UPVALUE:
                return(DisassembleTwoParams("OP_SET_UPVALUE", chunk, offset, writeLine));

            case OP_GET_PROPERTY:
                return(DisassembleConstant("OP_GET_PROPERTY", chunk, offset, OP_LOAD_FUNCTION, writeLine));

            case OP_SET_PROPERTY:
                return(DisassembleConstant("OP_SET_PROPERTY", chunk, offset, OP_LOAD_FUNCTION, writeLine));

            case OP_GET_SUPER:
                return(DisassembleConstant("OP_GET_SUPER", chunk, offset, OP_LOAD_FUNCTION, writeLine));

            case OP_EQUAL:
                return(DisassembleSimple("OP_EQUAL", chunk, offset, writeLine));

            case OP_GREATER:
                return(DisassembleSimple("OP_GREATER", chunk, offset, writeLine));

            case OP_LESS:
                return(DisassembleSimple("OP_LESS", chunk, offset, writeLine));

            case OP_ADD:
                return(DisassembleSimple("OP_ADD", chunk, offset, writeLine));

            case OP_SUBTRACT:
                return(DisassembleSimple("OP_SUBTRACT", chunk, offset, writeLine));

            case OP_MULTIPLY:
                return(DisassembleSimple("OP_MULTIPLY", chunk, offset, writeLine));

            case OP_DIVIDE:
                return(DisassembleSimple("OP_DIVIDE", chunk, offset, writeLine));

            case OP_NOT:
                return(DisassembleSimple("OP_NOT", chunk, offset, writeLine));

            case OP_NEGATE:
                return(DisassembleSimple("OP_NEGATE", chunk, offset, writeLine));

            case OP_JUMP:
                return(DisassembleTwoParams("OP_JUMP", chunk, offset, writeLine));

            case OP_JUMP_IF_FALSE:
                return(DisassembleTwoParams("OP_JUMP_IF_FALSE", chunk, offset, writeLine));

            case OP_LOOP:
                return(DisassembleTwoParams("OP_LOOP", chunk, offset, writeLine));

            case OP_CALL:
                return(DisassembleOneParam("OP_CALL", chunk, offset, writeLine));

            case OP_INVOKE:
                return(DisassembleInvoke("OP_INVOKE", chunk, offset, writeLine));

            case OP_SUPER_INVOKE:
                return(DisassembleInvoke("OP_SUPER_INVOKE", chunk, offset, writeLine));

            case OP_CLOSE_UPVALUE:
                return(DisassembleSimple("OP_CLOSE_UPVALUE", chunk, offset, writeLine));

            case OP_RETURN:
                return(DisassembleSimple("OP_RETURN", chunk, offset, writeLine));

            case OP_CLASS:
                return(DisassembleConstant("OP_CLASS", chunk, offset, OP_LOAD_FUNCTION, writeLine));

            case OP_INHERIT:
                return(DisassembleSimple("OP_INHERIT", chunk, offset, writeLine));

            case OP_METHOD:
                return(DisassembleSimple("OP_METHOD", chunk, offset, writeLine));

            default:
                writeLine($"Unknown opcode {instruction}");
                return(offset);
            }
        }
Example #13
0
 private int DisassembleSimple(string name, GearsChunk chunk, int offset, Action <string> writeLine)
 {
     writeLine(name);
     return(offset);
 }